1#![deny(rust_2018_idioms)]
2#![deny(clippy::all)]
3
4pub mod env;
5pub mod error;
6pub mod eval;
7pub mod plan;
8pub mod test_value;
9
10#[cfg(test)]
11mod tests {
12 use assert_matches::assert_matches;
13
14 use crate::env::basic::MapBindings;
15 use crate::plan;
16 use partiql_catalog::catalog::PartiqlCatalog;
17 use partiql_catalog::context::SystemContext;
18 use rust_decimal_macros::dec;
19
20 use partiql_logical as logical;
21 use partiql_logical::BindingsOp::{Distinct, Project, ProjectAll, ProjectValue};
22
23 use crate::eval::BasicContext;
24 use crate::plan::EvaluationMode;
25 use partiql_logical::{
26 BagExpr, BetweenExpr, BinaryOp, BindingsOp, CoalesceExpr, ExprQuery, IsTypeExpr, JoinKind,
27 ListExpr, LogicalPlan, NullIfExpr, PathComponent, TupleExpr, Type, ValueExpr, VarRefType,
28 };
29 use partiql_value as value;
30 use partiql_value::Value::{Missing, Null};
31 use partiql_value::{bag, list, tuple, Bag, BindingsName, DateTime, List, Tuple, Value};
32
33 fn evaluate(logical: LogicalPlan<BindingsOp>, bindings: MapBindings<Value>) -> Value {
34 let catalog = PartiqlCatalog::default().to_shared_catalog();
35 let mut planner = plan::EvaluatorPlanner::new(EvaluationMode::Permissive, &catalog);
36 let plan = planner.compile(&logical).expect("Expect no plan error");
37 let sys = SystemContext {
38 now: DateTime::from_system_now_utc(),
39 };
40 let ctx = BasicContext::new(bindings, sys);
41 if let Ok(out) = plan.execute(&ctx) {
42 out.result
43 } else {
44 Missing
45 }
46 }
47
48 fn data_customer() -> MapBindings<Value> {
49 fn customer_tuple(id: i64, first_name: &str, balance: i64) -> Value {
50 tuple![("id", id), ("firstName", first_name), ("balance", balance),].into()
51 }
52
53 let customer_val = bag![
54 customer_tuple(5, "jason", 100),
55 customer_tuple(4, "sisko", 0),
56 customer_tuple(3, "jason", -30),
57 customer_tuple(2, "miriam", 20),
58 customer_tuple(1, "miriam", 10),
59 ];
60
61 let mut bindings = MapBindings::default();
62 bindings.insert("customer", customer_val.into());
63 bindings
64 }
65
66 fn data_3_tuple() -> MapBindings<Value> {
67 fn a_tuple(n: i64) -> Value {
68 tuple![("a", n)].into()
69 }
70
71 let data = list![a_tuple(1), a_tuple(2), a_tuple(3)];
72
73 let mut bindings = MapBindings::default();
74 bindings.insert("data", data.into());
75 bindings
76 }
77
78 fn scan(name: &str, as_key: &str) -> BindingsOp {
79 BindingsOp::Scan(logical::Scan {
80 expr: ValueExpr::VarRef(
81 BindingsName::CaseInsensitive(name.to_string().into()),
82 VarRefType::Global,
83 ),
84 as_key: as_key.to_string(),
85 at_key: None,
86 })
87 }
88
89 fn path_var(name: &str, component: &str) -> ValueExpr {
90 ValueExpr::Path(
91 Box::new(ValueExpr::VarRef(
92 BindingsName::CaseInsensitive(name.to_string().into()),
93 VarRefType::Local,
94 )),
95 vec![PathComponent::Key(BindingsName::CaseInsensitive(
96 component.to_string().into(),
97 ))],
98 )
99 }
100
101 fn join_data() -> MapBindings<Value> {
102 let customers = list![
103 tuple![("id", 5), ("name", "Joe")],
104 tuple![("id", 7), ("name", "Mary")],
105 ];
106
107 let orders = list![
108 tuple![("custId", 7), ("productId", 101)],
109 tuple![("custId", 7), ("productId", 523)],
110 ];
111
112 let mut bindings = MapBindings::default();
113 bindings.insert("customers", customers.into());
114 bindings.insert("orders", orders.into());
115 bindings
116 }
117
118 fn join_data_sensors() -> MapBindings<Value> {
119 let sensors = list![
120 tuple![("readings", list![tuple![("v", 1.3)], tuple![("v", 2)],])],
121 tuple![(
122 "readings",
123 list![tuple![("v", 0.7)], tuple![("v", 0.8)], tuple![("v", 0.9)],]
124 )],
125 ];
126 let mut bindings = MapBindings::default();
127 bindings.insert("sensors", sensors.into());
128 bindings
129 }
130
131 fn join_data_sensors_with_empty_table() -> MapBindings<Value> {
132 let sensors = list![
133 tuple![("readings", list![tuple![("v", 1.3)], tuple![("v", 2)],])],
134 tuple![(
135 "readings",
136 list![tuple![("v", 0.7)], tuple![("v", 0.8)], tuple![("v", 0.9)],]
137 )],
138 tuple![("readings", list![])],
139 ];
140 let mut bindings = MapBindings::default();
141 bindings.insert("sensors", sensors.into());
142 bindings
143 }
144
145 fn case_when_data() -> MapBindings<Value> {
146 let nums = list![
147 tuple![("a", 1)],
148 tuple![("a", 2)],
149 tuple![("a", 3)],
150 tuple![("a", Null)],
151 tuple![("a", Missing)],
152 tuple![("a", "foo")],
153 ];
154
155 let mut bindings = MapBindings::default();
156 bindings.insert("nums", nums.into());
157 bindings
158 }
159
160 #[track_caller]
166 fn eval_bin_op<I: Into<logical::Lit>>(
167 op: BinaryOp,
168 lhs: Value,
169 rhs_lit: I,
170 expected_first_elem: Value,
171 ) {
172 let mut plan = LogicalPlan::new();
173 let scan = plan.add_operator(BindingsOp::Scan(logical::Scan {
174 expr: ValueExpr::VarRef(
175 BindingsName::CaseInsensitive("data".into()),
176 VarRefType::Global,
177 ),
178 as_key: "data".to_string(),
179 at_key: None,
180 }));
181
182 let project = plan.add_operator(Project(logical::Project {
183 exprs: Vec::from([(
184 "result".to_string(),
185 ValueExpr::BinaryExpr(
186 op,
187 Box::new(ValueExpr::Path(
188 Box::new(ValueExpr::VarRef(
189 BindingsName::CaseInsensitive("data".into()),
190 VarRefType::Local,
191 )),
192 vec![PathComponent::Key(BindingsName::CaseInsensitive(
193 "lhs".to_string().into(),
194 ))],
195 )),
196 Box::new(ValueExpr::Lit(Box::new(rhs_lit.into()))),
197 ),
198 )]),
199 }));
200
201 let sink = plan.add_operator(BindingsOp::Sink);
202 plan.extend_with_flows(&[(scan, project), (project, sink)]);
203
204 let mut bindings = MapBindings::default();
205 bindings.insert("data", list![Tuple::from([("lhs", lhs)])].into());
206
207 let result = evaluate(plan, bindings).coerce_into_bag();
208 assert!(!&result.is_empty());
209 let expected_result = if expected_first_elem != Missing {
210 bag!(Tuple::from([("result", expected_first_elem)]))
211 } else {
212 bag!(Tuple::new())
214 };
215 assert_eq!(expected_result, result);
216 }
217
218 #[test]
219 fn arithmetic_ops() {
220 eval_bin_op(
223 BinaryOp::Add,
224 Value::from(1),
225 Value::from(2),
226 Value::from(3),
227 );
228 eval_bin_op(
229 BinaryOp::Add,
230 Value::from(1),
231 Value::from(2.),
232 Value::from(3.),
233 );
234 eval_bin_op(
235 BinaryOp::Add,
236 Value::from(1.),
237 Value::from(2),
238 Value::from(3.),
239 );
240 eval_bin_op(
241 BinaryOp::Add,
242 Value::from(1.),
243 Value::from(2.),
244 Value::from(3.),
245 );
246 eval_bin_op(
247 BinaryOp::Add,
248 Value::from(1),
249 Value::from(dec!(2.)),
250 Value::from(dec!(3.)),
251 );
252 eval_bin_op(
253 BinaryOp::Add,
254 Value::from(1.),
255 Value::from(dec!(2.)),
256 Value::from(dec!(3.)),
257 );
258 eval_bin_op(
259 BinaryOp::Add,
260 Value::from(dec!(1.)),
261 Value::from(2),
262 Value::from(dec!(3.)),
263 );
264 eval_bin_op(
265 BinaryOp::Add,
266 Value::from(dec!(1.)),
267 Value::from(2.),
268 Value::from(dec!(3.)),
269 );
270 eval_bin_op(
271 BinaryOp::Add,
272 Value::from(dec!(1.)),
273 Value::from(dec!(2.)),
274 Value::from(dec!(3.)),
275 );
276 eval_bin_op(BinaryOp::Add, Null, Null, Null);
277 eval_bin_op(BinaryOp::Add, Missing, Missing, Missing);
278
279 eval_bin_op(
282 BinaryOp::Sub,
283 Value::from(1),
284 Value::from(2),
285 Value::from(-1),
286 );
287 eval_bin_op(
288 BinaryOp::Sub,
289 Value::from(1),
290 Value::from(2.),
291 Value::from(-1.),
292 );
293 eval_bin_op(
294 BinaryOp::Sub,
295 Value::from(1.),
296 Value::from(2),
297 Value::from(-1.),
298 );
299 eval_bin_op(
300 BinaryOp::Sub,
301 Value::from(1.),
302 Value::from(2.),
303 Value::from(-1.),
304 );
305 eval_bin_op(
306 BinaryOp::Sub,
307 Value::from(1),
308 Value::from(dec!(2.)),
309 Value::from(dec!(-1.)),
310 );
311 eval_bin_op(
312 BinaryOp::Sub,
313 Value::from(1.),
314 Value::from(dec!(2.)),
315 Value::from(dec!(-1.)),
316 );
317 eval_bin_op(
318 BinaryOp::Sub,
319 Value::from(dec!(1.)),
320 Value::from(2),
321 Value::from(dec!(-1.)),
322 );
323 eval_bin_op(
324 BinaryOp::Sub,
325 Value::from(dec!(1.)),
326 Value::from(2.),
327 Value::from(dec!(-1.)),
328 );
329 eval_bin_op(
330 BinaryOp::Sub,
331 Value::from(dec!(1.)),
332 Value::from(dec!(2.)),
333 Value::from(dec!(-1.)),
334 );
335 eval_bin_op(BinaryOp::Sub, Null, Null, Null);
336 eval_bin_op(BinaryOp::Sub, Missing, Missing, Missing);
337
338 eval_bin_op(
341 BinaryOp::Mul,
342 Value::from(1),
343 Value::from(2),
344 Value::from(2),
345 );
346 eval_bin_op(
347 BinaryOp::Mul,
348 Value::from(1),
349 Value::from(2.),
350 Value::from(2.),
351 );
352 eval_bin_op(
353 BinaryOp::Mul,
354 Value::from(1.),
355 Value::from(2),
356 Value::from(2.),
357 );
358 eval_bin_op(
359 BinaryOp::Mul,
360 Value::from(1.),
361 Value::from(2.),
362 Value::from(2.),
363 );
364 eval_bin_op(
365 BinaryOp::Mul,
366 Value::from(1),
367 Value::from(dec!(2.)),
368 Value::from(dec!(2.)),
369 );
370 eval_bin_op(
371 BinaryOp::Mul,
372 Value::from(1.),
373 Value::from(dec!(2.)),
374 Value::from(dec!(2.)),
375 );
376 eval_bin_op(
377 BinaryOp::Mul,
378 Value::from(dec!(1.)),
379 Value::from(2),
380 Value::from(dec!(2.)),
381 );
382 eval_bin_op(
383 BinaryOp::Mul,
384 Value::from(dec!(1.)),
385 Value::from(2.),
386 Value::from(dec!(2.)),
387 );
388 eval_bin_op(
389 BinaryOp::Mul,
390 Value::from(dec!(1.)),
391 Value::from(dec!(2.)),
392 Value::from(dec!(2.)),
393 );
394 eval_bin_op(BinaryOp::Mul, Null, Null, Null);
395 eval_bin_op(BinaryOp::Mul, Missing, Missing, Missing);
396
397 eval_bin_op(
400 BinaryOp::Div,
401 Value::from(1),
402 Value::from(2),
403 Value::from(0),
404 );
405 eval_bin_op(
406 BinaryOp::Div,
407 Value::from(1),
408 Value::from(2.),
409 Value::from(0.5),
410 );
411 eval_bin_op(
412 BinaryOp::Div,
413 Value::from(1.),
414 Value::from(2),
415 Value::from(0.5),
416 );
417 eval_bin_op(
418 BinaryOp::Div,
419 Value::from(1.),
420 Value::from(2.),
421 Value::from(0.5),
422 );
423 eval_bin_op(
424 BinaryOp::Div,
425 Value::from(1),
426 Value::from(dec!(2.)),
427 Value::from(dec!(0.5)),
428 );
429 eval_bin_op(
430 BinaryOp::Div,
431 Value::from(1.),
432 Value::from(dec!(2.)),
433 Value::from(dec!(0.5)),
434 );
435 eval_bin_op(
436 BinaryOp::Div,
437 Value::from(dec!(1.)),
438 Value::from(2),
439 Value::from(dec!(0.5)),
440 );
441 eval_bin_op(
442 BinaryOp::Div,
443 Value::from(dec!(1.)),
444 Value::from(2.),
445 Value::from(dec!(0.5)),
446 );
447 eval_bin_op(
448 BinaryOp::Div,
449 Value::from(dec!(1.)),
450 Value::from(dec!(2.)),
451 Value::from(dec!(0.5)),
452 );
453 eval_bin_op(BinaryOp::Div, Null, Null, Null);
454 eval_bin_op(BinaryOp::Div, Missing, Missing, Missing);
455
456 eval_bin_op(
459 BinaryOp::Mod,
460 Value::from(1),
461 Value::from(2),
462 Value::from(1),
463 );
464 eval_bin_op(
465 BinaryOp::Mod,
466 Value::from(1),
467 Value::from(2.),
468 Value::from(1.),
469 );
470 eval_bin_op(
471 BinaryOp::Mod,
472 Value::from(1.),
473 Value::from(2),
474 Value::from(1.),
475 );
476 eval_bin_op(
477 BinaryOp::Mod,
478 Value::from(1.),
479 Value::from(2.),
480 Value::from(1.),
481 );
482 eval_bin_op(
483 BinaryOp::Mod,
484 Value::from(1),
485 Value::from(dec!(2.)),
486 Value::from(dec!(1.)),
487 );
488 eval_bin_op(
489 BinaryOp::Mod,
490 Value::from(1.),
491 Value::from(dec!(2.)),
492 Value::from(dec!(1.)),
493 );
494 eval_bin_op(
495 BinaryOp::Mod,
496 Value::from(dec!(1.)),
497 Value::from(2),
498 Value::from(dec!(1.)),
499 );
500 eval_bin_op(
501 BinaryOp::Mod,
502 Value::from(dec!(1.)),
503 Value::from(2.),
504 Value::from(dec!(1.)),
505 );
506 eval_bin_op(
507 BinaryOp::Mod,
508 Value::from(dec!(1.)),
509 Value::from(dec!(2.)),
510 Value::from(dec!(1.)),
511 );
512 eval_bin_op(BinaryOp::Mod, Null, Null, Null);
513 eval_bin_op(BinaryOp::Mod, Missing, Missing, Missing);
514 }
515
516 #[test]
517 fn in_expr() {
518 eval_bin_op(
519 BinaryOp::In,
520 Value::from(1),
521 Value::from(list![1, 2, 3]),
522 Value::from(true),
523 );
524 eval_bin_op(
530 BinaryOp::In,
531 Value::from(tuple![("a", 2)]),
532 Value::from(list![tuple![("a", 6)], tuple![("b", 12)], tuple![("a", 2)]]),
533 Value::from(true),
534 );
535 eval_bin_op(
536 BinaryOp::In,
537 Value::from(10),
538 Value::from(bag!["a", "b", 11]),
539 Value::from(false),
540 );
541 eval_bin_op(BinaryOp::In, Value::from(1), Value::from(1), Null);
542 eval_bin_op(
543 BinaryOp::In,
544 Value::from(1),
545 Value::from(list![10, Missing, "b"]),
546 Null,
547 );
548 eval_bin_op(
549 BinaryOp::In,
550 Missing,
551 Value::from(list![1, Missing, "b"]),
552 Null,
553 );
554 eval_bin_op(
555 BinaryOp::In,
556 Null,
557 Value::from(list![1, Missing, "b"]),
558 Null,
559 );
560 eval_bin_op(
561 BinaryOp::In,
562 Value::from(1),
563 Value::from(list![1, Null, "b"]),
564 Value::from(true),
565 );
566 eval_bin_op(
567 BinaryOp::In,
568 Value::from(1),
569 Value::from(list![3, Null]),
570 Null,
571 );
572 }
573
574 #[test]
575 fn comparison_ops() {
576 eval_bin_op(
579 BinaryOp::Lt,
580 Value::from(1),
581 Value::from(2.),
582 Value::from(true),
583 );
584 eval_bin_op(
585 BinaryOp::Lt,
586 Value::from("abc"),
587 Value::from("def"),
588 Value::from(true),
589 );
590 eval_bin_op(BinaryOp::Lt, Missing, Value::from(2.), Missing);
591 eval_bin_op(BinaryOp::Lt, Null, Value::from(2.), Null);
592 eval_bin_op(BinaryOp::Lt, Value::from(1), Value::from("foo"), Missing);
593
594 eval_bin_op(
597 BinaryOp::Gt,
598 Value::from(1),
599 Value::from(2.),
600 Value::from(false),
601 );
602 eval_bin_op(
603 BinaryOp::Gt,
604 Value::from("abc"),
605 Value::from("def"),
606 Value::from(false),
607 );
608 eval_bin_op(BinaryOp::Gt, Missing, Value::from(2.), Missing);
609 eval_bin_op(BinaryOp::Gt, Null, Value::from(2.), Null);
610 eval_bin_op(BinaryOp::Gt, Value::from(1), Value::from("foo"), Missing);
611
612 eval_bin_op(
615 BinaryOp::Lteq,
616 Value::from(1),
617 Value::from(2.),
618 Value::from(true),
619 );
620 eval_bin_op(
621 BinaryOp::Lteq,
622 Value::from("abc"),
623 Value::from("def"),
624 Value::from(true),
625 );
626 eval_bin_op(BinaryOp::Lteq, Missing, Value::from(2.), Missing);
627 eval_bin_op(BinaryOp::Lt, Null, Value::from(2.), Null);
628 eval_bin_op(BinaryOp::Lteq, Value::from(1), Value::from("foo"), Missing);
629
630 eval_bin_op(
633 BinaryOp::Gteq,
634 Value::from(1),
635 Value::from(2.),
636 Value::from(false),
637 );
638 eval_bin_op(
639 BinaryOp::Gteq,
640 Value::from("abc"),
641 Value::from("def"),
642 Value::from(false),
643 );
644 eval_bin_op(BinaryOp::Gteq, Missing, Value::from(2.), Missing);
645 eval_bin_op(BinaryOp::Gteq, Null, Value::from(2.), Null);
646 eval_bin_op(BinaryOp::Gteq, Value::from(1), Value::from("foo"), Missing);
647 }
648
649 #[test]
650 fn and_or_null() {
651 #[track_caller]
652 fn eval_to_null<I: Into<logical::Lit>>(op: BinaryOp, lhs: I, rhs: I) {
653 let mut plan = LogicalPlan::new();
654 let expq = plan.add_operator(BindingsOp::ExprQuery(ExprQuery {
655 expr: ValueExpr::BinaryExpr(
656 op,
657 Box::new(ValueExpr::Lit(Box::new(lhs.into()))),
658 Box::new(ValueExpr::Lit(Box::new(rhs.into()))),
659 ),
660 }));
661
662 let sink = plan.add_operator(BindingsOp::Sink);
663 plan.add_flow(expq, sink);
664
665 let result = evaluate(plan, MapBindings::default());
666 assert_eq!(result, Value::Null);
667 }
668
669 eval_to_null(BinaryOp::And, Value::Null, Value::Boolean(true));
670 eval_to_null(BinaryOp::And, Value::Missing, Value::Boolean(true));
671 eval_to_null(BinaryOp::And, Value::Boolean(true), Value::Null);
672 eval_to_null(BinaryOp::And, Value::Boolean(true), Value::Missing);
673 eval_to_null(BinaryOp::Or, Value::Null, Value::Boolean(false));
674 eval_to_null(BinaryOp::Or, Value::Missing, Value::Boolean(false));
675 eval_to_null(BinaryOp::Or, Value::Boolean(false), Value::Null);
676 eval_to_null(BinaryOp::Or, Value::Boolean(false), Value::Missing);
677 }
678
679 #[test]
680 fn between_op() {
681 #[track_caller]
682 fn eval_between_op(value: Value, from: Value, to: Value, expected_first_elem: Value) {
683 let mut plan = LogicalPlan::new();
684 let scan = plan.add_operator(BindingsOp::Scan(logical::Scan {
685 expr: ValueExpr::VarRef(
686 BindingsName::CaseInsensitive("data".into()),
687 VarRefType::Global,
688 ),
689 as_key: "data".to_string(),
690 at_key: None,
691 }));
692
693 let project = plan.add_operator(Project(logical::Project {
694 exprs: Vec::from([(
695 "result".to_string(),
696 ValueExpr::BetweenExpr(BetweenExpr {
697 value: Box::new(ValueExpr::Path(
698 Box::new(ValueExpr::VarRef(
699 BindingsName::CaseInsensitive("data".into()),
700 VarRefType::Local,
701 )),
702 vec![PathComponent::Key(BindingsName::CaseInsensitive(
703 "value".to_string().into(),
704 ))],
705 )),
706 from: Box::new(ValueExpr::Lit(Box::new(from.into()))),
707 to: Box::new(ValueExpr::Lit(Box::new(to.into()))),
708 }),
709 )]),
710 }));
711
712 let sink = plan.add_operator(BindingsOp::Sink);
713 plan.extend_with_flows(&[(scan, project), (project, sink)]);
714
715 let mut bindings = MapBindings::default();
716 bindings.insert("data", list![Tuple::from([("value", value)])].into());
717
718 let result = evaluate(plan, bindings).coerce_into_bag();
719 assert!(!&result.is_empty());
720 let expected_result = bag!(Tuple::from([("result", expected_first_elem)]));
721 assert_eq!(expected_result, result);
722 }
723 eval_between_op(
724 Value::from(2),
725 Value::from(1),
726 Value::from(3),
727 Value::from(true),
728 );
729 eval_between_op(
730 Value::from(2),
731 Value::from(1.),
732 Value::from(dec!(3.)),
733 Value::from(true),
734 );
735 eval_between_op(
736 Value::from(1),
737 Value::from(2),
738 Value::from(3),
739 Value::from(false),
740 );
741 eval_between_op(Null, Value::from(1), Value::from(3), Null);
742 eval_between_op(Value::from(2), Null, Value::from(3), Null);
743 eval_between_op(Value::from(2), Value::from(1), Null, Null);
744 eval_between_op(Missing, Value::from(1), Value::from(3), Null);
745 eval_between_op(Value::from(2), Missing, Value::from(3), Null);
746 eval_between_op(Value::from(2), Value::from(1), Missing, Null);
747 eval_between_op(Value::from(1), Value::from(2), Null, Value::from(false));
749 eval_between_op(Value::from(1), Value::from(2), Missing, Value::from(false));
750 eval_between_op(Value::from(2), Null, Value::from(1), Value::from(false));
752 eval_between_op(Value::from(2), Missing, Value::from(1), Value::from(false));
753 }
754
755 #[test]
756 fn select_with_join_and_on() {
757 let from_lhs = scan("customers", "c");
760 let from_rhs = scan("orders", "o");
761
762 let mut lg = LogicalPlan::new();
763 let project = lg.add_operator(Project(logical::Project {
764 exprs: Vec::from([
765 ("id".to_string(), path_var("c", "id")),
766 ("name".to_string(), path_var("c", "name")),
767 ("custId".to_string(), path_var("o", "custId")),
768 ("productId".to_string(), path_var("o", "productId")),
769 ]),
770 }));
771
772 let join = lg.add_operator(BindingsOp::Join(logical::Join {
773 kind: JoinKind::Cross,
774 left: Box::new(from_lhs),
775 right: Box::new(from_rhs),
776 on: Some(ValueExpr::BinaryExpr(
777 BinaryOp::Eq,
778 Box::new(path_var("c", "id")),
779 Box::new(path_var("o", "custId")),
780 )),
781 }));
782
783 let sink = lg.add_operator(BindingsOp::Sink);
784 lg.add_flow_with_branch_num(join, project, 0);
785 lg.add_flow_with_branch_num(project, sink, 0);
786
787 let out = evaluate(lg, join_data());
788 println!("{:?}", &out);
789
790 assert_matches!(out, Value::Bag(bag) => {
791 let expected = bag![
792 tuple![("custId", 7), ("name", "Mary"), ("id", 7), ("productId", 101)],
793 tuple![("custId", 7), ("name", "Mary"), ("id", 7), ("productId", 523)],
794 ];
795 assert_eq!(*bag, expected);
796 });
797 }
798
799 #[test]
800 fn select_with_cross_join_sensors() {
801 let mut lg = LogicalPlan::new();
806
807 let from_lhs = scan("sensors", "s");
808 let from_rhs = BindingsOp::Scan(logical::Scan {
809 expr: path_var("s", "readings"),
810 as_key: "r".to_string(),
811 at_key: None,
812 });
813
814 let project = lg.add_operator(Project(logical::Project {
815 exprs: Vec::from([("v".to_string(), path_var("r", "v"))]),
816 }));
817
818 let join = lg.add_operator(BindingsOp::Join(logical::Join {
819 kind: JoinKind::Cross,
820 left: Box::new(from_lhs),
821 right: Box::new(from_rhs),
822 on: None,
823 }));
824
825 let sink = lg.add_operator(BindingsOp::Sink);
826 lg.add_flow_with_branch_num(join, project, 0);
827 lg.add_flow_with_branch_num(project, sink, 0);
828
829 let out = evaluate(lg, join_data_sensors());
830 println!("{:?}", &out);
831
832 assert_matches!(out, Value::Bag(bag) => {
833 let expected = bag![
834 tuple![("v", 1.3)],
835 tuple![("v", 2)],
836 tuple![("v", 0.7)],
837 tuple![("v", 0.8)],
838 tuple![("v", 0.9)],
839 ];
840 assert_eq!(*bag, expected);
841 });
842 }
843
844 #[test]
845 fn select_with_cross_join_sensors_with_empty_table() {
846 let mut lg = LogicalPlan::new();
851
852 let from_lhs = scan("sensors", "s");
853 let from_rhs = BindingsOp::Scan(logical::Scan {
854 expr: path_var("s", "readings"),
855 as_key: "r".to_string(),
856 at_key: None,
857 });
858
859 let project = lg.add_operator(Project(logical::Project {
860 exprs: Vec::from([("v".to_string(), path_var("r", "v"))]),
861 }));
862
863 let join = lg.add_operator(BindingsOp::Join(logical::Join {
864 kind: JoinKind::Cross,
865 left: Box::new(from_lhs),
866 right: Box::new(from_rhs),
867 on: None,
868 }));
869
870 let sink = lg.add_operator(BindingsOp::Sink);
871 lg.add_flow_with_branch_num(join, project, 0);
872 lg.add_flow_with_branch_num(project, sink, 0);
873
874 let out = evaluate(lg, join_data_sensors_with_empty_table());
875 println!("{:?}", &out);
876
877 assert_matches!(out, Value::Bag(bag) => {
878 let expected = bag![
879 tuple![("v", 1.3)],
880 tuple![("v", 2)],
881 tuple![("v", 0.7)],
882 tuple![("v", 0.8)],
883 tuple![("v", 0.9)],
884 ];
885 assert_eq!(*bag, expected);
886 });
887 }
888
889 #[test]
890 fn select_with_left_join_sensors_with_empty_table() {
891 let mut lg = LogicalPlan::new();
898
899 let from_lhs = scan("sensors", "s");
900 let from_rhs = BindingsOp::Scan(logical::Scan {
901 expr: path_var("s", "readings"),
902 as_key: "r".to_string(),
903 at_key: None,
904 });
905
906 let project = lg.add_operator(Project(logical::Project {
907 exprs: Vec::from([(
908 "r".to_string(),
909 ValueExpr::VarRef(BindingsName::CaseInsensitive("r".into()), VarRefType::Local),
910 )]),
911 }));
912
913 let join = lg.add_operator(BindingsOp::Join(logical::Join {
914 kind: JoinKind::Left,
915 left: Box::new(from_lhs),
916 right: Box::new(from_rhs),
917 on: Some(ValueExpr::Lit(Box::new(Value::from(true).into()))),
918 }));
919
920 let sink = lg.add_operator(BindingsOp::Sink);
921 lg.add_flow_with_branch_num(join, project, 0);
922 lg.add_flow_with_branch_num(project, sink, 0);
923
924 let out = evaluate(lg, join_data_sensors_with_empty_table());
925 println!("{:?}", &out);
926
927 assert_matches!(out, Value::Bag(bag) => {
928 let expected = bag![
929 tuple![("r", tuple![("v", 1.3)])],
930 tuple![("r", tuple![("v", 2)])],
931 tuple![("r", tuple![("v", 0.7)])],
932 tuple![("r", tuple![("v", 0.8)])],
933 tuple![("r", tuple![("v", 0.9)])],
934 tuple![("r", Null)],
935 ];
936 assert_eq!(*bag, expected);
937 });
938 }
939
940 fn simple_case_expr_with_default() -> logical::SimpleCase {
941 logical::SimpleCase {
942 expr: Box::new(path_var("n", "a")),
943 cases: vec![
944 (
945 Box::new(ValueExpr::Lit(Box::new(Value::Integer(1).into()))),
946 Box::new(ValueExpr::Lit(Box::new(
947 Value::from("one".to_string()).into(),
948 ))),
949 ),
950 (
951 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
952 Box::new(ValueExpr::Lit(Box::new(
953 Value::from("two".to_string()).into(),
954 ))),
955 ),
956 ],
957 default: Some(Box::new(ValueExpr::Lit(Box::new(
958 Value::from("other".to_string()).into(),
959 )))),
960 }
961 }
962
963 fn searched_case_expr_with_default() -> logical::SearchedCase {
964 logical::SearchedCase {
965 cases: vec![
966 (
967 Box::new(ValueExpr::BinaryExpr(
968 BinaryOp::Eq,
969 Box::new(path_var("n", "a")),
970 Box::new(ValueExpr::Lit(Box::new(Value::Integer(1).into()))),
971 )),
972 Box::new(ValueExpr::Lit(Box::new(
973 Value::from("one".to_string()).into(),
974 ))),
975 ),
976 (
977 Box::new(ValueExpr::BinaryExpr(
978 BinaryOp::Eq,
979 Box::new(path_var("n", "a")),
980 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
981 )),
982 Box::new(ValueExpr::Lit(Box::new(
983 Value::from("two".to_string()).into(),
984 ))),
985 ),
986 ],
987 default: Some(Box::new(ValueExpr::Lit(Box::new(
988 Value::from("other".to_string()).into(),
989 )))),
990 }
991 }
992
993 #[test]
994 fn simple_case_when_expr_with_default() {
995 let mut lg = LogicalPlan::new();
996 let scan = lg.add_operator(scan("nums", "n"));
1003
1004 let project_logical = Project(logical::Project {
1005 exprs: Vec::from([
1006 ("a".to_string(), path_var("n", "a")),
1007 (
1008 "b".to_string(),
1009 ValueExpr::SimpleCase(simple_case_expr_with_default()),
1010 ),
1011 ]),
1012 });
1013 let project = lg.add_operator(project_logical);
1014 let sink = lg.add_operator(BindingsOp::Sink);
1015 lg.add_flow(scan, project);
1016 lg.add_flow(project, sink);
1017
1018 let out = evaluate(lg, case_when_data());
1019 println!("{:?}", &out);
1020
1021 assert_matches!(out, Value::Bag(bag) => {
1022 let expected = bag![
1023 tuple![("a", 1), ("b", "one")],
1024 tuple![("a", 2), ("b", "two")],
1025 tuple![("a", 3), ("b", "other")],
1026 tuple![("a", Null), ("b", "other")],
1027 tuple![("b", "other")],
1028 tuple![("a", "foo"), ("b", "other")],
1029 ];
1030 assert_eq!(*bag, expected);
1031 });
1032 }
1033
1034 #[test]
1035 fn simple_case_when_expr_without_default() {
1036 let mut lg = LogicalPlan::new();
1037 let scan = lg.add_operator(scan("nums", "n"));
1043 let project_logical_no_default = Project(logical::Project {
1044 exprs: Vec::from([
1045 ("a".to_string(), path_var("n", "a")),
1046 (
1047 "b".to_string(),
1048 ValueExpr::SimpleCase(logical::SimpleCase {
1049 default: None,
1050 ..simple_case_expr_with_default()
1051 }),
1052 ),
1053 ]),
1054 });
1055 let project = lg.add_operator(project_logical_no_default);
1056 let sink = lg.add_operator(BindingsOp::Sink);
1057 lg.add_flow(scan, project);
1058 lg.add_flow(project, sink);
1059
1060 let out = evaluate(lg, case_when_data());
1061 println!("{:?}", &out);
1062
1063 assert_matches!(out, Value::Bag(bag) => {
1064 let expected = bag![
1065 tuple![("a", 1), ("b", "one")],
1066 tuple![("a", 2), ("b", "two")],
1067 tuple![("a", 3), ("b", Null)],
1068 tuple![("a", Null), ("b", Null)],
1069 tuple![("b", Null)],
1070 tuple![("a", "foo"), ("b", Null)],
1071 ];
1072 assert_eq!(*bag, expected);
1073 });
1074 }
1075
1076 #[test]
1077 fn searched_case_when_expr_with_default() {
1078 let mut lg = LogicalPlan::new();
1079 let scan = lg.add_operator(scan("nums", "n"));
1086
1087 let project_logical = Project(logical::Project {
1088 exprs: Vec::from([
1089 ("a".to_string(), path_var("n", "a")),
1090 (
1091 "b".to_string(),
1092 ValueExpr::SearchedCase(searched_case_expr_with_default()),
1093 ),
1094 ]),
1095 });
1096 let project = lg.add_operator(project_logical);
1097 let sink = lg.add_operator(BindingsOp::Sink);
1098 lg.add_flow(scan, project);
1099 lg.add_flow(project, sink);
1100
1101 let out = evaluate(lg, case_when_data());
1102 println!("{:?}", &out);
1103
1104 assert_matches!(out, Value::Bag(bag) => {
1105 let expected = bag![
1106 tuple![("a", 1), ("b", "one")],
1107 tuple![("a", 2), ("b", "two")],
1108 tuple![("a", 3), ("b", "other")],
1109 tuple![("a", Null), ("b", "other")],
1110 tuple![("b", "other")],
1111 tuple![("a", "foo"), ("b", "other")],
1112 ];
1113 assert_eq!(*bag, expected);
1114 });
1115 }
1116
1117 #[test]
1118 fn searched_case_when_expr_without_default() {
1119 let mut lg = LogicalPlan::new();
1120 let scan = lg.add_operator(scan("nums", "n"));
1126 let project_logical_no_default = Project(logical::Project {
1127 exprs: Vec::from([
1128 ("a".to_string(), path_var("n", "a")),
1129 (
1130 "b".to_string(),
1131 ValueExpr::SearchedCase(logical::SearchedCase {
1132 default: None,
1133 ..searched_case_expr_with_default()
1134 }),
1135 ),
1136 ]),
1137 });
1138 let project = lg.add_operator(project_logical_no_default);
1139 let sink = lg.add_operator(BindingsOp::Sink);
1140 lg.add_flow(scan, project);
1141 lg.add_flow(project, sink);
1142
1143 let out = evaluate(lg, case_when_data());
1144 println!("{:?}", &out);
1145
1146 assert_matches!(out, Value::Bag(bag) => {
1147 let expected = bag![
1148 tuple![("a", 1), ("b", "one")],
1149 tuple![("a", 2), ("b", "two")],
1150 tuple![("a", 3), ("b", Null)],
1151 tuple![("a", Null), ("b", Null)],
1152 tuple![("b", Null)],
1153 tuple![("a", "foo"), ("b", Null)],
1154 ];
1155 assert_eq!(*bag, expected);
1156 });
1157 }
1158
1159 fn eval_is_op(not: bool, expr: Value, is_type: Type, expected_first_elem: Value) {
1163 let mut plan = LogicalPlan::new();
1164 let scan = plan.add_operator(BindingsOp::Scan(logical::Scan {
1165 expr: ValueExpr::VarRef(
1166 BindingsName::CaseInsensitive("data".into()),
1167 VarRefType::Global,
1168 ),
1169 as_key: "data".to_string(),
1170 at_key: None,
1171 }));
1172
1173 let project = plan.add_operator(Project(logical::Project {
1174 exprs: Vec::from([(
1175 "result".to_string(),
1176 ValueExpr::IsTypeExpr(IsTypeExpr {
1177 not,
1178 expr: Box::new(ValueExpr::Path(
1179 Box::new(ValueExpr::VarRef(
1180 BindingsName::CaseInsensitive("data".into()),
1181 VarRefType::Local,
1182 )),
1183 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1184 "expr".to_string().into(),
1185 ))],
1186 )),
1187 is_type,
1188 }),
1189 )]),
1190 }));
1191
1192 let sink = plan.add_operator(BindingsOp::Sink);
1193 plan.extend_with_flows(&[(scan, project), (project, sink)]);
1194
1195 let mut bindings = MapBindings::default();
1196 bindings.insert("data", list![Tuple::from([("expr", expr)])].into());
1197
1198 let result = evaluate(plan, bindings).coerce_into_bag();
1199 assert!(!&result.is_empty());
1200 assert_eq!(bag!(Tuple::from([("result", expected_first_elem)])), result);
1201 }
1202
1203 #[test]
1204 fn is_type_null_missing() {
1205 eval_is_op(false, Value::from(1), Type::MissingType, Value::from(false));
1207 eval_is_op(false, Value::Missing, Type::MissingType, Value::from(true));
1208 eval_is_op(false, Value::Null, Type::MissingType, Value::from(false));
1209
1210 eval_is_op(true, Value::from(1), Type::MissingType, Value::from(true));
1212 eval_is_op(true, Value::Missing, Type::MissingType, Value::from(false));
1213 eval_is_op(true, Value::Null, Type::MissingType, Value::from(true));
1214
1215 eval_is_op(false, Value::from(1), Type::NullType, Value::from(false));
1217 eval_is_op(false, Value::Missing, Type::NullType, Value::from(true));
1218 eval_is_op(false, Value::Null, Type::NullType, Value::from(true));
1219
1220 eval_is_op(true, Value::from(1), Type::NullType, Value::from(true));
1222 eval_is_op(true, Value::Missing, Type::NullType, Value::from(false));
1223 eval_is_op(true, Value::Null, Type::NullType, Value::from(false));
1224 }
1225
1226 fn eval_null_if_op(lhs: Value, rhs: Value, expected_first_elem: Value) {
1230 let mut plan = LogicalPlan::new();
1231 let scan = plan.add_operator(BindingsOp::Scan(logical::Scan {
1232 expr: ValueExpr::VarRef(
1233 BindingsName::CaseInsensitive("data".into()),
1234 VarRefType::Global,
1235 ),
1236 as_key: "data".to_string(),
1237 at_key: None,
1238 }));
1239
1240 let project = plan.add_operator(Project(logical::Project {
1241 exprs: Vec::from([(
1242 "result".to_string(),
1243 ValueExpr::NullIfExpr(NullIfExpr {
1244 lhs: Box::new(ValueExpr::Path(
1245 Box::new(ValueExpr::VarRef(
1246 BindingsName::CaseInsensitive("data".into()),
1247 VarRefType::Local,
1248 )),
1249 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1250 "lhs".to_string().into(),
1251 ))],
1252 )),
1253 rhs: Box::new(ValueExpr::Lit(Box::new(rhs.into()))),
1254 }),
1255 )]),
1256 }));
1257
1258 let sink = plan.add_operator(BindingsOp::Sink);
1259 plan.extend_with_flows(&[(scan, project), (project, sink)]);
1260
1261 let mut bindings = MapBindings::default();
1262 bindings.insert("data", list![Tuple::from([("lhs", lhs)])].into());
1263
1264 let result = evaluate(plan, bindings).coerce_into_bag();
1265 assert!(!&result.is_empty());
1266 let expected_result = if expected_first_elem != Missing {
1267 bag!(Tuple::from([("result", expected_first_elem)]))
1268 } else {
1269 bag!(Tuple::new())
1271 };
1272 assert_eq!(expected_result, result);
1273 }
1274
1275 #[test]
1276 fn test_null_if_op() {
1277 eval_null_if_op(Value::from(1), Value::from(1), Value::Null);
1278 eval_null_if_op(Value::from(1), Value::from("foo"), Value::from(1));
1279 eval_null_if_op(Value::from("foo"), Value::from(1), Value::from("foo"));
1280 eval_null_if_op(Null, Null, Value::Null);
1281 eval_null_if_op(Missing, Null, Value::Missing);
1282 eval_null_if_op(Null, Missing, Value::Null);
1283 }
1284
1285 fn eval_coalesce_op(elements: Vec<Value>, expected_first_elem: Value) {
1289 let mut plan = LogicalPlan::new();
1290 let scan = plan.add_operator(BindingsOp::Scan(logical::Scan {
1291 expr: ValueExpr::VarRef(
1292 BindingsName::CaseInsensitive("data".into()),
1293 VarRefType::Global,
1294 ),
1295 as_key: "data".to_string(),
1296 at_key: None,
1297 }));
1298
1299 fn index_to_valueexpr(i: usize) -> ValueExpr {
1300 ValueExpr::Path(
1301 Box::new(ValueExpr::VarRef(
1302 BindingsName::CaseInsensitive("data".into()),
1303 VarRefType::Local,
1304 )),
1305 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1306 format!("arg{i}").into(),
1307 ))],
1308 )
1309 }
1310
1311 let project = plan.add_operator(Project(logical::Project {
1312 exprs: Vec::from([(
1313 "result".to_string(),
1314 ValueExpr::CoalesceExpr(CoalesceExpr {
1315 elements: (0..elements.len()).map(index_to_valueexpr).collect(),
1316 }),
1317 )]),
1318 }));
1319
1320 let sink = plan.add_operator(BindingsOp::Sink);
1321 plan.extend_with_flows(&[(scan, project), (project, sink)]);
1322
1323 let mut bindings = MapBindings::default();
1324 let mut data = Tuple::new();
1325 elements
1327 .into_iter()
1328 .enumerate()
1329 .for_each(|(i, e)| data.insert(&format!("arg{i}"), e));
1330 bindings.insert("data", list![data].into());
1331
1332 let result = evaluate(plan, bindings).coerce_into_bag();
1333 assert!(!&result.is_empty());
1334 assert_eq!(bag!(Tuple::from([("result", expected_first_elem)])), result);
1335 }
1336
1337 #[test]
1338 fn test_coalesce_op() {
1339 eval_coalesce_op(vec![Value::from(1)], Value::from(1));
1341 eval_coalesce_op(vec![Null], Null);
1342 eval_coalesce_op(vec![Missing], Null);
1343
1344 eval_coalesce_op(vec![Missing, Null, Value::from(1)], Value::from(1));
1346 eval_coalesce_op(vec![Missing, Null, Value::from(1)], Value::from(1));
1347 eval_coalesce_op(vec![Missing, Null, Null], Null);
1348 eval_coalesce_op(
1349 vec![
1350 Missing,
1351 Null,
1352 Missing,
1353 Null,
1354 Missing,
1355 Null,
1356 Value::from(1),
1357 Value::from(2),
1358 Missing,
1359 Null,
1360 ],
1361 Value::from(1),
1362 );
1363 eval_coalesce_op(
1364 vec![
1365 Missing, Null, Missing, Null, Missing, Null, Missing, Null, Missing, Null,
1366 ],
1367 Null,
1368 );
1369 }
1370
1371 #[test]
1372 fn expr_query() {
1373 let mut lg = LogicalPlan::new();
1374 let expq = lg.add_operator(BindingsOp::ExprQuery(ExprQuery {
1375 expr: ValueExpr::BinaryExpr(
1376 BinaryOp::Add,
1377 Box::new(ValueExpr::Lit(Box::new(40.into()))),
1378 Box::new(ValueExpr::Lit(Box::new(2.into()))),
1379 ),
1380 }));
1381
1382 let sink = lg.add_operator(BindingsOp::Sink);
1383
1384 lg.add_flow(expq, sink);
1385
1386 let out = evaluate(lg, MapBindings::default());
1387 println!("{:?}", &out);
1388 assert_matches!(out, Value::Integer(42));
1389 }
1390
1391 #[test]
1392 fn paths() {
1393 fn test(expr: ValueExpr, expected: Value) {
1394 let mut lg = LogicalPlan::new();
1395 let expq = lg.add_operator(BindingsOp::ExprQuery(ExprQuery { expr }));
1396
1397 let sink = lg.add_operator(BindingsOp::Sink);
1398 lg.add_flow(expq, sink);
1399
1400 let out = evaluate(lg, MapBindings::default());
1401 println!("{:?}", &out);
1402 assert_eq!(out, expected);
1403 }
1404 let list = ValueExpr::Lit(Box::new(Value::List(Box::new(list![1, 2, 3])).into()));
1405
1406 let index = ValueExpr::Path(Box::new(list.clone()), vec![PathComponent::Index(0)]);
1408 test(index, Value::Integer(1));
1409
1410 let index_expr = ValueExpr::BinaryExpr(
1412 BinaryOp::Add,
1413 Box::new(ValueExpr::Lit(Box::new(1.into()))),
1414 Box::new(ValueExpr::Lit(Box::new(1.into()))),
1415 );
1416 let index = ValueExpr::Path(
1417 Box::new(list),
1418 vec![PathComponent::IndexExpr(Box::new(index_expr))],
1419 );
1420 test(index, Value::Integer(3));
1421
1422 let tuple = ValueExpr::Lit(Box::new(Value::Tuple(Box::new(tuple![("a", 10)])).into()));
1424 let index_expr = ValueExpr::BinaryExpr(
1425 BinaryOp::Concat,
1426 Box::new(ValueExpr::Lit(Box::new("".into()))),
1427 Box::new(ValueExpr::Lit(Box::new("a".into()))),
1428 );
1429 let index = ValueExpr::Path(
1430 Box::new(tuple),
1431 vec![PathComponent::KeyExpr(Box::new(index_expr))],
1432 );
1433 test(index, Value::Integer(10));
1434 }
1435
1436 #[test]
1437 fn select() {
1438 let mut lg = LogicalPlan::new();
1439
1440 let from = lg.add_operator(scan("data", "data"));
1441
1442 let project = lg.add_operator(Project(logical::Project {
1443 exprs: Vec::from([(
1444 "b".to_string(),
1445 ValueExpr::Path(
1446 Box::new(ValueExpr::VarRef(
1447 BindingsName::CaseInsensitive("data".into()),
1448 VarRefType::Local,
1449 )),
1450 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1451 "a".to_string().into(),
1452 ))],
1453 ),
1454 )]),
1455 }));
1456
1457 let sink = lg.add_operator(BindingsOp::Sink);
1458
1459 lg.add_flow(from, project);
1460 lg.add_flow(project, sink);
1461
1462 let out = evaluate(lg, data_3_tuple());
1463 println!("{:?}", &out);
1464 assert_matches!(out, Value::Bag(bag) => {
1465 let expected = bag![
1466 tuple![("b", 1)],
1467 tuple![("b", 2)],
1468 tuple![("b", 3)],
1469 ];
1470 assert_eq!(*bag, expected);
1471 });
1472 }
1473
1474 #[test]
1475 fn select_star() {
1476 let mut lg = LogicalPlan::new();
1478
1479 let from = lg.add_operator(scan("data", "data"));
1480
1481 let project = lg.add_operator(ProjectAll(Default::default()));
1482
1483 let sink = lg.add_operator(BindingsOp::Sink);
1484
1485 lg.add_flow(from, project);
1486 lg.add_flow(project, sink);
1487
1488 let out = evaluate(lg, data_3_tuple());
1489 println!("{:?}", &out);
1490 assert_matches!(out, Value::Bag(bag) => {
1491 let expected = bag![
1492 tuple![("a", 1)],
1493 tuple![("a", 2)],
1494 tuple![("a", 3)],
1495 ];
1496 assert_eq!(*bag, expected);
1497 });
1498 }
1499
1500 #[test]
1505 fn select_value() {
1506 let mut lg = LogicalPlan::new();
1508
1509 let from = lg.add_operator(scan("data", "v"));
1510
1511 let va = path_var("v", "a");
1512 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1513 expr: ValueExpr::BinaryExpr(
1514 BinaryOp::Mul,
1515 Box::new(va),
1516 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
1517 ),
1518 }));
1519
1520 let sink = lg.add_operator(BindingsOp::Sink);
1521
1522 lg.add_flow(from, select_value);
1523 lg.add_flow(select_value, sink);
1524
1525 let out = evaluate(lg, data_3_tuple());
1526 println!("{:?}", &out);
1527 assert_matches!(out, Value::Bag(bag) => {
1528 let expected = bag![2, 4, 6];
1529 assert_eq!(*bag, expected);
1530 });
1531 }
1532
1533 #[test]
1538 fn select_value_tuple_constructor_1() {
1539 let mut lg = LogicalPlan::new();
1540
1541 let from = lg.add_operator(scan("data", "v"));
1542
1543 let va = path_var("v", "a");
1544 let vb = path_var("v", "b");
1545
1546 let mut tuple_expr = TupleExpr::new();
1547 tuple_expr.attrs.push(ValueExpr::Lit(Box::new("a".into())));
1548 tuple_expr.attrs.push(ValueExpr::Lit(Box::new("b".into())));
1549 tuple_expr.values.push(va);
1550 tuple_expr.values.push(vb);
1551
1552 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1553 expr: ValueExpr::TupleExpr(tuple_expr),
1554 }));
1555
1556 let sink = lg.add_operator(BindingsOp::Sink);
1557
1558 lg.add_flow(from, select_value);
1559 lg.add_flow(select_value, sink);
1560
1561 let data = bag![tuple![("a", 1), ("b", 1)], tuple![("a", 2), ("b", 2)],];
1562
1563 let mut bindings: MapBindings<Value> = MapBindings::default();
1564 bindings.insert("data", data.into());
1565
1566 let out = evaluate(lg, bindings);
1567 println!("{:?}", &out);
1568 assert_matches!(out, Value::Bag(bag) => {
1569 let expected = bag![
1570 tuple![("a", 1), ("b", 1)],
1571 tuple![("a", 2), ("b", 2)],
1572 ];
1573 assert_eq!(*bag, expected);
1574 });
1575 }
1576
1577 #[test]
1582 fn select_value_tuple_constructor_2() {
1583 let mut lg = LogicalPlan::new();
1584
1585 let from = lg.add_operator(scan("data", "v"));
1586
1587 let va = path_var("v", "a");
1588 let mut tuple_expr = TupleExpr::new();
1589 tuple_expr
1590 .attrs
1591 .push(ValueExpr::Lit(Box::new("test".into())));
1592 tuple_expr.values.push(ValueExpr::BinaryExpr(
1593 BinaryOp::Mul,
1594 Box::new(va),
1595 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
1596 ));
1597
1598 let project = lg.add_operator(ProjectValue(logical::ProjectValue {
1599 expr: ValueExpr::TupleExpr(tuple_expr),
1600 }));
1601
1602 let sink = lg.add_operator(BindingsOp::Sink);
1603
1604 lg.add_flow(from, project);
1605 lg.add_flow(project, sink);
1606
1607 let out = evaluate(lg, data_3_tuple());
1608 println!("{:?}", &out);
1609 assert_matches!(out, Value::Bag(bag) => {
1610 let expected = bag![
1611 tuple![("test", 2)],
1612 tuple![("test", 4)],
1613 tuple![("test", 6)],
1614 ];
1615 assert_eq!(*bag, expected);
1616 });
1617 }
1618
1619 #[test]
1624 fn select_value_with_tuple_mistype_attr() {
1625 let mut lg = LogicalPlan::new();
1626
1627 let from = lg.add_operator(scan("data", "v"));
1628
1629 let va = path_var("v", "a");
1630 let vb = path_var("v", "b");
1631
1632 let mut tuple_expr = TupleExpr::new();
1633 tuple_expr.attrs.push(va);
1634 tuple_expr.values.push(vb);
1635
1636 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1637 expr: ValueExpr::TupleExpr(tuple_expr),
1638 }));
1639
1640 let sink = lg.add_operator(BindingsOp::Sink);
1641
1642 lg.add_flow(from, select_value);
1643 lg.add_flow(select_value, sink);
1644
1645 let data = list![
1646 tuple![("a", "legit"), ("b", 1)],
1647 tuple![("a", 400), ("b", 2)],
1648 ];
1649
1650 let mut bindings: MapBindings<Value> = MapBindings::default();
1651 bindings.insert("data", data.into());
1652
1653 let out = evaluate(lg, bindings);
1654 println!("{:?}", &out);
1655 assert_matches!(out, Value::Bag(bag) => {
1656 let expected = bag![tuple![("legit", 1)], tuple![]];
1657 assert_eq!(*bag, expected);
1658 });
1659 }
1660
1661 #[test]
1666 fn select_value_with_duplicate_attrs() {
1667 let mut lg = LogicalPlan::new();
1668 let from = lg.add_operator(scan("data", "v"));
1669
1670 let va = path_var("v", "a");
1671 let vb = path_var("v", "b");
1672 let vc = path_var("v", "c");
1673 let vd = path_var("v", "d");
1674
1675 let mut tuple_expr = TupleExpr::new();
1676 tuple_expr.attrs.push(va);
1677 tuple_expr.values.push(vb);
1678 tuple_expr.attrs.push(vc);
1679 tuple_expr.values.push(vd);
1680
1681 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1682 expr: ValueExpr::TupleExpr(tuple_expr),
1683 }));
1684
1685 let sink = lg.add_operator(BindingsOp::Sink);
1686
1687 lg.add_flow(from, select_value);
1688 lg.add_flow(select_value, sink);
1689
1690 let data = list![tuple![("a", "same"), ("b", 1), ("c", "same"), ("d", 2)]];
1691
1692 let mut bindings: MapBindings<Value> = MapBindings::default();
1693 bindings.insert("data", data.into());
1694
1695 let out = evaluate(lg, bindings);
1696 println!("{:?}", &out);
1697 assert_matches!(out, Value::Bag(bag) => {
1698 let expected = bag![tuple![("same", 1), ("same", 2)]];
1699 assert_eq!(*bag, expected);
1700 });
1701 }
1702
1703 #[test]
1708 fn select_value_array_constructor_1() {
1709 let mut lg = LogicalPlan::new();
1710
1711 let from = lg.add_operator(scan("data", "v"));
1712
1713 let va = path_var("v", "a");
1714 let vb = path_var("v", "b");
1715
1716 let mut list_expr = ListExpr::new();
1717 list_expr.elements.push(va);
1718 list_expr.elements.push(vb);
1719
1720 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1721 expr: ValueExpr::ListExpr(list_expr),
1722 }));
1723
1724 let sink = lg.add_operator(BindingsOp::Sink);
1725
1726 lg.add_flow(from, select_value);
1727 lg.add_flow(select_value, sink);
1728
1729 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2), ("b", 2)],];
1730
1731 let mut bindings: MapBindings<Value> = MapBindings::default();
1732 bindings.insert("data", data.into());
1733
1734 let out = evaluate(lg, bindings);
1735 println!("{:?}", &out);
1736 assert_matches!(out, Value::Bag(bag) => {
1737 let expected = bag![list![1, 1], list![2, 2]];
1738 assert_eq!(*bag, expected);
1739 });
1740 }
1741
1742 #[test]
1747 fn select_value_with_array_constructor_2() {
1748 let mut lg = LogicalPlan::new();
1749
1750 let from = lg.add_operator(scan("data", "v"));
1751
1752 let va = path_var("v", "a");
1753 let mut list_expr = ListExpr::new();
1754 list_expr.elements.push(ValueExpr::BinaryExpr(
1755 BinaryOp::Mul,
1756 Box::new(va),
1757 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
1758 ));
1759
1760 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1761 expr: ValueExpr::ListExpr(list_expr),
1762 }));
1763
1764 let sink = lg.add_operator(BindingsOp::Sink);
1765
1766 lg.add_flow(from, select_value);
1767 lg.add_flow(select_value, sink);
1768
1769 let out = evaluate(lg, data_3_tuple());
1770 println!("{:?}", &out);
1771 assert_matches!(out, Value::Bag(bag) => {
1772 let expected = bag![list![2], list![4], list![6]];
1773 assert_eq!(*bag, expected);
1774 });
1775 }
1776
1777 #[test]
1782 fn select_value_bag_constructor() {
1783 let mut lg = LogicalPlan::new();
1784
1785 let from = lg.add_operator(scan("data", "v"));
1786
1787 let va = path_var("v", "a");
1788 let vb = path_var("v", "b");
1789
1790 let mut bag_expr = BagExpr::new();
1791 bag_expr.elements.push(va);
1792 bag_expr.elements.push(vb);
1793
1794 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1795 expr: ValueExpr::BagExpr(bag_expr),
1796 }));
1797
1798 let sink = lg.add_operator(BindingsOp::Sink);
1799
1800 lg.add_flow(from, select_value);
1801 lg.add_flow(select_value, sink);
1802
1803 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2), ("b", 2)],];
1804
1805 let mut bindings: MapBindings<Value> = MapBindings::default();
1806 bindings.insert("data", data.into());
1807
1808 let out = evaluate(lg, bindings);
1809 println!("{:?}", &out);
1810 assert_matches!(out, Value::Bag(bag) => {
1811 let expected = bag![bag![1, 1], bag![2, 2]];
1812 assert_eq!(*bag, expected);
1813 });
1814 }
1815
1816 #[test]
1821 fn missing_in_select_value_for_tuple() {
1822 let mut lg = LogicalPlan::new();
1823 let from = lg.add_operator(scan("data", "v"));
1824
1825 let va = path_var("v", "a");
1826 let vb = path_var("v", "b");
1827
1828 let mut tuple_expr = TupleExpr::new();
1829 tuple_expr.attrs.push(ValueExpr::Lit(Box::new("a".into())));
1830 tuple_expr.values.push(va);
1831 tuple_expr.attrs.push(ValueExpr::Lit(Box::new("b".into())));
1832 tuple_expr.values.push(vb);
1833
1834 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1835 expr: ValueExpr::TupleExpr(tuple_expr),
1836 }));
1837
1838 let sink = lg.add_operator(BindingsOp::Sink);
1839
1840 lg.add_flow(from, select_value);
1841 lg.add_flow(select_value, sink);
1842
1843 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2)]];
1844
1845 let mut bindings: MapBindings<Value> = MapBindings::default();
1846 bindings.insert("data", data.into());
1847
1848 let out = evaluate(lg, bindings);
1849 println!("{:?}", &out);
1850 assert_matches!(out, Value::Bag(bag) => {
1851 let expected =
1852 bag![tuple![("a", 1), ("b", 1)], tuple![("a", 2)],];
1853 assert_eq!(*bag, expected);
1854 });
1855 }
1856
1857 #[test]
1862 fn missing_in_select_value_for_list() {
1863 let mut lg = LogicalPlan::new();
1864 let from = lg.add_operator(scan("data", "v"));
1865
1866 let va = path_var("v", "a");
1867 let vb = path_var("v", "b");
1868
1869 let mut list_expr = ListExpr::new();
1870 list_expr.elements.push(va);
1871 list_expr.elements.push(vb);
1872
1873 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1874 expr: ValueExpr::ListExpr(list_expr),
1875 }));
1876
1877 let sink = lg.add_operator(BindingsOp::Sink);
1878
1879 lg.add_flow(from, select_value);
1880 lg.add_flow(select_value, sink);
1881
1882 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2)]];
1883
1884 let mut bindings: MapBindings<Value> = MapBindings::default();
1885 bindings.insert("data", data.into());
1886
1887 let out = evaluate(lg, bindings);
1888 println!("{:?}", &out);
1889 assert_matches!(out, Value::Bag(bag) => {
1890 let expected = bag![list![1, 1], list![2, Value::Missing]];
1891 assert_eq!(*bag, expected);
1892 });
1893 }
1894
1895 #[test]
1900 fn missing_in_select_value_for_bag_1() {
1901 let mut lg = LogicalPlan::new();
1902 let from = lg.add_operator(scan("data", "v"));
1903
1904 let vb = path_var("v", "b");
1905
1906 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue { expr: vb }));
1907
1908 let sink = lg.add_operator(BindingsOp::Sink);
1909
1910 lg.add_flow(from, select_value);
1911 lg.add_flow(select_value, sink);
1912
1913 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2)]];
1914
1915 let mut bindings: MapBindings<Value> = MapBindings::default();
1916 bindings.insert("data", data.into());
1917
1918 let out = evaluate(lg, bindings);
1919 println!("{:?}", &out);
1920 assert_matches!(out, Value::Bag(bag) => {
1921 let expected = bag![1, Value::Missing];
1922 assert_eq!(*bag, expected);
1923 });
1924 }
1925
1926 #[test]
1931 fn missing_in_select_value_for_bag_2() {
1932 let mut lg = LogicalPlan::new();
1933 let from = lg.add_operator(scan("data", "v"));
1934
1935 let va = path_var("v", "a");
1936 let vb = path_var("v", "b");
1937
1938 let mut bag_expr = BagExpr::new();
1939 bag_expr.elements.push(va);
1940 bag_expr.elements.push(vb);
1941
1942 let select_value = lg.add_operator(ProjectValue(logical::ProjectValue {
1943 expr: ValueExpr::BagExpr(bag_expr),
1944 }));
1945
1946 let sink = lg.add_operator(BindingsOp::Sink);
1947
1948 lg.add_flow(from, select_value);
1949 lg.add_flow(select_value, sink);
1950
1951 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2)]];
1952
1953 let mut bindings: MapBindings<Value> = MapBindings::default();
1954 bindings.insert("data", data.into());
1955
1956 let out = evaluate(lg, bindings);
1957 println!("{:?}", &out);
1958 assert_matches!(out, Value::Bag(bag) => {
1959 let expected = bag![bag![1, 1], bag![2, Value::Missing]];
1960 assert_eq!(*bag, expected);
1961 });
1962 }
1963
1964 #[test]
1965 fn select_distinct() {
1966 let mut logical = LogicalPlan::new();
1968
1969 let scan = logical.add_operator(scan("customer", "customer"));
1970
1971 let filter = logical.add_operator(BindingsOp::Filter(logical::Filter {
1972 expr: ValueExpr::BinaryExpr(
1973 BinaryOp::Gt,
1974 Box::new(ValueExpr::Path(
1975 Box::new(ValueExpr::VarRef(
1976 BindingsName::CaseInsensitive("customer".into()),
1977 VarRefType::Local,
1978 )),
1979 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1980 "balance".to_string().into(),
1981 ))],
1982 )),
1983 Box::new(ValueExpr::Lit(Box::new(Value::Integer(0).into()))),
1984 ),
1985 }));
1986
1987 let project = logical.add_operator(Project(logical::Project {
1988 exprs: Vec::from([
1989 (
1990 "firstName".to_string(),
1991 ValueExpr::Path(
1992 Box::new(ValueExpr::VarRef(
1993 BindingsName::CaseInsensitive("customer".into()),
1994 VarRefType::Local,
1995 )),
1996 vec![PathComponent::Key(BindingsName::CaseInsensitive(
1997 "firstName".to_string().into(),
1998 ))],
1999 ),
2000 ),
2001 (
2002 "doubleName".to_string(),
2003 ValueExpr::BinaryExpr(
2004 BinaryOp::Concat,
2005 Box::new(ValueExpr::Path(
2006 Box::new(ValueExpr::VarRef(
2007 BindingsName::CaseInsensitive("customer".into()),
2008 VarRefType::Local,
2009 )),
2010 vec![PathComponent::Key(BindingsName::CaseInsensitive(
2011 "firstName".to_string().into(),
2012 ))],
2013 )),
2014 Box::new(ValueExpr::Path(
2015 Box::new(ValueExpr::VarRef(
2016 BindingsName::CaseInsensitive("customer".into()),
2017 VarRefType::Local,
2018 )),
2019 vec![PathComponent::Key(BindingsName::CaseInsensitive(
2020 "firstName".to_string().into(),
2021 ))],
2022 )),
2023 ),
2024 ),
2025 ]),
2026 }));
2027
2028 let distinct = logical.add_operator(Distinct);
2029 let sink = logical.add_operator(BindingsOp::Sink);
2030
2031 logical.extend_with_flows(&[
2032 (scan, filter),
2033 (filter, project),
2034 (project, distinct),
2035 (distinct, sink),
2036 ]);
2037
2038 let out = evaluate(logical, data_customer());
2039 println!("{:?}", &out);
2040 assert_matches!(out, Value::Bag(bag) => {
2041 let expected = bag![
2042 tuple![("firstName", "jason"), ("doubleName", "jasonjason")],
2043 tuple![("firstName", "miriam"), ("doubleName", "miriammiriam")],
2044 ];
2045 assert_eq!(*bag, expected);
2046 });
2047 }
2048
2049 #[test]
2050 fn select_with_in_as_predicate() {
2051 let mut logical = LogicalPlan::new();
2053
2054 let scan = logical.add_operator(scan("data", "data"));
2055
2056 let filter = logical.add_operator(BindingsOp::Filter(logical::Filter {
2057 expr: ValueExpr::BinaryExpr(
2058 BinaryOp::In,
2059 Box::new(ValueExpr::Path(
2060 Box::new(ValueExpr::VarRef(
2061 BindingsName::CaseInsensitive("data".into()),
2062 VarRefType::Local,
2063 )),
2064 vec![PathComponent::Key(BindingsName::CaseInsensitive(
2065 "a".to_string().into(),
2066 ))],
2067 )),
2068 Box::new(ValueExpr::Lit(Box::new(list![1].into()))),
2069 ),
2070 }));
2071
2072 let project = logical.add_operator(Project(logical::Project {
2073 exprs: Vec::from([(
2074 "b".to_string(),
2075 ValueExpr::Path(
2076 Box::new(ValueExpr::VarRef(
2077 BindingsName::CaseInsensitive("data".into()),
2078 VarRefType::Local,
2079 )),
2080 vec![PathComponent::Key(BindingsName::CaseInsensitive(
2081 "a".to_string().into(),
2082 ))],
2083 ),
2084 )]),
2085 }));
2086
2087 let sink = logical.add_operator(BindingsOp::Sink);
2088
2089 logical.extend_with_flows(&[(scan, filter), (filter, project), (project, sink)]);
2090
2091 let out = evaluate(logical, data_3_tuple());
2092 println!("{:?}", &out);
2093 assert_matches!(out, Value::Bag(bag) => {
2094 let expected = bag![
2095 tuple![("b", 1)],
2096 ];
2097 assert_eq!(*bag, expected);
2098 });
2099 }
2100
2101 #[test]
2102 fn subquery_in_from() {
2103 let mut subq_plan = LogicalPlan::new();
2105 let subq_scan = subq_plan.add_operator(scan("t", "v"));
2106 let va = path_var("v", "a");
2107 let subq_project = subq_plan.add_operator(Project(logical::Project {
2108 exprs: Vec::from([(
2109 "u".to_string(),
2110 ValueExpr::BinaryExpr(
2111 BinaryOp::Mul,
2112 Box::new(va),
2113 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
2114 ),
2115 )]),
2116 }));
2117 let subq_sink = subq_plan.add_operator(BindingsOp::Sink);
2118
2119 subq_plan.add_flow(subq_scan, subq_project);
2120 subq_plan.add_flow(subq_project, subq_sink);
2121
2122 let mut lg = LogicalPlan::new();
2123
2124 let from_lhs = scan("data", "t");
2125 let from_rhs = BindingsOp::Scan(logical::Scan {
2126 expr: ValueExpr::SubQueryExpr(logical::SubQueryExpr { plan: subq_plan }),
2127 as_key: "s".to_string(),
2128 at_key: None,
2129 });
2130
2131 let join = lg.add_operator(BindingsOp::Join(logical::Join {
2132 kind: JoinKind::Cross,
2133 left: Box::new(from_lhs),
2134 right: Box::new(from_rhs),
2135 on: None,
2136 }));
2137
2138 let ta = path_var("t", "a");
2139 let su = path_var("s", "u");
2140 let project = lg.add_operator(Project(logical::Project {
2141 exprs: Vec::from([("ta".to_string(), ta), ("su".to_string(), su)]),
2142 }));
2143
2144 let sink = lg.add_operator(BindingsOp::Sink);
2145
2146 lg.add_flow_with_branch_num(join, project, 0);
2147 lg.add_flow_with_branch_num(project, sink, 0);
2148
2149 let data = list![tuple![("a", 1)], tuple![("a", 2)], tuple![("a", 3)],];
2150
2151 let mut bindings: MapBindings<Value> = MapBindings::default();
2152 bindings.insert("data", data.into());
2153
2154 let out = evaluate(lg, bindings);
2155 println!("{:?}", &out);
2156 assert_matches!(out, Value::Bag(bag) => {
2157 let expected = bag![
2158 tuple![
2159 ("ta", 1),
2160 ("su", 2),
2161 ],
2162 tuple![
2163 ("ta", 2),
2164 ("su", 4),
2165 ],
2166 tuple![
2167 ("ta", 3),
2168 ("su", 6),
2169 ],
2170 ];
2171 assert_eq!(*bag, expected);
2172 });
2173 }
2174
2175 #[test]
2176 fn subquery_in_project() {
2177 let mut subq_plan = LogicalPlan::new();
2179 let subq_scan = subq_plan.add_operator(scan("t", "v"));
2180 let va = path_var("v", "a");
2181 let subq_project = subq_plan.add_operator(Project(logical::Project {
2182 exprs: Vec::from([(
2183 "u".to_string(),
2184 ValueExpr::BinaryExpr(
2185 BinaryOp::Mul,
2186 Box::new(va),
2187 Box::new(ValueExpr::Lit(Box::new(Value::Integer(2).into()))),
2188 ),
2189 )]),
2190 }));
2191 let subq_sink = subq_plan.add_operator(BindingsOp::Sink);
2192
2193 subq_plan.add_flow(subq_scan, subq_project);
2194 subq_plan.add_flow(subq_project, subq_sink);
2195
2196 let mut lg = LogicalPlan::new();
2197 let from = lg.add_operator(scan("data", "t"));
2198 let ta = path_var("t", "a");
2199 let project = lg.add_operator(Project(logical::Project {
2200 exprs: Vec::from([
2201 ("ta".to_string(), ta),
2202 (
2203 "s".to_string(),
2204 ValueExpr::SubQueryExpr(logical::SubQueryExpr { plan: subq_plan }),
2205 ),
2206 ]),
2207 }));
2208
2209 let sink = lg.add_operator(BindingsOp::Sink);
2210
2211 lg.add_flow(from, project);
2212 lg.add_flow(project, sink);
2213
2214 let data = list![tuple![("a", 1), ("b", 1)], tuple![("a", 2), ("b", 2)]];
2215
2216 let mut bindings: MapBindings<Value> = MapBindings::default();
2217 bindings.insert("data", data.into());
2218
2219 let out = evaluate(lg, bindings);
2220 println!("{:?}", &out);
2221 assert_matches!(out, Value::Bag(bag) => {
2222 let expected = bag![
2223 tuple![
2224 ("ta", 1),
2225 ("s", bag![tuple![("u", 2)]]),
2226 ],
2227 tuple![
2228 ("ta", 2),
2229 ("s", bag![tuple![("u", 4)]]),
2230 ],
2231 ];
2232 assert_eq!(*bag, expected);
2233 });
2234 }
2235
2236 mod clause_from {
2237 use crate::eval::evaluable::{EvalScan, Evaluable};
2238 use crate::eval::expr::{EvalGlobalVarRef, EvalPath, EvalPathComponent};
2239 use crate::eval::BasicContext;
2240 use partiql_catalog::context::SystemContext;
2241 use partiql_value::{bag, list, BindingsName, DateTime};
2242
2243 use super::*;
2244
2245 fn some_ordered_table() -> List {
2246 list![tuple![("a", 0), ("b", 0)], tuple![("a", 1), ("b", 1)],]
2247 }
2248
2249 fn some_unordered_table() -> Bag {
2250 Bag::from(some_ordered_table())
2251 }
2252
2253 #[test]
2255 fn basic() {
2256 let mut p0: MapBindings<Value> = MapBindings::default();
2257 p0.insert("someOrderedTable", some_ordered_table().into());
2258
2259 let sys = SystemContext {
2260 now: DateTime::from_system_now_utc(),
2261 };
2262 let ctx = BasicContext::new(p0, sys);
2263
2264 let scan = EvalScan::new_with_at_key(
2265 Box::new(EvalGlobalVarRef {
2266 name: BindingsName::CaseInsensitive("someOrderedTable".to_string().into()),
2267 }),
2268 "x",
2269 "y",
2270 );
2271
2272 let res = scan.evaluate([None, None], &ctx);
2273
2274 let expected = bag![
2276 tuple![("x", tuple![("a", 0), ("b", 0)]), ("y", 0)],
2277 tuple![("x", tuple![("a", 1), ("b", 1)]), ("y", 1)],
2278 ];
2279 assert_eq!(Value::Bag(Box::new(expected)), res);
2280 }
2281
2282 #[test]
2284 fn mistype_at_on_bag() {
2285 let mut p0: MapBindings<Value> = MapBindings::default();
2286 p0.insert("someUnorderedTable", some_unordered_table().into());
2287
2288 let sys = SystemContext {
2289 now: DateTime::from_system_now_utc(),
2290 };
2291 let ctx = BasicContext::new(p0, sys);
2292
2293 let scan = EvalScan::new_with_at_key(
2294 Box::new(EvalGlobalVarRef {
2295 name: BindingsName::CaseInsensitive("someUnorderedTable".to_string().into()),
2296 }),
2297 "x",
2298 "y",
2299 );
2300
2301 let res = scan.evaluate([None, None], &ctx);
2302
2303 let expected = bag![
2305 tuple![
2306 ("x", tuple![("a", 0), ("b", 0)]),
2307 ("y", value::Value::Missing)
2308 ],
2309 tuple![
2310 ("x", tuple![("a", 1), ("b", 1)]),
2311 ("y", value::Value::Missing)
2312 ],
2313 ];
2314 assert_eq!(Value::Bag(Box::new(expected)), res);
2315 }
2316
2317 #[test]
2319 fn mistype_scalar() {
2320 let mut p0: MapBindings<Value> = MapBindings::default();
2321 p0.insert("someOrderedTable", some_ordered_table().into());
2322
2323 let table_ref = EvalGlobalVarRef {
2324 name: BindingsName::CaseInsensitive("someOrderedTable".to_string().into()),
2325 };
2326 let path_to_scalar = EvalPath {
2327 expr: Box::new(table_ref),
2328 components: vec![
2329 EvalPathComponent::Index(0),
2330 EvalPathComponent::Key(BindingsName::CaseInsensitive("a".into())),
2331 ],
2332 };
2333 let scan = EvalScan::new(Box::new(path_to_scalar), "x");
2334
2335 let sys = SystemContext {
2336 now: DateTime::from_system_now_utc(),
2337 };
2338 let ctx = BasicContext::new(p0, sys);
2339 let scan_res = scan.evaluate([None, None], &ctx);
2340
2341 let expected = bag![tuple![("x", 0)]];
2342 assert_eq!(Value::Bag(Box::new(expected)), scan_res);
2343 }
2344
2345 #[test]
2347 fn mistype_absent() {
2348 let mut p0: MapBindings<Value> = MapBindings::default();
2349 p0.insert("someOrderedTable", some_ordered_table().into());
2350
2351 let table_ref = EvalGlobalVarRef {
2352 name: BindingsName::CaseInsensitive("someOrderedTable".to_string().into()),
2353 };
2354 let path_to_scalar = EvalPath {
2355 expr: Box::new(table_ref),
2356 components: vec![
2357 EvalPathComponent::Index(0),
2358 EvalPathComponent::Key(BindingsName::CaseInsensitive("c".into())),
2359 ],
2360 };
2361 let scan = EvalScan::new(Box::new(path_to_scalar), "x");
2362
2363 let sys = SystemContext {
2364 now: DateTime::from_system_now_utc(),
2365 };
2366 let ctx = BasicContext::new(p0, sys);
2367 let res = scan.evaluate([None, None], &ctx);
2368
2369 let expected = bag![tuple![("x", value::Value::Missing)]];
2370 assert_eq!(Value::Bag(Box::new(expected)), res);
2371 }
2372 }
2373
2374 mod clause_unpivot {
2375 use partiql_value::{bag, BindingsName, DateTime, Tuple};
2376
2377 use crate::eval::evaluable::{EvalUnpivot, Evaluable};
2378 use crate::eval::expr::EvalGlobalVarRef;
2379 use crate::eval::BasicContext;
2380
2381 use super::*;
2382
2383 fn just_a_tuple() -> Tuple {
2384 tuple![("amzn", 840.05), ("tdc", 31.06)]
2385 }
2386
2387 #[test]
2389 fn basic() {
2390 let mut p0: MapBindings<Value> = MapBindings::default();
2391 p0.insert("justATuple", just_a_tuple().into());
2392
2393 let unpivot = EvalUnpivot::new(
2394 Box::new(EvalGlobalVarRef {
2395 name: BindingsName::CaseInsensitive("justATuple".to_string().into()),
2396 }),
2397 "price",
2398 Some("symbol".into()),
2399 );
2400
2401 let sys = SystemContext {
2402 now: DateTime::from_system_now_utc(),
2403 };
2404 let ctx = BasicContext::new(p0, sys);
2405 let res = unpivot.evaluate([None, None], &ctx);
2406
2407 let expected = bag![
2408 tuple![("symbol", "tdc"), ("price", 31.06)],
2409 tuple![("symbol", "amzn"), ("price", 840.05)],
2410 ];
2411 assert_eq!(Value::Bag(Box::new(expected)), res);
2412 }
2413
2414 #[test]
2416 fn mistype_non_tuple() {
2417 let mut p0: MapBindings<Value> = MapBindings::default();
2418 p0.insert("nonTuple", Value::from(1));
2419
2420 let unpivot = EvalUnpivot::new(
2421 Box::new(EvalGlobalVarRef {
2422 name: BindingsName::CaseInsensitive("nonTuple".to_string().into()),
2423 }),
2424 "x",
2425 Some("y".into()),
2426 );
2427
2428 let sys = SystemContext {
2429 now: DateTime::from_system_now_utc(),
2430 };
2431 let ctx = BasicContext::new(p0, sys);
2432 let res = unpivot.evaluate([None, None], &ctx);
2433
2434 let expected = bag![tuple![("x", 1), ("y", "_1")]];
2435 assert_eq!(Value::Bag(Box::new(expected)), res);
2436 }
2437 }
2438}