1use std::slice::from_ref;
5
6use reifydb_core::value::column::{Column, data::ColumnData};
7use reifydb_rql::expression::Expression;
8use reifydb_type::{
9 error::{BinaryOp, Error, IntoDiagnostic, LogicalOp, OperandCategory, RuntimeErrorKind, TypeError},
10 fragment::Fragment,
11 value::{Value, r#type::Type},
12};
13
14use super::{
15 context::CompileContext,
16 option::{binary_op_unwrap_option, unary_op_unwrap_option},
17};
18use crate::{
19 Result,
20 error::CastError,
21 expression::{
22 access::access_lookup,
23 arith::{add::add_columns, div::div_columns, mul::mul_columns, rem::rem_columns, sub::sub_columns},
24 call::call_eval,
25 cast::cast_column_data,
26 compare::{Equal, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, NotEqual, compare_columns},
27 constant::{constant_value, constant_value_of},
28 context::EvalContext,
29 lookup::column_lookup,
30 parameter::parameter_lookup,
31 prefix::prefix_eval,
32 },
33 vm::stack::Variable,
34};
35
36pub struct CompiledExpr {
37 inner: CompiledExprInner,
38 access_column_name: Option<String>,
39}
40
41enum CompiledExprInner {
42 Single(Box<dyn Fn(&EvalContext) -> Result<Column> + Send + Sync>),
43 Multi(Box<dyn Fn(&EvalContext) -> Result<Vec<Column>> + Send + Sync>),
44}
45
46impl CompiledExpr {
47 pub fn new(f: impl Fn(&EvalContext) -> Result<Column> + Send + Sync + 'static) -> Self {
48 Self {
49 inner: CompiledExprInner::Single(Box::new(f)),
50 access_column_name: None,
51 }
52 }
53
54 pub fn new_multi(f: impl Fn(&EvalContext) -> Result<Vec<Column>> + Send + Sync + 'static) -> Self {
55 Self {
56 inner: CompiledExprInner::Multi(Box::new(f)),
57 access_column_name: None,
58 }
59 }
60
61 pub fn new_access(name: String, f: impl Fn(&EvalContext) -> Result<Column> + Send + Sync + 'static) -> Self {
62 Self {
63 inner: CompiledExprInner::Single(Box::new(f)),
64 access_column_name: Some(name),
65 }
66 }
67
68 pub fn access_column_name(&self) -> Option<&str> {
69 self.access_column_name.as_deref()
70 }
71
72 pub fn execute(&self, ctx: &EvalContext) -> Result<Column> {
73 match &self.inner {
74 CompiledExprInner::Single(f) => f(ctx),
75 CompiledExprInner::Multi(f) => {
76 let columns = f(ctx)?;
77 Ok(columns.into_iter().next().unwrap_or_else(|| Column {
78 name: Fragment::internal("none"),
79 data: ColumnData::with_capacity(Type::Option(Box::new(Type::Boolean)), 0),
80 }))
81 }
82 }
83 }
84
85 pub fn execute_multi(&self, ctx: &EvalContext) -> Result<Vec<Column>> {
86 match &self.inner {
87 CompiledExprInner::Single(f) => Ok(vec![f(ctx)?]),
88 CompiledExprInner::Multi(f) => f(ctx),
89 }
90 }
91}
92
93pub fn compile_expression(_ctx: &CompileContext, expr: &Expression) -> Result<CompiledExpr> {
97 Ok(match expr {
98 Expression::Constant(e) => {
99 let expr = e.clone();
100 CompiledExpr::new(move |ctx| {
101 let row_count = ctx.take.unwrap_or(ctx.row_count);
102 Ok(Column {
103 name: expr.full_fragment_owned(),
104 data: constant_value(&expr, row_count)?,
105 })
106 })
107 }
108
109 Expression::Column(e) => {
110 let expr = e.clone();
111 CompiledExpr::new(move |ctx| column_lookup(ctx, &expr))
112 }
113
114 Expression::Variable(e) => {
115 let expr = e.clone();
116 CompiledExpr::new(move |ctx| {
117 let variable_name = expr.name();
118
119 if variable_name == "env" {
120 return Err(TypeError::Runtime {
121 kind: RuntimeErrorKind::VariableIsDataframe {
122 name: variable_name.to_string(),
123 },
124 message: format!(
125 "Variable '{}' contains a dataframe and cannot be used directly in scalar expressions",
126 variable_name
127 ),
128 }
129 .into());
130 }
131
132 match ctx.symbol_table.get(variable_name) {
133 Some(Variable::Scalar(columns)) => {
134 let value = columns.scalar_value();
135 let mut data =
136 ColumnData::with_capacity(value.get_type(), ctx.row_count);
137 for _ in 0..ctx.row_count {
138 data.push_value(value.clone());
139 }
140 Ok(Column {
141 name: Fragment::internal(variable_name),
142 data,
143 })
144 }
145 Some(Variable::Columns(_))
146 | Some(Variable::ForIterator {
147 ..
148 })
149 | Some(Variable::Closure(_)) => {
150 return Err(TypeError::Runtime {
151 kind: RuntimeErrorKind::VariableIsDataframe {
152 name: variable_name.to_string(),
153 },
154 message: format!(
155 "Variable '{}' contains a dataframe and cannot be used directly in scalar expressions",
156 variable_name
157 ),
158 }
159 .into());
160 }
161 None => {
162 if let Some(value) = ctx.params.get_named(variable_name) {
164 let mut data = ColumnData::with_capacity(
165 value.get_type(),
166 ctx.row_count,
167 );
168 for _ in 0..ctx.row_count {
169 data.push_value(value.clone());
170 }
171 return Ok(Column {
172 name: Fragment::internal(variable_name),
173 data,
174 });
175 }
176 return Err(TypeError::Runtime {
177 kind: RuntimeErrorKind::VariableNotFound {
178 name: variable_name.to_string(),
179 },
180 message: format!("Variable '{}' is not defined", variable_name),
181 }
182 .into());
183 }
184 }
185 })
186 }
187
188 Expression::Parameter(e) => {
189 let expr = e.clone();
190 CompiledExpr::new(move |ctx| parameter_lookup(ctx, &expr))
191 }
192
193 Expression::Alias(e) => {
194 let inner = compile_expression(_ctx, &e.expression)?;
195 let alias = e.alias.0.clone();
196 CompiledExpr::new(move |ctx| {
197 let mut column = inner.execute(ctx)?;
198 column.name = alias.clone();
199 Ok(column)
200 })
201 }
202
203 Expression::Add(e) => {
204 let left = compile_expression(_ctx, &e.left)?;
205 let right = compile_expression(_ctx, &e.right)?;
206 let fragment = e.full_fragment_owned();
207 CompiledExpr::new(move |ctx| {
208 let l = left.execute(ctx)?;
209 let r = right.execute(ctx)?;
210 add_columns(ctx, &l, &r, || fragment.clone())
211 })
212 }
213
214 Expression::Sub(e) => {
215 let left = compile_expression(_ctx, &e.left)?;
216 let right = compile_expression(_ctx, &e.right)?;
217 let fragment = e.full_fragment_owned();
218 CompiledExpr::new(move |ctx| {
219 let l = left.execute(ctx)?;
220 let r = right.execute(ctx)?;
221 sub_columns(ctx, &l, &r, || fragment.clone())
222 })
223 }
224
225 Expression::Mul(e) => {
226 let left = compile_expression(_ctx, &e.left)?;
227 let right = compile_expression(_ctx, &e.right)?;
228 let fragment = e.full_fragment_owned();
229 CompiledExpr::new(move |ctx| {
230 let l = left.execute(ctx)?;
231 let r = right.execute(ctx)?;
232 mul_columns(ctx, &l, &r, || fragment.clone())
233 })
234 }
235
236 Expression::Div(e) => {
237 let left = compile_expression(_ctx, &e.left)?;
238 let right = compile_expression(_ctx, &e.right)?;
239 let fragment = e.full_fragment_owned();
240 CompiledExpr::new(move |ctx| {
241 let l = left.execute(ctx)?;
242 let r = right.execute(ctx)?;
243 div_columns(ctx, &l, &r, || fragment.clone())
244 })
245 }
246
247 Expression::Rem(e) => {
248 let left = compile_expression(_ctx, &e.left)?;
249 let right = compile_expression(_ctx, &e.right)?;
250 let fragment = e.full_fragment_owned();
251 CompiledExpr::new(move |ctx| {
252 let l = left.execute(ctx)?;
253 let r = right.execute(ctx)?;
254 rem_columns(ctx, &l, &r, || fragment.clone())
255 })
256 }
257
258 Expression::Equal(e) => {
259 let left = compile_expression(_ctx, &e.left)?;
260 let right = compile_expression(_ctx, &e.right)?;
261 let fragment = e.full_fragment_owned();
262 CompiledExpr::new(move |ctx| {
263 let l = left.execute(ctx)?;
264 let r = right.execute(ctx)?;
265 let result = compare_columns::<Equal>(&l, &r, fragment.clone(), |f, l, r| {
266 TypeError::BinaryOperatorNotApplicable {
267 operator: BinaryOp::Equal,
268 left: l,
269 right: r,
270 fragment: f,
271 }
272 .into_diagnostic()
273 });
274 result
275 })
276 }
277
278 Expression::NotEqual(e) => {
279 let left = compile_expression(_ctx, &e.left)?;
280 let right = compile_expression(_ctx, &e.right)?;
281 let fragment = e.full_fragment_owned();
282 CompiledExpr::new(move |ctx| {
283 let l = left.execute(ctx)?;
284 let r = right.execute(ctx)?;
285 let result = compare_columns::<NotEqual>(&l, &r, fragment.clone(), |f, l, r| {
286 TypeError::BinaryOperatorNotApplicable {
287 operator: BinaryOp::NotEqual,
288 left: l,
289 right: r,
290 fragment: f,
291 }
292 .into_diagnostic()
293 });
294 result
295 })
296 }
297
298 Expression::GreaterThan(e) => {
299 let left = compile_expression(_ctx, &e.left)?;
300 let right = compile_expression(_ctx, &e.right)?;
301 let fragment = e.full_fragment_owned();
302 CompiledExpr::new(move |ctx| {
303 let l = left.execute(ctx)?;
304 let r = right.execute(ctx)?;
305 let result = compare_columns::<GreaterThan>(&l, &r, fragment.clone(), |f, l, r| {
306 TypeError::BinaryOperatorNotApplicable {
307 operator: BinaryOp::GreaterThan,
308 left: l,
309 right: r,
310 fragment: f,
311 }
312 .into_diagnostic()
313 });
314 result
315 })
316 }
317
318 Expression::GreaterThanEqual(e) => {
319 let left = compile_expression(_ctx, &e.left)?;
320 let right = compile_expression(_ctx, &e.right)?;
321 let fragment = e.full_fragment_owned();
322 CompiledExpr::new(move |ctx| {
323 let l = left.execute(ctx)?;
324 let r = right.execute(ctx)?;
325 let result =
326 compare_columns::<GreaterThanEqual>(&l, &r, fragment.clone(), |f, l, r| {
327 TypeError::BinaryOperatorNotApplicable {
328 operator: BinaryOp::GreaterThanEqual,
329 left: l,
330 right: r,
331 fragment: f,
332 }
333 .into_diagnostic()
334 });
335 result
336 })
337 }
338
339 Expression::LessThan(e) => {
340 let left = compile_expression(_ctx, &e.left)?;
341 let right = compile_expression(_ctx, &e.right)?;
342 let fragment = e.full_fragment_owned();
343 CompiledExpr::new(move |ctx| {
344 let l = left.execute(ctx)?;
345 let r = right.execute(ctx)?;
346 let result = compare_columns::<LessThan>(&l, &r, fragment.clone(), |f, l, r| {
347 TypeError::BinaryOperatorNotApplicable {
348 operator: BinaryOp::LessThan,
349 left: l,
350 right: r,
351 fragment: f,
352 }
353 .into_diagnostic()
354 });
355 result
356 })
357 }
358
359 Expression::LessThanEqual(e) => {
360 let left = compile_expression(_ctx, &e.left)?;
361 let right = compile_expression(_ctx, &e.right)?;
362 let fragment = e.full_fragment_owned();
363 CompiledExpr::new(move |ctx| {
364 let l = left.execute(ctx)?;
365 let r = right.execute(ctx)?;
366 let result = compare_columns::<LessThanEqual>(&l, &r, fragment.clone(), |f, l, r| {
367 TypeError::BinaryOperatorNotApplicable {
368 operator: BinaryOp::LessThanEqual,
369 left: l,
370 right: r,
371 fragment: f,
372 }
373 .into_diagnostic()
374 });
375 result
376 })
377 }
378
379 Expression::And(e) => {
380 let left = compile_expression(_ctx, &e.left)?;
381 let right = compile_expression(_ctx, &e.right)?;
382 let fragment = e.full_fragment_owned();
383 CompiledExpr::new(move |ctx| {
384 let l = left.execute(ctx)?;
385 let r = right.execute(ctx)?;
386 let result = execute_and(&l, &r, &fragment);
387 result
388 })
389 }
390
391 Expression::Or(e) => {
392 let left = compile_expression(_ctx, &e.left)?;
393 let right = compile_expression(_ctx, &e.right)?;
394 let fragment = e.full_fragment_owned();
395 CompiledExpr::new(move |ctx| {
396 let l = left.execute(ctx)?;
397 let r = right.execute(ctx)?;
398 let result = execute_or(&l, &r, &fragment);
399 result
400 })
401 }
402
403 Expression::Xor(e) => {
404 let left = compile_expression(_ctx, &e.left)?;
405 let right = compile_expression(_ctx, &e.right)?;
406 let fragment = e.full_fragment_owned();
407 CompiledExpr::new(move |ctx| {
408 let l = left.execute(ctx)?;
409 let r = right.execute(ctx)?;
410 let result = execute_xor(&l, &r, &fragment);
411 result
412 })
413 }
414
415 Expression::Prefix(e) => {
416 let expr = e.clone();
417 CompiledExpr::new(move |ctx| prefix_eval(ctx, &expr, ctx.functions, ctx.clock))
418 }
419
420 Expression::Type(e) => {
421 let ty = e.ty.clone();
422 let fragment = e.fragment.clone();
423 CompiledExpr::new(move |ctx| {
424 let row_count = ctx.take.unwrap_or(ctx.row_count);
425 let values: Vec<Box<Value>> =
426 (0..row_count).map(|_| Box::new(Value::Type(ty.clone()))).collect();
427 Ok(Column::new(fragment.text(), ColumnData::any(values)))
428 })
429 }
430
431 Expression::AccessSource(e) => {
432 let col_name = e.column.name.text().to_string();
433 let expr = e.clone();
434 CompiledExpr::new_access(col_name, move |ctx| access_lookup(ctx, &expr))
435 }
436
437 Expression::Tuple(e) => {
438 if e.expressions.len() == 1 {
439 let inner = compile_expression(_ctx, &e.expressions[0])?;
440 CompiledExpr::new(move |ctx| inner.execute(ctx))
441 } else {
442 let compiled: Vec<CompiledExpr> = e
443 .expressions
444 .iter()
445 .map(|expr| compile_expression(_ctx, expr))
446 .collect::<Result<Vec<_>>>()?;
447 let fragment = e.fragment.clone();
448 CompiledExpr::new(move |ctx| {
449 let columns: Vec<Column> = compiled
450 .iter()
451 .map(|expr| expr.execute(ctx))
452 .collect::<Result<Vec<_>>>()?;
453
454 let len = columns.first().map_or(1, |c| c.data().len());
455 let mut data: Vec<Box<Value>> = Vec::with_capacity(len);
456
457 for i in 0..len {
458 let items: Vec<Value> =
459 columns.iter().map(|col| col.data().get_value(i)).collect();
460 data.push(Box::new(Value::Tuple(items)));
461 }
462
463 Ok(Column {
464 name: fragment.clone(),
465 data: ColumnData::any(data),
466 })
467 })
468 }
469 }
470
471 Expression::List(e) => {
472 let compiled: Vec<CompiledExpr> = e
473 .expressions
474 .iter()
475 .map(|expr| compile_expression(_ctx, expr))
476 .collect::<Result<Vec<_>>>()?;
477 let fragment = e.fragment.clone();
478 CompiledExpr::new(move |ctx| {
479 let columns: Vec<Column> =
480 compiled.iter().map(|expr| expr.execute(ctx)).collect::<Result<Vec<_>>>()?;
481
482 let len = columns.first().map_or(1, |c| c.data().len());
483 let mut data: Vec<Box<Value>> = Vec::with_capacity(len);
484
485 for i in 0..len {
486 let items: Vec<Value> =
487 columns.iter().map(|col| col.data().get_value(i)).collect();
488 data.push(Box::new(Value::List(items)));
489 }
490
491 Ok(Column {
492 name: fragment.clone(),
493 data: ColumnData::any(data),
494 })
495 })
496 }
497
498 Expression::Between(e) => {
499 let value = compile_expression(_ctx, &e.value)?;
500 let lower = compile_expression(_ctx, &e.lower)?;
501 let upper = compile_expression(_ctx, &e.upper)?;
502 let fragment = e.fragment.clone();
503 CompiledExpr::new(move |ctx| {
504 let value_col = value.execute(ctx)?;
505 let lower_col = lower.execute(ctx)?;
506 let upper_col = upper.execute(ctx)?;
507
508 let ge_result = compare_columns::<GreaterThanEqual>(
509 &value_col,
510 &lower_col,
511 fragment.clone(),
512 |f, l, r| {
513 TypeError::BinaryOperatorNotApplicable {
514 operator: BinaryOp::GreaterThanEqual,
515 left: l,
516 right: r,
517 fragment: f,
518 }
519 .into_diagnostic()
520 },
521 )?;
522 let le_result = compare_columns::<LessThanEqual>(
523 &value_col,
524 &upper_col,
525 fragment.clone(),
526 |f, l, r| {
527 TypeError::BinaryOperatorNotApplicable {
528 operator: BinaryOp::LessThanEqual,
529 left: l,
530 right: r,
531 fragment: f,
532 }
533 .into_diagnostic()
534 },
535 )?;
536
537 if !matches!(ge_result.data(), ColumnData::Bool(_))
538 || !matches!(le_result.data(), ColumnData::Bool(_))
539 {
540 return Err(TypeError::BinaryOperatorNotApplicable {
541 operator: BinaryOp::Between,
542 left: value_col.get_type(),
543 right: lower_col.get_type(),
544 fragment: fragment.clone(),
545 }
546 .into());
547 }
548
549 match (ge_result.data(), le_result.data()) {
550 (ColumnData::Bool(ge_container), ColumnData::Bool(le_container)) => {
551 let mut data = Vec::with_capacity(ge_container.len());
552 let mut bitvec = Vec::with_capacity(ge_container.len());
553
554 for i in 0..ge_container.len() {
555 if ge_container.is_defined(i) && le_container.is_defined(i) {
556 data.push(ge_container.data().get(i)
557 && le_container.data().get(i));
558 bitvec.push(true);
559 } else {
560 data.push(false);
561 bitvec.push(false);
562 }
563 }
564
565 Ok(Column {
566 name: fragment.clone(),
567 data: ColumnData::bool_with_bitvec(data, bitvec),
568 })
569 }
570 _ => unreachable!(
571 "Both comparison results should be boolean after the check above"
572 ),
573 }
574 })
575 }
576
577 Expression::In(e) => {
578 let list_expressions = match e.list.as_ref() {
579 Expression::Tuple(tuple) => &tuple.expressions,
580 Expression::List(list) => &list.expressions,
581 _ => from_ref(e.list.as_ref()),
582 };
583 let value = compile_expression(_ctx, &e.value)?;
584 let list: Vec<CompiledExpr> = list_expressions
585 .iter()
586 .map(|expr| compile_expression(_ctx, expr))
587 .collect::<Result<Vec<_>>>()?;
588 let negated = e.negated;
589 let fragment = e.fragment.clone();
590 CompiledExpr::new(move |ctx| {
591 if list.is_empty() {
592 let value_col = value.execute(ctx)?;
593 let len = value_col.data().len();
594 let result = vec![negated; len];
595 return Ok(Column {
596 name: fragment.clone(),
597 data: ColumnData::bool(result),
598 });
599 }
600
601 let value_col = value.execute(ctx)?;
602
603 let first_col = list[0].execute(ctx)?;
604 let mut result = compare_columns::<Equal>(
605 &value_col,
606 &first_col,
607 fragment.clone(),
608 |f, l, r| {
609 TypeError::BinaryOperatorNotApplicable {
610 operator: BinaryOp::Equal,
611 left: l,
612 right: r,
613 fragment: f,
614 }
615 .into_diagnostic()
616 },
617 )?;
618
619 for list_expr in list.iter().skip(1) {
620 let list_col = list_expr.execute(ctx)?;
621 let eq_result = compare_columns::<Equal>(
622 &value_col,
623 &list_col,
624 fragment.clone(),
625 |f, l, r| {
626 TypeError::BinaryOperatorNotApplicable {
627 operator: BinaryOp::Equal,
628 left: l,
629 right: r,
630 fragment: f,
631 }
632 .into_diagnostic()
633 },
634 )?;
635 result = or_columns(result, eq_result, fragment.clone())?;
636 }
637
638 if negated {
639 result = negate_column(result, fragment.clone());
640 }
641
642 Ok(result)
643 })
644 }
645
646 Expression::Contains(e) => {
647 let list_expressions = match e.list.as_ref() {
648 Expression::Tuple(tuple) => &tuple.expressions,
649 Expression::List(list) => &list.expressions,
650 _ => from_ref(e.list.as_ref()),
651 };
652 let value = compile_expression(_ctx, &e.value)?;
653 let list: Vec<CompiledExpr> = list_expressions
654 .iter()
655 .map(|expr| compile_expression(_ctx, expr))
656 .collect::<Result<Vec<_>>>()?;
657 let fragment = e.fragment.clone();
658 CompiledExpr::new(move |ctx| {
659 let value_col = value.execute(ctx)?;
660
661 if list.is_empty() {
663 let len = value_col.data().len();
664 let result = vec![true; len];
665 return Ok(Column {
666 name: fragment.clone(),
667 data: ColumnData::bool(result),
668 });
669 }
670
671 let first_col = list[0].execute(ctx)?;
673 let mut result = list_contains_element(&value_col, &first_col, &fragment)?;
674
675 for list_expr in list.iter().skip(1) {
676 let list_col = list_expr.execute(ctx)?;
677 let element_result = list_contains_element(&value_col, &list_col, &fragment)?;
678 result = and_columns(result, element_result, fragment.clone())?;
679 }
680
681 Ok(result)
682 })
683 }
684
685 Expression::Cast(e) => {
686 if let Expression::Constant(const_expr) = e.expression.as_ref() {
687 let const_expr = const_expr.clone();
688 let target_type = e.to.ty.clone();
689 CompiledExpr::new(move |ctx| {
690 let row_count = ctx.take.unwrap_or(ctx.row_count);
691 let data = constant_value(&const_expr, row_count)?;
692 let casted = if data.get_type() == target_type {
693 data
694 } else {
695 constant_value_of(&const_expr, target_type.clone(), row_count)?
696 };
697 Ok(Column {
698 name: const_expr.full_fragment_owned(),
699 data: casted,
700 })
701 })
702 } else {
703 let inner = compile_expression(_ctx, &e.expression)?;
704 let target_type = e.to.ty.clone();
705 let inner_fragment = e.expression.full_fragment_owned();
706 CompiledExpr::new(move |ctx| {
707 let column = inner.execute(ctx)?;
708 let frag = inner_fragment.clone();
709 let casted =
710 cast_column_data(ctx, &column.data(), target_type.clone(), &|| {
711 inner_fragment.clone()
712 })
713 .map_err(|e| {
714 Error::from(CastError::InvalidNumber {
715 fragment: frag,
716 target: target_type.clone(),
717 cause: e.diagnostic(),
718 })
719 })?;
720 Ok(Column {
721 name: column.name_owned(),
722 data: casted,
723 })
724 })
725 }
726 }
727
728 Expression::If(e) => {
729 let condition = compile_expression(_ctx, &e.condition)?;
730 let then_expr = compile_expressions(_ctx, from_ref(e.then_expr.as_ref()))?;
731 let else_ifs: Vec<(CompiledExpr, Vec<CompiledExpr>)> = e
732 .else_ifs
733 .iter()
734 .map(|ei| {
735 Ok((
736 compile_expression(_ctx, &ei.condition)?,
737 compile_expressions(_ctx, from_ref(ei.then_expr.as_ref()))?,
738 ))
739 })
740 .collect::<Result<Vec<_>>>()?;
741 let else_branch: Option<Vec<CompiledExpr>> = match &e.else_expr {
742 Some(expr) => Some(compile_expressions(_ctx, from_ref(expr.as_ref()))?),
743 None => None,
744 };
745 let fragment = e.fragment.clone();
746 CompiledExpr::new_multi(move |ctx| {
747 execute_if_multi(ctx, &condition, &then_expr, &else_ifs, &else_branch, &fragment)
748 })
749 }
750
751 Expression::Map(e) => {
752 let expressions = compile_expressions(_ctx, &e.expressions)?;
753 CompiledExpr::new_multi(move |ctx| execute_map_multi(ctx, &expressions))
754 }
755
756 Expression::Extend(e) => {
757 let expressions = compile_expressions(_ctx, &e.expressions)?;
758 CompiledExpr::new_multi(move |ctx| execute_extend_multi(ctx, &expressions))
759 }
760
761 Expression::Call(e) => {
762 let expr = e.clone();
763 CompiledExpr::new(move |ctx| call_eval(ctx, &expr, ctx.functions, ctx.clock))
764 }
765
766 Expression::SumTypeConstructor(_) => {
767 panic!(
768 "SumTypeConstructor in expression context — constructors should be expanded by InlineDataNode before expression compilation"
769 );
770 }
771
772 Expression::IsVariant(e) => {
773 let col_name = match e.expression.as_ref() {
774 Expression::Column(c) => c.0.name.text().to_string(),
775 other => other.full_fragment_owned().text().to_string(),
776 };
777 let tag_col_name = format!("{}_tag", col_name);
778 let tag = e.tag.expect("IS variant tag must be resolved before compilation");
779 let fragment = e.fragment.clone();
780 CompiledExpr::new(move |ctx| {
781 if let Some(tag_col) =
782 ctx.columns.iter().find(|c| c.name().text() == tag_col_name.as_str())
783 {
784 match tag_col.data() {
785 ColumnData::Uint1(container) => {
786 let results: Vec<bool> = container
787 .iter()
788 .take(ctx.row_count)
789 .map(|v| v == Some(tag))
790 .collect();
791 Ok(Column {
792 name: fragment.clone(),
793 data: ColumnData::bool(results),
794 })
795 }
796 _ => Ok(Column {
797 name: fragment.clone(),
798 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
799 }),
800 }
801 } else {
802 Ok(Column {
803 name: fragment.clone(),
804 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
805 })
806 }
807 })
808 }
809
810 Expression::FieldAccess(e) => {
811 let field_name = e.field.text().to_string();
812 let var_name = match e.object.as_ref() {
814 Expression::Variable(var_expr) => Some(var_expr.name().to_string()),
815 _ => None,
816 };
817 let object = compile_expression(_ctx, &e.object)?;
818 CompiledExpr::new(move |ctx| {
819 if let Some(ref variable_name) = var_name {
820 match ctx.symbol_table.get(variable_name) {
821 Some(Variable::Columns(columns)) => {
822 let col = columns
823 .columns
824 .iter()
825 .find(|c| c.name.text() == field_name);
826 match col {
827 Some(col) => {
828 let value = col.data.get_value(0);
829 let row_count =
830 ctx.take.unwrap_or(ctx.row_count);
831 let mut data = ColumnData::with_capacity(
832 value.get_type(),
833 row_count,
834 );
835 for _ in 0..row_count {
836 data.push_value(value.clone());
837 }
838 Ok(Column {
839 name: Fragment::internal(&field_name),
840 data,
841 })
842 }
843 None => {
844 let available: Vec<String> = columns
845 .columns
846 .iter()
847 .map(|c| c.name.text().to_string())
848 .collect();
849 return Err(TypeError::Runtime {
850 kind: RuntimeErrorKind::FieldNotFound {
851 variable: variable_name
852 .to_string(),
853 field: field_name.to_string(),
854 available,
855 },
856 message: format!(
857 "Field '{}' not found on variable '{}'",
858 field_name, variable_name
859 ),
860 }
861 .into());
862 }
863 }
864 }
865 Some(Variable::Scalar(_)) | Some(Variable::Closure(_)) => {
866 return Err(TypeError::Runtime {
867 kind: RuntimeErrorKind::FieldNotFound {
868 variable: variable_name.to_string(),
869 field: field_name.to_string(),
870 available: vec![],
871 },
872 message: format!(
873 "Field '{}' not found on variable '{}'",
874 field_name, variable_name
875 ),
876 }
877 .into());
878 }
879 Some(Variable::ForIterator {
880 ..
881 }) => {
882 return Err(TypeError::Runtime {
883 kind: RuntimeErrorKind::VariableIsDataframe {
884 name: variable_name.to_string(),
885 },
886 message: format!(
887 "Variable '{}' contains a dataframe and cannot be used directly in scalar expressions",
888 variable_name
889 ),
890 }
891 .into());
892 }
893 None => {
894 return Err(TypeError::Runtime {
895 kind: RuntimeErrorKind::VariableNotFound {
896 name: variable_name.to_string(),
897 },
898 message: format!(
899 "Variable '{}' is not defined",
900 variable_name
901 ),
902 }
903 .into());
904 }
905 }
906 } else {
907 let _obj_col = object.execute(ctx)?;
909 return Err(TypeError::Runtime {
910 kind: RuntimeErrorKind::FieldNotFound {
911 variable: "<expression>".to_string(),
912 field: field_name.to_string(),
913 available: vec![],
914 },
915 message: format!(
916 "Field '{}' not found on variable '<expression>'",
917 field_name
918 ),
919 }
920 .into());
921 }
922 })
923 }
924 })
925}
926
927fn compile_expressions(ctx: &CompileContext, exprs: &[Expression]) -> Result<Vec<CompiledExpr>> {
928 exprs.iter().map(|e| compile_expression(ctx, e)).collect()
929}
930
931fn execute_and(left: &Column, right: &Column, fragment: &Fragment) -> Result<Column> {
934 binary_op_unwrap_option(left, right, fragment.clone(), |left, right| match (&left.data(), &right.data()) {
935 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
936 let data: Vec<bool> = l_container
937 .data()
938 .iter()
939 .zip(r_container.data().iter())
940 .map(|(l_val, r_val)| l_val && r_val)
941 .collect();
942
943 Ok(Column {
944 name: fragment.clone(),
945 data: ColumnData::bool(data),
946 })
947 }
948 (l, r) => {
949 if l.is_number() || r.is_number() {
950 return Err(TypeError::LogicalOperatorNotApplicable {
951 operator: LogicalOp::And,
952 operand_category: OperandCategory::Number,
953 fragment: fragment.clone(),
954 }
955 .into());
956 } else if l.is_text() || r.is_text() {
957 return Err(TypeError::LogicalOperatorNotApplicable {
958 operator: LogicalOp::And,
959 operand_category: OperandCategory::Text,
960 fragment: fragment.clone(),
961 }
962 .into());
963 } else if l.is_temporal() || r.is_temporal() {
964 return Err(TypeError::LogicalOperatorNotApplicable {
965 operator: LogicalOp::And,
966 operand_category: OperandCategory::Temporal,
967 fragment: fragment.clone(),
968 }
969 .into());
970 } else if l.is_uuid() || r.is_uuid() {
971 return Err(TypeError::LogicalOperatorNotApplicable {
972 operator: LogicalOp::And,
973 operand_category: OperandCategory::Uuid,
974 fragment: fragment.clone(),
975 }
976 .into());
977 } else {
978 unimplemented!("{} and {}", l.get_type(), r.get_type());
979 }
980 }
981 })
982}
983
984fn execute_or(left: &Column, right: &Column, fragment: &Fragment) -> Result<Column> {
985 binary_op_unwrap_option(left, right, fragment.clone(), |left, right| match (&left.data(), &right.data()) {
986 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
987 let data: Vec<bool> = l_container
988 .data()
989 .iter()
990 .zip(r_container.data().iter())
991 .map(|(l_val, r_val)| l_val || r_val)
992 .collect();
993
994 Ok(Column {
995 name: fragment.clone(),
996 data: ColumnData::bool(data),
997 })
998 }
999 (l, r) => {
1000 if l.is_number() || r.is_number() {
1001 return Err(TypeError::LogicalOperatorNotApplicable {
1002 operator: LogicalOp::Or,
1003 operand_category: OperandCategory::Number,
1004 fragment: fragment.clone(),
1005 }
1006 .into());
1007 } else if l.is_text() || r.is_text() {
1008 return Err(TypeError::LogicalOperatorNotApplicable {
1009 operator: LogicalOp::Or,
1010 operand_category: OperandCategory::Text,
1011 fragment: fragment.clone(),
1012 }
1013 .into());
1014 } else if l.is_temporal() || r.is_temporal() {
1015 return Err(TypeError::LogicalOperatorNotApplicable {
1016 operator: LogicalOp::Or,
1017 operand_category: OperandCategory::Temporal,
1018 fragment: fragment.clone(),
1019 }
1020 .into());
1021 } else if l.is_uuid() || r.is_uuid() {
1022 return Err(TypeError::LogicalOperatorNotApplicable {
1023 operator: LogicalOp::Or,
1024 operand_category: OperandCategory::Uuid,
1025 fragment: fragment.clone(),
1026 }
1027 .into());
1028 } else {
1029 unimplemented!("{} or {}", l.get_type(), r.get_type());
1030 }
1031 }
1032 })
1033}
1034
1035fn execute_xor(left: &Column, right: &Column, fragment: &Fragment) -> Result<Column> {
1036 binary_op_unwrap_option(left, right, fragment.clone(), |left, right| match (&left.data(), &right.data()) {
1037 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
1038 let data: Vec<bool> = l_container
1039 .data()
1040 .iter()
1041 .zip(r_container.data().iter())
1042 .map(|(l_val, r_val)| l_val != r_val)
1043 .collect();
1044
1045 Ok(Column {
1046 name: fragment.clone(),
1047 data: ColumnData::bool(data),
1048 })
1049 }
1050 (l, r) => {
1051 if l.is_number() || r.is_number() {
1052 return Err(TypeError::LogicalOperatorNotApplicable {
1053 operator: LogicalOp::Xor,
1054 operand_category: OperandCategory::Number,
1055 fragment: fragment.clone(),
1056 }
1057 .into());
1058 } else if l.is_text() || r.is_text() {
1059 return Err(TypeError::LogicalOperatorNotApplicable {
1060 operator: LogicalOp::Xor,
1061 operand_category: OperandCategory::Text,
1062 fragment: fragment.clone(),
1063 }
1064 .into());
1065 } else if l.is_temporal() || r.is_temporal() {
1066 return Err(TypeError::LogicalOperatorNotApplicable {
1067 operator: LogicalOp::Xor,
1068 operand_category: OperandCategory::Temporal,
1069 fragment: fragment.clone(),
1070 }
1071 .into());
1072 } else if l.is_uuid() || r.is_uuid() {
1073 return Err(TypeError::LogicalOperatorNotApplicable {
1074 operator: LogicalOp::Xor,
1075 operand_category: OperandCategory::Uuid,
1076 fragment: fragment.clone(),
1077 }
1078 .into());
1079 } else {
1080 unimplemented!("{} xor {}", l.get_type(), r.get_type());
1081 }
1082 }
1083 })
1084}
1085
1086fn or_columns(left: Column, right: Column, fragment: Fragment) -> Result<Column> {
1087 binary_op_unwrap_option(&left, &right, fragment.clone(), |left, right| match (left.data(), right.data()) {
1088 (ColumnData::Bool(l), ColumnData::Bool(r)) => {
1089 let len = l.len();
1090 let mut data = Vec::with_capacity(len);
1091 let mut bitvec = Vec::with_capacity(len);
1092
1093 for i in 0..len {
1094 let l_defined = l.is_defined(i);
1095 let r_defined = r.is_defined(i);
1096 let l_val = l.data().get(i);
1097 let r_val = r.data().get(i);
1098
1099 if l_defined && r_defined {
1100 data.push(l_val || r_val);
1101 bitvec.push(true);
1102 } else {
1103 data.push(false);
1104 bitvec.push(false);
1105 }
1106 }
1107
1108 Ok(Column {
1109 name: fragment.clone(),
1110 data: ColumnData::bool_with_bitvec(data, bitvec),
1111 })
1112 }
1113 _ => {
1114 unreachable!("OR columns should only be called with boolean columns from equality comparisons")
1115 }
1116 })
1117}
1118
1119fn and_columns(left: Column, right: Column, fragment: Fragment) -> Result<Column> {
1120 binary_op_unwrap_option(&left, &right, fragment.clone(), |left, right| match (left.data(), right.data()) {
1121 (ColumnData::Bool(l), ColumnData::Bool(r)) => {
1122 let len = l.len();
1123 let mut data = Vec::with_capacity(len);
1124 let mut bitvec = Vec::with_capacity(len);
1125
1126 for i in 0..len {
1127 let l_defined = l.is_defined(i);
1128 let r_defined = r.is_defined(i);
1129 let l_val = l.data().get(i);
1130 let r_val = r.data().get(i);
1131
1132 if l_defined && r_defined {
1133 data.push(l_val && r_val);
1134 bitvec.push(true);
1135 } else {
1136 data.push(false);
1137 bitvec.push(false);
1138 }
1139 }
1140
1141 Ok(Column {
1142 name: fragment.clone(),
1143 data: ColumnData::bool_with_bitvec(data, bitvec),
1144 })
1145 }
1146 _ => {
1147 unreachable!("AND columns should only be called with boolean columns")
1148 }
1149 })
1150}
1151
1152fn list_items_contain(items: &[Value], element: &Value, fragment: &Fragment) -> bool {
1153 items.iter().any(|item| {
1154 if item == element {
1155 return true;
1156 }
1157 let item_col = Column {
1158 name: fragment.clone(),
1159 data: ColumnData::from(item.clone()),
1160 };
1161 let elem_col = Column {
1162 name: fragment.clone(),
1163 data: ColumnData::from(element.clone()),
1164 };
1165 compare_columns::<Equal>(&item_col, &elem_col, fragment.clone(), |f, l, r| {
1166 TypeError::BinaryOperatorNotApplicable {
1167 operator: BinaryOp::Equal,
1168 left: l,
1169 right: r,
1170 fragment: f,
1171 }
1172 .into_diagnostic()
1173 })
1174 .ok()
1175 .and_then(|c| match c.data() {
1176 ColumnData::Bool(b) => Some(b.data().get(0)),
1177 _ => None,
1178 })
1179 .unwrap_or(false)
1180 })
1181}
1182
1183fn list_contains_element(list_col: &Column, element_col: &Column, fragment: &Fragment) -> Result<Column> {
1184 let len = list_col.data().len();
1185 let mut data = Vec::with_capacity(len);
1186
1187 for i in 0..len {
1188 let list_value = list_col.data().get_value(i);
1189 let element_value = element_col.data().get_value(i);
1190
1191 let contained = match &list_value {
1192 Value::List(items) => list_items_contain(items, &element_value, fragment),
1193 Value::Tuple(items) => list_items_contain(items, &element_value, fragment),
1194 Value::Any(boxed) => match boxed.as_ref() {
1195 Value::List(items) => list_items_contain(items, &element_value, fragment),
1196 Value::Tuple(items) => list_items_contain(items, &element_value, fragment),
1197 _ => false,
1198 },
1199 _ => false,
1200 };
1201 data.push(contained);
1202 }
1203
1204 Ok(Column {
1205 name: fragment.clone(),
1206 data: ColumnData::bool(data),
1207 })
1208}
1209
1210fn negate_column(col: Column, fragment: Fragment) -> Column {
1211 unary_op_unwrap_option(&col, |col| match col.data() {
1212 ColumnData::Bool(container) => {
1213 let len = container.len();
1214 let mut data = Vec::with_capacity(len);
1215 let mut bitvec = Vec::with_capacity(len);
1216
1217 for i in 0..len {
1218 if container.is_defined(i) {
1219 data.push(!container.data().get(i));
1220 bitvec.push(true);
1221 } else {
1222 data.push(false);
1223 bitvec.push(false);
1224 }
1225 }
1226
1227 Ok(Column {
1228 name: fragment.clone(),
1229 data: ColumnData::bool_with_bitvec(data, bitvec),
1230 })
1231 }
1232 _ => unreachable!("negate_column should only be called with boolean columns"),
1233 })
1234 .unwrap()
1235}
1236
1237fn is_truthy(value: &Value) -> bool {
1238 match value {
1239 Value::Boolean(true) => true,
1240 Value::Boolean(false) => false,
1241 Value::None {
1242 ..
1243 } => false,
1244 Value::Int1(0) | Value::Int2(0) | Value::Int4(0) | Value::Int8(0) | Value::Int16(0) => false,
1245 Value::Uint1(0) | Value::Uint2(0) | Value::Uint4(0) | Value::Uint8(0) | Value::Uint16(0) => false,
1246 Value::Int1(_) | Value::Int2(_) | Value::Int4(_) | Value::Int8(_) | Value::Int16(_) => true,
1247 Value::Uint1(_) | Value::Uint2(_) | Value::Uint4(_) | Value::Uint8(_) | Value::Uint16(_) => true,
1248 Value::Utf8(s) => !s.is_empty(),
1249 _ => true,
1250 }
1251}
1252
1253fn execute_if_multi(
1254 ctx: &EvalContext,
1255 condition: &CompiledExpr,
1256 then_expr: &[CompiledExpr],
1257 else_ifs: &[(CompiledExpr, Vec<CompiledExpr>)],
1258 else_branch: &Option<Vec<CompiledExpr>>,
1259 _fragment: &Fragment,
1260) -> Result<Vec<Column>> {
1261 let condition_column = condition.execute(ctx)?;
1262
1263 let mut result_data: Option<Vec<ColumnData>> = None;
1264 let mut result_names: Vec<Fragment> = Vec::new();
1265
1266 for row_idx in 0..ctx.row_count {
1267 let condition_value = condition_column.data().get_value(row_idx);
1268
1269 let branch_results = if is_truthy(&condition_value) {
1270 execute_multi_exprs(ctx, then_expr)?
1271 } else {
1272 let mut found_branch = false;
1273 let mut branch_columns = None;
1274
1275 for (else_if_condition, else_if_then) in else_ifs {
1276 let else_if_col = else_if_condition.execute(ctx)?;
1277 let else_if_value = else_if_col.data().get_value(row_idx);
1278
1279 if is_truthy(&else_if_value) {
1280 branch_columns = Some(execute_multi_exprs(ctx, else_if_then)?);
1281 found_branch = true;
1282 break;
1283 }
1284 }
1285
1286 if found_branch {
1287 branch_columns.unwrap()
1288 } else if let Some(else_exprs) = else_branch {
1289 execute_multi_exprs(ctx, else_exprs)?
1290 } else {
1291 vec![]
1292 }
1293 };
1294
1295 let is_empty_result = branch_results.is_empty();
1297 if is_empty_result {
1298 if let Some(data) = result_data.as_mut() {
1299 for col_data in data.iter_mut() {
1300 col_data.push_value(Value::none());
1301 }
1302 }
1303 continue;
1304 }
1305
1306 if result_data.is_none() {
1308 let mut data: Vec<ColumnData> = branch_results
1309 .iter()
1310 .map(|col| ColumnData::with_capacity(col.data().get_type(), ctx.row_count))
1311 .collect();
1312 for _ in 0..row_idx {
1313 for col_data in data.iter_mut() {
1314 col_data.push_value(Value::none());
1315 }
1316 }
1317 result_data = Some(data);
1318 result_names = branch_results.iter().map(|col| col.name.clone()).collect();
1319 }
1320
1321 let data = result_data.as_mut().unwrap();
1322 for (i, branch_col) in branch_results.iter().enumerate() {
1323 if i < data.len() {
1324 let branch_value = branch_col.data().get_value(row_idx);
1325 data[i].push_value(branch_value);
1326 }
1327 }
1328 }
1329
1330 let result_data = result_data.unwrap_or_default();
1331 let result: Vec<Column> = result_data
1332 .into_iter()
1333 .enumerate()
1334 .map(|(i, data)| Column {
1335 name: result_names.get(i).cloned().unwrap_or_else(|| Fragment::internal("column")),
1336 data,
1337 })
1338 .collect();
1339
1340 if result.is_empty() {
1341 Ok(vec![Column {
1342 name: Fragment::internal("none"),
1343 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
1344 }])
1345 } else {
1346 Ok(result)
1347 }
1348}
1349
1350fn execute_multi_exprs(ctx: &EvalContext, exprs: &[CompiledExpr]) -> Result<Vec<Column>> {
1351 let mut result = Vec::new();
1352 for expr in exprs {
1353 result.extend(expr.execute_multi(ctx)?);
1354 }
1355 Ok(result)
1356}
1357
1358fn execute_map_multi(ctx: &EvalContext, expressions: &[CompiledExpr]) -> Result<Vec<Column>> {
1359 let mut result = Vec::with_capacity(expressions.len());
1360
1361 for expr in expressions {
1362 let column = expr.execute(ctx)?;
1363 let name = column.name.text().to_string();
1364 result.push(Column {
1365 name: Fragment::internal(name),
1366 data: column.data,
1367 });
1368 }
1369
1370 Ok(result)
1371}
1372
1373fn execute_extend_multi(ctx: &EvalContext, expressions: &[CompiledExpr]) -> Result<Vec<Column>> {
1374 let mut result = Vec::with_capacity(expressions.len());
1375
1376 for expr in expressions {
1377 let column = expr.execute(ctx)?;
1378 let name = column.name.text().to_string();
1379 result.push(Column {
1380 name: Fragment::internal(name),
1381 data: column.data,
1382 });
1383 }
1384
1385 Ok(result)
1386}