reifydb_engine/evaluate/row/
mod.rs1use reifydb_core::{
5 Row,
6 interface::ColumnDef,
7 value::{
8 column::{Column, ColumnData, Columns},
9 container::NumberContainer,
10 encoded::EncodedValuesNamedLayout,
11 },
12};
13use reifydb_rql::expression::Expression;
14use reifydb_type::{Error, Fragment, Params, ROW_NUMBER_COLUMN_NAME, Type, Value, internal};
15
16use crate::evaluate::column::{StandardColumnEvaluator, cast};
17pub(crate) use crate::evaluate::{ColumnEvaluationContext, RowEvaluationContext};
18
19pub struct StandardRowEvaluator {
20 evaluator: StandardColumnEvaluator,
21}
22
23impl StandardRowEvaluator {
24 pub fn new() -> Self {
25 Self {
26 evaluator: StandardColumnEvaluator::default(),
27 }
28 }
29}
30
31impl Default for StandardRowEvaluator {
32 fn default() -> Self {
33 Self::new()
34 }
35}
36
37impl StandardRowEvaluator {
38 pub fn evaluate<'a>(&self, ctx: &RowEvaluationContext<'a>, expr: &Expression<'a>) -> crate::Result<Value> {
39 let mut columns = Vec::new();
40
41 let row_number_column = Column {
42 name: Fragment::owned_internal(ROW_NUMBER_COLUMN_NAME),
43 data: ColumnData::Uint8(NumberContainer::from_vec(vec![ctx.row.number.0])),
44 };
45 columns.push(row_number_column);
46
47 for (idx, field) in ctx.row.layout.fields.iter().enumerate() {
48 let value = ctx.row.layout.get_value(&ctx.row.encoded, idx);
49 debug_assert!(
52 field.r#type == value.get_type() || value.get_type() == reifydb_type::Type::Undefined,
53 "Type mismatch: field expects {:?}, got {:?}",
54 field.r#type,
55 value.get_type()
56 );
57
58 let column_type = if value.get_type() == reifydb_type::Type::Undefined {
61 field.r#type
62 } else {
63 value.get_type()
64 };
65 let mut data = if column_type == Type::Undefined {
66 ColumnData::undefined(0)
67 } else {
68 ColumnData::with_capacity(column_type, 1)
69 };
70 data.push_value(value);
71
72 let name = ctx.row.layout.get_name(idx).ok_or_else(|| {
73 Error(internal!("EncodedRowNamedLayout missing name for field at index {}", idx))
74 })?;
75
76 columns.push(Column {
77 name: Fragment::owned_internal(name),
78 data,
79 })
80 }
81
82 let ctx = ColumnEvaluationContext {
83 target: ctx.target.clone(),
84 columns: Columns::new(columns),
85 row_count: 1,
86 take: None,
87 params: ctx.params,
88 stack: &crate::stack::Stack::new(),
89 is_aggregate_context: false,
90 };
91
92 let result = self.evaluator.evaluate(&ctx, &expr)?;
93
94 Ok(result.data().get_value(0))
95 }
96}
97
98impl StandardRowEvaluator {
99 pub fn coerce(&self, row: &Row, target_columns: &[ColumnDef]) -> crate::Result<Row> {
100 let mut source_columns = Vec::new();
101
102 for (idx, field) in row.layout.fields.iter().enumerate() {
103 let value = row.layout.get_value(&row.encoded, idx);
104
105 let mut data = if field.r#type == Type::Undefined {
106 ColumnData::undefined(0)
107 } else {
108 ColumnData::with_capacity(field.r#type, 1)
109 };
110 data.push_value(value);
111
112 let name = row.layout.get_name(idx).ok_or_else(|| {
113 Error(internal!("EncodedRowNamedLayout missing name for field at index {}", idx))
114 })?;
115
116 source_columns.push(Column {
117 name: Fragment::owned_internal(name),
118 data,
119 });
120 }
121
122 let ctx = ColumnEvaluationContext {
123 target: None,
124 columns: Columns::new(source_columns),
125 row_count: 1,
126 take: None,
127 params: &Params::None,
128 stack: &crate::stack::Stack::new(),
129 is_aggregate_context: false,
130 };
131
132 let mut values = Vec::with_capacity(target_columns.len());
133 let mut names = Vec::with_capacity(target_columns.len());
134 let mut types = Vec::with_capacity(target_columns.len());
135
136 for target_col in target_columns.iter() {
137 let r#type = target_col.constraint.get_type();
138
139 let value = if let Some(source_column) = ctx.columns.column(&target_col.name) {
140 let lazy_frag = Fragment::owned_internal(&target_col.name);
141 let coerced = cast::cast_column_data(&ctx, source_column.data(), r#type, &lazy_frag)?;
142 coerced.get_value(0)
143 } else {
144 Value::Undefined
145 };
146 values.push(value);
147 names.push(target_col.name.clone());
148 types.push(r#type);
149 }
150
151 let layout = EncodedValuesNamedLayout::new(names.into_iter().zip(types.into_iter()));
152 let mut encoded = layout.allocate_row();
153 layout.set_values(&mut encoded, &values);
154
155 Ok(Row {
156 number: row.number,
157 encoded,
158 layout,
159 })
160 }
161}