1use reifydb_core::value::column::{Column, data::ColumnData};
5use reifydb_rql::expression::Expression;
6use reifydb_type::{
7 error,
8 error::diagnostic::{
9 cast,
10 operator::{
11 and_can_not_applied_to_number, and_can_not_applied_to_temporal, and_can_not_applied_to_text,
12 and_can_not_applied_to_uuid, between_cannot_be_applied_to_incompatible_types,
13 equal_cannot_be_applied_to_incompatible_types,
14 greater_than_cannot_be_applied_to_incompatible_types,
15 greater_than_equal_cannot_be_applied_to_incompatible_types,
16 less_than_cannot_be_applied_to_incompatible_types,
17 less_than_equal_cannot_be_applied_to_incompatible_types,
18 not_equal_cannot_be_applied_to_incompatible_types, or_can_not_applied_to_number,
19 or_can_not_applied_to_temporal, or_can_not_applied_to_text, or_can_not_applied_to_uuid,
20 xor_can_not_applied_to_number, xor_can_not_applied_to_temporal, xor_can_not_applied_to_text,
21 xor_can_not_applied_to_uuid,
22 },
23 runtime::{variable_is_dataframe, variable_not_found},
24 },
25 fragment::Fragment,
26 return_error,
27 value::{Value, r#type::Type},
28};
29
30use super::context::CompileContext;
31use crate::{
32 expression::{
33 arith::{add::add_columns, div::div_columns, mul::mul_columns, rem::rem_columns, sub::sub_columns},
34 call::call_eval,
35 cast::cast_column_data,
36 compare::{Equal, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, NotEqual, compare_columns},
37 constant::{constant_value, constant_value_of},
38 context::EvalContext,
39 lookup::column_lookup,
40 },
41 vm::stack::Variable,
42};
43
44pub struct CompiledExpr {
45 inner: CompiledExprInner,
46 access_column_name: Option<String>,
47}
48
49enum CompiledExprInner {
50 Single(Box<dyn Fn(&EvalContext) -> crate::Result<Column> + Send + Sync>),
51 Multi(Box<dyn Fn(&EvalContext) -> crate::Result<Vec<Column>> + Send + Sync>),
52}
53
54impl CompiledExpr {
55 pub fn new(f: impl Fn(&EvalContext) -> crate::Result<Column> + Send + Sync + 'static) -> Self {
56 Self {
57 inner: CompiledExprInner::Single(Box::new(f)),
58 access_column_name: None,
59 }
60 }
61
62 pub fn new_multi(f: impl Fn(&EvalContext) -> crate::Result<Vec<Column>> + Send + Sync + 'static) -> Self {
63 Self {
64 inner: CompiledExprInner::Multi(Box::new(f)),
65 access_column_name: None,
66 }
67 }
68
69 pub fn new_access(
70 name: String,
71 f: impl Fn(&EvalContext) -> crate::Result<Column> + Send + Sync + 'static,
72 ) -> Self {
73 Self {
74 inner: CompiledExprInner::Single(Box::new(f)),
75 access_column_name: Some(name),
76 }
77 }
78
79 pub fn access_column_name(&self) -> Option<&str> {
80 self.access_column_name.as_deref()
81 }
82
83 pub fn execute(&self, ctx: &EvalContext) -> crate::Result<Column> {
84 match &self.inner {
85 CompiledExprInner::Single(f) => f(ctx),
86 CompiledExprInner::Multi(f) => {
87 let columns = f(ctx)?;
88 Ok(columns.into_iter().next().unwrap_or_else(|| Column {
89 name: Fragment::internal("none"),
90 data: ColumnData::with_capacity(Type::Option(Box::new(Type::Boolean)), 0),
91 }))
92 }
93 }
94 }
95
96 pub fn execute_multi(&self, ctx: &EvalContext) -> crate::Result<Vec<Column>> {
97 match &self.inner {
98 CompiledExprInner::Single(f) => Ok(vec![f(ctx)?]),
99 CompiledExprInner::Multi(f) => f(ctx),
100 }
101 }
102}
103
104pub fn compile_expression(_ctx: &CompileContext, expr: &Expression) -> crate::Result<CompiledExpr> {
108 Ok(match expr {
109 Expression::Constant(e) => {
110 let expr = e.clone();
111 CompiledExpr::new(move |ctx| {
112 let row_count = ctx.take.unwrap_or(ctx.row_count);
113 Ok(Column {
114 name: expr.full_fragment_owned(),
115 data: constant_value(&expr, row_count)?,
116 })
117 })
118 }
119
120 Expression::Column(e) => {
121 let expr = e.clone();
122 CompiledExpr::new(move |ctx| column_lookup(ctx, &expr))
123 }
124
125 Expression::Variable(e) => {
126 let expr = e.clone();
127 CompiledExpr::new(move |ctx| {
128 let variable_name = expr.name();
129
130 if variable_name == "env" {
131 return_error!(variable_is_dataframe(variable_name));
132 }
133
134 match ctx.symbol_table.get(variable_name) {
135 Some(Variable::Scalar(columns)) => {
136 let value = columns.scalar_value();
137 let mut data =
138 ColumnData::with_capacity(value.get_type(), ctx.row_count);
139 for _ in 0..ctx.row_count {
140 data.push_value(value.clone());
141 }
142 Ok(Column {
143 name: Fragment::internal(variable_name),
144 data,
145 })
146 }
147 Some(Variable::Columns(_))
148 | Some(Variable::ForIterator {
149 ..
150 }) => {
151 return_error!(variable_is_dataframe(variable_name));
152 }
153 None => {
154 return_error!(variable_not_found(variable_name));
155 }
156 }
157 })
158 }
159
160 Expression::Parameter(e) => {
161 let expr = e.clone();
162 CompiledExpr::new(move |ctx| crate::expression::parameter::parameter_lookup(ctx, &expr))
163 }
164
165 Expression::Alias(e) => {
166 let inner = compile_expression(_ctx, &e.expression)?;
167 let alias = e.alias.0.clone();
168 CompiledExpr::new(move |ctx| {
169 let mut column = inner.execute(ctx)?;
170 column.name = alias.clone();
171 Ok(column)
172 })
173 }
174
175 Expression::Add(e) => {
176 let left = compile_expression(_ctx, &e.left)?;
177 let right = compile_expression(_ctx, &e.right)?;
178 let fragment = e.full_fragment_owned();
179 CompiledExpr::new(move |ctx| {
180 let l = left.execute(ctx)?;
181 let r = right.execute(ctx)?;
182 add_columns(ctx, &l, &r, || fragment.clone())
183 })
184 }
185
186 Expression::Sub(e) => {
187 let left = compile_expression(_ctx, &e.left)?;
188 let right = compile_expression(_ctx, &e.right)?;
189 let fragment = e.full_fragment_owned();
190 CompiledExpr::new(move |ctx| {
191 let l = left.execute(ctx)?;
192 let r = right.execute(ctx)?;
193 sub_columns(ctx, &l, &r, || fragment.clone())
194 })
195 }
196
197 Expression::Mul(e) => {
198 let left = compile_expression(_ctx, &e.left)?;
199 let right = compile_expression(_ctx, &e.right)?;
200 let fragment = e.full_fragment_owned();
201 CompiledExpr::new(move |ctx| {
202 let l = left.execute(ctx)?;
203 let r = right.execute(ctx)?;
204 mul_columns(ctx, &l, &r, || fragment.clone())
205 })
206 }
207
208 Expression::Div(e) => {
209 let left = compile_expression(_ctx, &e.left)?;
210 let right = compile_expression(_ctx, &e.right)?;
211 let fragment = e.full_fragment_owned();
212 CompiledExpr::new(move |ctx| {
213 let l = left.execute(ctx)?;
214 let r = right.execute(ctx)?;
215 div_columns(ctx, &l, &r, || fragment.clone())
216 })
217 }
218
219 Expression::Rem(e) => {
220 let left = compile_expression(_ctx, &e.left)?;
221 let right = compile_expression(_ctx, &e.right)?;
222 let fragment = e.full_fragment_owned();
223 CompiledExpr::new(move |ctx| {
224 let l = left.execute(ctx)?;
225 let r = right.execute(ctx)?;
226 rem_columns(ctx, &l, &r, || fragment.clone())
227 })
228 }
229
230 Expression::Equal(e) => {
231 let left = compile_expression(_ctx, &e.left)?;
232 let right = compile_expression(_ctx, &e.right)?;
233 let fragment = e.full_fragment_owned();
234 CompiledExpr::new(move |ctx| {
235 let l = left.execute(ctx)?;
236 let r = right.execute(ctx)?;
237 let result = compare_columns::<Equal>(
238 &l,
239 &r,
240 fragment.clone(),
241 equal_cannot_be_applied_to_incompatible_types,
242 );
243 result
244 })
245 }
246
247 Expression::NotEqual(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 let result = compare_columns::<NotEqual>(
255 &l,
256 &r,
257 fragment.clone(),
258 not_equal_cannot_be_applied_to_incompatible_types,
259 );
260 result
261 })
262 }
263
264 Expression::GreaterThan(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::<GreaterThan>(
272 &l,
273 &r,
274 fragment.clone(),
275 greater_than_cannot_be_applied_to_incompatible_types,
276 );
277 result
278 })
279 }
280
281 Expression::GreaterThanEqual(e) => {
282 let left = compile_expression(_ctx, &e.left)?;
283 let right = compile_expression(_ctx, &e.right)?;
284 let fragment = e.full_fragment_owned();
285 CompiledExpr::new(move |ctx| {
286 let l = left.execute(ctx)?;
287 let r = right.execute(ctx)?;
288 let result = compare_columns::<GreaterThanEqual>(
289 &l,
290 &r,
291 fragment.clone(),
292 greater_than_equal_cannot_be_applied_to_incompatible_types,
293 );
294 result
295 })
296 }
297
298 Expression::LessThan(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::<LessThan>(
306 &l,
307 &r,
308 fragment.clone(),
309 less_than_cannot_be_applied_to_incompatible_types,
310 );
311 result
312 })
313 }
314
315 Expression::LessThanEqual(e) => {
316 let left = compile_expression(_ctx, &e.left)?;
317 let right = compile_expression(_ctx, &e.right)?;
318 let fragment = e.full_fragment_owned();
319 CompiledExpr::new(move |ctx| {
320 let l = left.execute(ctx)?;
321 let r = right.execute(ctx)?;
322 let result = compare_columns::<LessThanEqual>(
323 &l,
324 &r,
325 fragment.clone(),
326 less_than_equal_cannot_be_applied_to_incompatible_types,
327 );
328 result
329 })
330 }
331
332 Expression::And(e) => {
333 let left = compile_expression(_ctx, &e.left)?;
334 let right = compile_expression(_ctx, &e.right)?;
335 let fragment = e.full_fragment_owned();
336 CompiledExpr::new(move |ctx| {
337 let l = left.execute(ctx)?;
338 let r = right.execute(ctx)?;
339 let result = execute_and(&l, &r, &fragment);
340 result
341 })
342 }
343
344 Expression::Or(e) => {
345 let left = compile_expression(_ctx, &e.left)?;
346 let right = compile_expression(_ctx, &e.right)?;
347 let fragment = e.full_fragment_owned();
348 CompiledExpr::new(move |ctx| {
349 let l = left.execute(ctx)?;
350 let r = right.execute(ctx)?;
351 let result = execute_or(&l, &r, &fragment);
352 result
353 })
354 }
355
356 Expression::Xor(e) => {
357 let left = compile_expression(_ctx, &e.left)?;
358 let right = compile_expression(_ctx, &e.right)?;
359 let fragment = e.full_fragment_owned();
360 CompiledExpr::new(move |ctx| {
361 let l = left.execute(ctx)?;
362 let r = right.execute(ctx)?;
363 let result = execute_xor(&l, &r, &fragment);
364 result
365 })
366 }
367
368 Expression::Prefix(e) => {
369 let expr = e.clone();
370 CompiledExpr::new(move |ctx| {
371 crate::expression::prefix::prefix_eval(ctx, &expr, ctx.functions, ctx.clock)
372 })
373 }
374
375 Expression::Type(e) => {
376 let ty = e.ty.clone();
377 let fragment = e.fragment.clone();
378 CompiledExpr::new(move |ctx| {
379 let row_count = ctx.take.unwrap_or(ctx.row_count);
380 let values: Vec<Box<Value>> =
381 (0..row_count).map(|_| Box::new(Value::Type(ty.clone()))).collect();
382 Ok(Column::new(fragment.text(), ColumnData::any(values)))
383 })
384 }
385
386 Expression::AccessSource(e) => {
387 let col_name = e.column.name.text().to_string();
388 let expr = e.clone();
389 CompiledExpr::new_access(col_name, move |ctx| {
390 crate::expression::access::access_lookup(ctx, &expr)
391 })
392 }
393
394 Expression::Tuple(e) => {
395 if e.expressions.len() == 1 {
396 let inner = compile_expression(_ctx, &e.expressions[0])?;
397 CompiledExpr::new(move |ctx| inner.execute(ctx))
398 } else {
399 unimplemented!("Multi-element tuple evaluation not yet supported: {:?}", e)
400 }
401 }
402
403 Expression::Between(e) => {
404 let value = compile_expression(_ctx, &e.value)?;
405 let lower = compile_expression(_ctx, &e.lower)?;
406 let upper = compile_expression(_ctx, &e.upper)?;
407 let fragment = e.fragment.clone();
408 CompiledExpr::new(move |ctx| {
409 let value_col = value.execute(ctx)?;
410 let lower_col = lower.execute(ctx)?;
411 let upper_col = upper.execute(ctx)?;
412
413 let ge_result = compare_columns::<GreaterThanEqual>(
414 &value_col,
415 &lower_col,
416 fragment.clone(),
417 greater_than_equal_cannot_be_applied_to_incompatible_types,
418 )?;
419 let le_result = compare_columns::<LessThanEqual>(
420 &value_col,
421 &upper_col,
422 fragment.clone(),
423 less_than_equal_cannot_be_applied_to_incompatible_types,
424 )?;
425
426 if !matches!(ge_result.data(), ColumnData::Bool(_))
427 || !matches!(le_result.data(), ColumnData::Bool(_))
428 {
429 return_error!(between_cannot_be_applied_to_incompatible_types(
430 fragment.clone(),
431 value_col.get_type(),
432 lower_col.get_type(),
433 ))
434 }
435
436 match (ge_result.data(), le_result.data()) {
437 (ColumnData::Bool(ge_container), ColumnData::Bool(le_container)) => {
438 let mut data = Vec::with_capacity(ge_container.len());
439 let mut bitvec = Vec::with_capacity(ge_container.len());
440
441 for i in 0..ge_container.len() {
442 if ge_container.is_defined(i) && le_container.is_defined(i) {
443 data.push(ge_container.data().get(i)
444 && le_container.data().get(i));
445 bitvec.push(true);
446 } else {
447 data.push(false);
448 bitvec.push(false);
449 }
450 }
451
452 Ok(Column {
453 name: fragment.clone(),
454 data: ColumnData::bool_with_bitvec(data, bitvec),
455 })
456 }
457 _ => unreachable!(
458 "Both comparison results should be boolean after the check above"
459 ),
460 }
461 })
462 }
463
464 Expression::In(e) => {
465 let list_expressions = match e.list.as_ref() {
466 Expression::Tuple(tuple) => &tuple.expressions,
467 _ => std::slice::from_ref(e.list.as_ref()),
468 };
469 let value = compile_expression(_ctx, &e.value)?;
470 let list: Vec<CompiledExpr> = list_expressions
471 .iter()
472 .map(|expr| compile_expression(_ctx, expr))
473 .collect::<crate::Result<Vec<_>>>()?;
474 let negated = e.negated;
475 let fragment = e.fragment.clone();
476 CompiledExpr::new(move |ctx| {
477 if list.is_empty() {
478 let value_col = value.execute(ctx)?;
479 let len = value_col.data().len();
480 let result = vec![negated; len];
481 return Ok(Column {
482 name: fragment.clone(),
483 data: ColumnData::bool(result),
484 });
485 }
486
487 let value_col = value.execute(ctx)?;
488
489 let first_col = list[0].execute(ctx)?;
490 let mut result = compare_columns::<Equal>(
491 &value_col,
492 &first_col,
493 fragment.clone(),
494 equal_cannot_be_applied_to_incompatible_types,
495 )?;
496
497 for list_expr in list.iter().skip(1) {
498 let list_col = list_expr.execute(ctx)?;
499 let eq_result = compare_columns::<Equal>(
500 &value_col,
501 &list_col,
502 fragment.clone(),
503 equal_cannot_be_applied_to_incompatible_types,
504 )?;
505 result = or_columns(result, eq_result, fragment.clone())?;
506 }
507
508 if negated {
509 result = negate_column(result, fragment.clone());
510 }
511
512 Ok(result)
513 })
514 }
515
516 Expression::Cast(e) => {
517 if let Expression::Constant(const_expr) = e.expression.as_ref() {
518 let const_expr = const_expr.clone();
519 let target_type = e.to.ty.clone();
520 CompiledExpr::new(move |ctx| {
521 let row_count = ctx.take.unwrap_or(ctx.row_count);
522 let data = constant_value(&const_expr, row_count)?;
523 let casted = if data.get_type() == target_type {
524 data
525 } else {
526 constant_value_of(&const_expr, target_type.clone(), row_count)?
527 };
528 Ok(Column {
529 name: const_expr.full_fragment_owned(),
530 data: casted,
531 })
532 })
533 } else {
534 let inner = compile_expression(_ctx, &e.expression)?;
535 let target_type = e.to.ty.clone();
536 let inner_fragment = e.expression.full_fragment_owned();
537 CompiledExpr::new(move |ctx| {
538 let column = inner.execute(ctx)?;
539 let frag = inner_fragment.clone();
540 let casted =
541 cast_column_data(ctx, &column.data(), target_type.clone(), &|| {
542 inner_fragment.clone()
543 })
544 .map_err(|e| {
545 error!(cast::invalid_number(
546 frag,
547 target_type.clone(),
548 e.diagnostic()
549 ))
550 })?;
551 Ok(Column {
552 name: column.name_owned(),
553 data: casted,
554 })
555 })
556 }
557 }
558
559 Expression::If(e) => {
560 let condition = compile_expression(_ctx, &e.condition)?;
561 let then_expr = compile_expressions(_ctx, std::slice::from_ref(e.then_expr.as_ref()))?;
562 let else_ifs: Vec<(CompiledExpr, Vec<CompiledExpr>)> = e
563 .else_ifs
564 .iter()
565 .map(|ei| {
566 Ok((
567 compile_expression(_ctx, &ei.condition)?,
568 compile_expressions(_ctx, std::slice::from_ref(ei.then_expr.as_ref()))?,
569 ))
570 })
571 .collect::<crate::Result<Vec<_>>>()?;
572 let else_branch: Option<Vec<CompiledExpr>> = match &e.else_expr {
573 Some(expr) => Some(compile_expressions(_ctx, std::slice::from_ref(expr.as_ref()))?),
574 None => None,
575 };
576 let fragment = e.fragment.clone();
577 CompiledExpr::new_multi(move |ctx| {
578 execute_if_multi(ctx, &condition, &then_expr, &else_ifs, &else_branch, &fragment)
579 })
580 }
581
582 Expression::Map(e) => {
583 let expressions = compile_expressions(_ctx, &e.expressions)?;
584 CompiledExpr::new_multi(move |ctx| execute_map_multi(ctx, &expressions))
585 }
586
587 Expression::Extend(e) => {
588 let expressions = compile_expressions(_ctx, &e.expressions)?;
589 CompiledExpr::new_multi(move |ctx| execute_extend_multi(ctx, &expressions))
590 }
591
592 Expression::Call(e) => {
593 let expr = e.clone();
594 CompiledExpr::new(move |ctx| call_eval(ctx, &expr, ctx.functions, ctx.clock))
595 }
596
597 Expression::SumTypeConstructor(_) => {
598 panic!(
599 "SumTypeConstructor in expression context — constructors should be expanded by InlineDataNode before expression compilation"
600 );
601 }
602
603 Expression::IsVariant(e) => {
604 let col_name = match e.expression.as_ref() {
605 Expression::Column(c) => c.0.name.text().to_string(),
606 other => other.full_fragment_owned().text().to_string(),
607 };
608 let tag_col_name = format!("{}_tag", col_name);
609 let tag = e.tag.expect("IS variant tag must be resolved before compilation");
610 let fragment = e.fragment.clone();
611 CompiledExpr::new(move |ctx| {
612 if let Some(tag_col) =
613 ctx.columns.iter().find(|c| c.name().text() == tag_col_name.as_str())
614 {
615 match tag_col.data() {
616 ColumnData::Uint1(container) => {
617 let results: Vec<bool> = container
618 .iter()
619 .take(ctx.row_count)
620 .map(|v| v == Some(tag))
621 .collect();
622 Ok(Column {
623 name: fragment.clone(),
624 data: ColumnData::bool(results),
625 })
626 }
627 _ => Ok(Column {
628 name: fragment.clone(),
629 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
630 }),
631 }
632 } else {
633 Ok(Column {
634 name: fragment.clone(),
635 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
636 })
637 }
638 })
639 }
640 })
641}
642
643fn compile_expressions(ctx: &CompileContext, exprs: &[Expression]) -> crate::Result<Vec<CompiledExpr>> {
644 exprs.iter().map(|e| compile_expression(ctx, e)).collect()
645}
646
647fn execute_and(left: &Column, right: &Column, fragment: &Fragment) -> crate::Result<Column> {
650 super::option::binary_op_unwrap_option(left, right, fragment.clone(), |left, right| {
651 match (&left.data(), &right.data()) {
652 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
653 let data: Vec<bool> = l_container
654 .data()
655 .iter()
656 .zip(r_container.data().iter())
657 .map(|(l_val, r_val)| l_val && r_val)
658 .collect();
659
660 Ok(Column {
661 name: fragment.clone(),
662 data: ColumnData::bool(data),
663 })
664 }
665 (l, r) => {
666 if l.is_number() || r.is_number() {
667 return_error!(and_can_not_applied_to_number(fragment.clone()));
668 } else if l.is_text() || r.is_text() {
669 return_error!(and_can_not_applied_to_text(fragment.clone()));
670 } else if l.is_temporal() || r.is_temporal() {
671 return_error!(and_can_not_applied_to_temporal(fragment.clone()));
672 } else if l.is_uuid() || r.is_uuid() {
673 return_error!(and_can_not_applied_to_uuid(fragment.clone()));
674 } else {
675 unimplemented!("{} and {}", l.get_type(), r.get_type());
676 }
677 }
678 }
679 })
680}
681
682fn execute_or(left: &Column, right: &Column, fragment: &Fragment) -> crate::Result<Column> {
683 super::option::binary_op_unwrap_option(left, right, fragment.clone(), |left, right| {
684 match (&left.data(), &right.data()) {
685 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
686 let data: Vec<bool> = l_container
687 .data()
688 .iter()
689 .zip(r_container.data().iter())
690 .map(|(l_val, r_val)| l_val || r_val)
691 .collect();
692
693 Ok(Column {
694 name: fragment.clone(),
695 data: ColumnData::bool(data),
696 })
697 }
698 (l, r) => {
699 if l.is_number() || r.is_number() {
700 return_error!(or_can_not_applied_to_number(fragment.clone()));
701 } else if l.is_text() || r.is_text() {
702 return_error!(or_can_not_applied_to_text(fragment.clone()));
703 } else if l.is_temporal() || r.is_temporal() {
704 return_error!(or_can_not_applied_to_temporal(fragment.clone()));
705 } else if l.is_uuid() || r.is_uuid() {
706 return_error!(or_can_not_applied_to_uuid(fragment.clone()));
707 } else {
708 unimplemented!("{} or {}", l.get_type(), r.get_type());
709 }
710 }
711 }
712 })
713}
714
715fn execute_xor(left: &Column, right: &Column, fragment: &Fragment) -> crate::Result<Column> {
716 super::option::binary_op_unwrap_option(left, right, fragment.clone(), |left, right| {
717 match (&left.data(), &right.data()) {
718 (ColumnData::Bool(l_container), ColumnData::Bool(r_container)) => {
719 let data: Vec<bool> = l_container
720 .data()
721 .iter()
722 .zip(r_container.data().iter())
723 .map(|(l_val, r_val)| l_val != r_val)
724 .collect();
725
726 Ok(Column {
727 name: fragment.clone(),
728 data: ColumnData::bool(data),
729 })
730 }
731 (l, r) => {
732 if l.is_number() || r.is_number() {
733 return_error!(xor_can_not_applied_to_number(fragment.clone()));
734 } else if l.is_text() || r.is_text() {
735 return_error!(xor_can_not_applied_to_text(fragment.clone()));
736 } else if l.is_temporal() || r.is_temporal() {
737 return_error!(xor_can_not_applied_to_temporal(fragment.clone()));
738 } else if l.is_uuid() || r.is_uuid() {
739 return_error!(xor_can_not_applied_to_uuid(fragment.clone()));
740 } else {
741 unimplemented!("{} xor {}", l.get_type(), r.get_type());
742 }
743 }
744 }
745 })
746}
747
748fn or_columns(left: Column, right: Column, fragment: Fragment) -> crate::Result<Column> {
749 super::option::binary_op_unwrap_option(&left, &right, fragment.clone(), |left, right| {
750 match (left.data(), right.data()) {
751 (ColumnData::Bool(l), ColumnData::Bool(r)) => {
752 let len = l.len();
753 let mut data = Vec::with_capacity(len);
754 let mut bitvec = Vec::with_capacity(len);
755
756 for i in 0..len {
757 let l_defined = l.is_defined(i);
758 let r_defined = r.is_defined(i);
759 let l_val = l.data().get(i);
760 let r_val = r.data().get(i);
761
762 if l_defined && r_defined {
763 data.push(l_val || r_val);
764 bitvec.push(true);
765 } else {
766 data.push(false);
767 bitvec.push(false);
768 }
769 }
770
771 Ok(Column {
772 name: fragment.clone(),
773 data: ColumnData::bool_with_bitvec(data, bitvec),
774 })
775 }
776 _ => {
777 unreachable!(
778 "OR columns should only be called with boolean columns from equality comparisons"
779 )
780 }
781 }
782 })
783}
784
785fn negate_column(col: Column, fragment: Fragment) -> Column {
786 super::option::unary_op_unwrap_option(&col, |col| match col.data() {
787 ColumnData::Bool(container) => {
788 let len = container.len();
789 let mut data = Vec::with_capacity(len);
790 let mut bitvec = Vec::with_capacity(len);
791
792 for i in 0..len {
793 if container.is_defined(i) {
794 data.push(!container.data().get(i));
795 bitvec.push(true);
796 } else {
797 data.push(false);
798 bitvec.push(false);
799 }
800 }
801
802 Ok(Column {
803 name: fragment.clone(),
804 data: ColumnData::bool_with_bitvec(data, bitvec),
805 })
806 }
807 _ => unreachable!("negate_column should only be called with boolean columns"),
808 })
809 .unwrap()
810}
811
812fn is_truthy(value: &Value) -> bool {
813 match value {
814 Value::Boolean(true) => true,
815 Value::Boolean(false) => false,
816 Value::None {
817 ..
818 } => false,
819 Value::Int1(0) | Value::Int2(0) | Value::Int4(0) | Value::Int8(0) | Value::Int16(0) => false,
820 Value::Uint1(0) | Value::Uint2(0) | Value::Uint4(0) | Value::Uint8(0) | Value::Uint16(0) => false,
821 Value::Int1(_) | Value::Int2(_) | Value::Int4(_) | Value::Int8(_) | Value::Int16(_) => true,
822 Value::Uint1(_) | Value::Uint2(_) | Value::Uint4(_) | Value::Uint8(_) | Value::Uint16(_) => true,
823 Value::Utf8(s) => !s.is_empty(),
824 _ => true,
825 }
826}
827
828fn execute_if_multi(
829 ctx: &EvalContext,
830 condition: &CompiledExpr,
831 then_expr: &[CompiledExpr],
832 else_ifs: &[(CompiledExpr, Vec<CompiledExpr>)],
833 else_branch: &Option<Vec<CompiledExpr>>,
834 _fragment: &Fragment,
835) -> crate::Result<Vec<Column>> {
836 let condition_column = condition.execute(ctx)?;
837
838 let mut result_data: Option<Vec<ColumnData>> = None;
839 let mut result_names: Vec<Fragment> = Vec::new();
840
841 for row_idx in 0..ctx.row_count {
842 let condition_value = condition_column.data().get_value(row_idx);
843
844 let branch_results = if is_truthy(&condition_value) {
845 execute_multi_exprs(ctx, then_expr)?
846 } else {
847 let mut found_branch = false;
848 let mut branch_columns = None;
849
850 for (else_if_condition, else_if_then) in else_ifs {
851 let else_if_col = else_if_condition.execute(ctx)?;
852 let else_if_value = else_if_col.data().get_value(row_idx);
853
854 if is_truthy(&else_if_value) {
855 branch_columns = Some(execute_multi_exprs(ctx, else_if_then)?);
856 found_branch = true;
857 break;
858 }
859 }
860
861 if found_branch {
862 branch_columns.unwrap()
863 } else if let Some(else_exprs) = else_branch {
864 execute_multi_exprs(ctx, else_exprs)?
865 } else {
866 vec![]
867 }
868 };
869
870 let is_empty_result = branch_results.is_empty();
872 if is_empty_result {
873 if let Some(data) = result_data.as_mut() {
874 for col_data in data.iter_mut() {
875 col_data.push_value(Value::none());
876 }
877 }
878 continue;
879 }
880
881 if result_data.is_none() {
883 let mut data: Vec<ColumnData> = branch_results
884 .iter()
885 .map(|col| ColumnData::with_capacity(col.data().get_type(), ctx.row_count))
886 .collect();
887 for _ in 0..row_idx {
888 for col_data in data.iter_mut() {
889 col_data.push_value(Value::none());
890 }
891 }
892 result_data = Some(data);
893 result_names = branch_results.iter().map(|col| col.name.clone()).collect();
894 }
895
896 let data = result_data.as_mut().unwrap();
897 for (i, branch_col) in branch_results.iter().enumerate() {
898 if i < data.len() {
899 let branch_value = branch_col.data().get_value(row_idx);
900 data[i].push_value(branch_value);
901 }
902 }
903 }
904
905 let result_data = result_data.unwrap_or_default();
906 let result: Vec<Column> = result_data
907 .into_iter()
908 .enumerate()
909 .map(|(i, data)| Column {
910 name: result_names.get(i).cloned().unwrap_or_else(|| Fragment::internal("column")),
911 data,
912 })
913 .collect();
914
915 if result.is_empty() {
916 Ok(vec![Column {
917 name: Fragment::internal("none"),
918 data: ColumnData::none_typed(Type::Boolean, ctx.row_count),
919 }])
920 } else {
921 Ok(result)
922 }
923}
924
925fn execute_multi_exprs(ctx: &EvalContext, exprs: &[CompiledExpr]) -> crate::Result<Vec<Column>> {
926 let mut result = Vec::new();
927 for expr in exprs {
928 result.extend(expr.execute_multi(ctx)?);
929 }
930 Ok(result)
931}
932
933fn execute_map_multi(ctx: &EvalContext, expressions: &[CompiledExpr]) -> crate::Result<Vec<Column>> {
934 let mut result = Vec::with_capacity(expressions.len());
935
936 for expr in expressions {
937 let column = expr.execute(ctx)?;
938 let name = column.name.text().to_string();
939 result.push(Column {
940 name: Fragment::internal(name),
941 data: column.data,
942 });
943 }
944
945 Ok(result)
946}
947
948fn execute_extend_multi(ctx: &EvalContext, expressions: &[CompiledExpr]) -> crate::Result<Vec<Column>> {
949 let mut result = Vec::with_capacity(expressions.len());
950
951 for expr in expressions {
952 let column = expr.execute(ctx)?;
953 let name = column.name.text().to_string();
954 result.push(Column {
955 name: Fragment::internal(name),
956 data: column.data,
957 });
958 }
959
960 Ok(result)
961}