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