@@ -17,8 +17,8 @@ mod tests {
17
17
use partiql_logical as logical;
18
18
use partiql_logical:: BindingsExpr :: { Distinct , Project , ProjectValue } ;
19
19
use partiql_logical:: {
20
- BagExpr , BinaryOp , BindingsExpr , JoinKind , ListExpr , LogicalPlan , PathComponent , TupleExpr ,
21
- ValueExpr ,
20
+ BagExpr , BetweenExpr , BinaryOp , BindingsExpr , JoinKind , ListExpr , LogicalPlan ,
21
+ PathComponent , TupleExpr , ValueExpr ,
22
22
} ;
23
23
use partiql_value as value;
24
24
use partiql_value:: {
@@ -470,6 +470,200 @@ mod tests {
470
470
}
471
471
472
472
#[ test]
473
+ fn comparison_ops ( ) {
474
+ // Lt
475
+ // Plan for `select lhs < rhs as result from data`
476
+ eval_bin_op (
477
+ BinaryOp :: Lt ,
478
+ Value :: from ( 1 ) ,
479
+ Value :: from ( 2. ) ,
480
+ Value :: from ( true ) ,
481
+ ) ;
482
+ eval_bin_op (
483
+ BinaryOp :: Lt ,
484
+ Value :: from ( "abc" ) ,
485
+ Value :: from ( "def" ) ,
486
+ Value :: from ( true ) ,
487
+ ) ;
488
+ eval_bin_op (
489
+ BinaryOp :: Lt ,
490
+ Value :: Missing ,
491
+ Value :: from ( 2. ) ,
492
+ Value :: Missing ,
493
+ ) ;
494
+ eval_bin_op ( BinaryOp :: Lt , Value :: Null , Value :: from ( 2. ) , Value :: Null ) ;
495
+ eval_bin_op (
496
+ BinaryOp :: Lt ,
497
+ Value :: from ( 1 ) ,
498
+ Value :: from ( "foo" ) ,
499
+ Value :: Missing ,
500
+ ) ;
501
+
502
+ // Gt
503
+ // Plan for `select lhs > rhs as result from data`
504
+ eval_bin_op (
505
+ BinaryOp :: Gt ,
506
+ Value :: from ( 1 ) ,
507
+ Value :: from ( 2. ) ,
508
+ Value :: from ( false ) ,
509
+ ) ;
510
+ eval_bin_op (
511
+ BinaryOp :: Gt ,
512
+ Value :: from ( "abc" ) ,
513
+ Value :: from ( "def" ) ,
514
+ Value :: from ( false ) ,
515
+ ) ;
516
+ eval_bin_op (
517
+ BinaryOp :: Gt ,
518
+ Value :: Missing ,
519
+ Value :: from ( 2. ) ,
520
+ Value :: Missing ,
521
+ ) ;
522
+ eval_bin_op ( BinaryOp :: Gt , Value :: Null , Value :: from ( 2. ) , Value :: Null ) ;
523
+ eval_bin_op (
524
+ BinaryOp :: Gt ,
525
+ Value :: from ( 1 ) ,
526
+ Value :: from ( "foo" ) ,
527
+ Value :: Missing ,
528
+ ) ;
529
+
530
+ // Lteq
531
+ // Plan for `select lhs <= rhs as result from data`
532
+ eval_bin_op (
533
+ BinaryOp :: Lteq ,
534
+ Value :: from ( 1 ) ,
535
+ Value :: from ( 2. ) ,
536
+ Value :: from ( true ) ,
537
+ ) ;
538
+ eval_bin_op (
539
+ BinaryOp :: Lteq ,
540
+ Value :: from ( "abc" ) ,
541
+ Value :: from ( "def" ) ,
542
+ Value :: from ( true ) ,
543
+ ) ;
544
+ eval_bin_op (
545
+ BinaryOp :: Lteq ,
546
+ Value :: Missing ,
547
+ Value :: from ( 2. ) ,
548
+ Value :: Missing ,
549
+ ) ;
550
+ eval_bin_op ( BinaryOp :: Lt , Value :: Null , Value :: from ( 2. ) , Value :: Null ) ;
551
+ eval_bin_op (
552
+ BinaryOp :: Lteq ,
553
+ Value :: from ( 1 ) ,
554
+ Value :: from ( "foo" ) ,
555
+ Value :: Missing ,
556
+ ) ;
557
+
558
+ // Gteq
559
+ // Plan for `select lhs >= rhs as result from data`
560
+ eval_bin_op (
561
+ BinaryOp :: Gteq ,
562
+ Value :: from ( 1 ) ,
563
+ Value :: from ( 2. ) ,
564
+ Value :: from ( false ) ,
565
+ ) ;
566
+ eval_bin_op (
567
+ BinaryOp :: Gteq ,
568
+ Value :: from ( "abc" ) ,
569
+ Value :: from ( "def" ) ,
570
+ Value :: from ( false ) ,
571
+ ) ;
572
+ eval_bin_op (
573
+ BinaryOp :: Gteq ,
574
+ Value :: Missing ,
575
+ Value :: from ( 2. ) ,
576
+ Value :: Missing ,
577
+ ) ;
578
+ eval_bin_op ( BinaryOp :: Gteq , Value :: Null , Value :: from ( 2. ) , Value :: Null ) ;
579
+ eval_bin_op (
580
+ BinaryOp :: Gteq ,
581
+ Value :: from ( 1 ) ,
582
+ Value :: from ( "foo" ) ,
583
+ Value :: Missing ,
584
+ ) ;
585
+ }
586
+
587
+ #[ test]
588
+ fn between_op ( ) {
589
+ fn eval_between_op ( value : Value , from : Value , to : Value , expected_first_elem : Value ) {
590
+ let mut plan = LogicalPlan :: new ( ) ;
591
+ let scan = plan. add_operator ( BindingsExpr :: Scan ( logical:: Scan {
592
+ expr : ValueExpr :: VarRef ( BindingsName :: CaseInsensitive ( "data" . into ( ) ) ) ,
593
+ as_key : "data" . to_string ( ) ,
594
+ at_key : None ,
595
+ } ) ) ;
596
+
597
+ let project = plan. add_operator ( Project ( logical:: Project {
598
+ exprs : HashMap :: from ( [ (
599
+ "result" . to_string ( ) ,
600
+ ValueExpr :: BetweenExpr ( BetweenExpr {
601
+ value : Box :: new ( ValueExpr :: Path (
602
+ Box :: new ( ValueExpr :: VarRef ( BindingsName :: CaseInsensitive (
603
+ "data" . into ( ) ,
604
+ ) ) ) ,
605
+ vec ! [ PathComponent :: Key ( "value" . to_string( ) ) ] ,
606
+ ) ) ,
607
+ from : Box :: new ( ValueExpr :: Lit ( Box :: new ( from) ) ) ,
608
+ to : Box :: new ( ValueExpr :: Lit ( Box :: new ( to) ) ) ,
609
+ } ) ,
610
+ ) ] ) ,
611
+ } ) ) ;
612
+
613
+ let sink = plan. add_operator ( BindingsExpr :: Sink ) ;
614
+ plan. extend_with_flows ( & [ ( scan, project) , ( project, sink) ] ) ;
615
+
616
+ let mut bindings = MapBindings :: default ( ) ;
617
+ bindings. insert (
618
+ "data" ,
619
+ partiql_list ! [ Tuple :: from( [ ( "value" . into( ) , value) ] ) ] . into ( ) ,
620
+ ) ;
621
+
622
+ let result = evaluate ( plan, bindings) . coerce_to_bag ( ) ;
623
+ assert ! ( !& result. is_empty( ) ) ;
624
+ let expected_result =
625
+ partiql_bag ! ( Tuple :: from( [ ( "result" . into( ) , expected_first_elem) ] ) ) ;
626
+ assert_eq ! ( expected_result, result) ;
627
+ }
628
+ eval_between_op (
629
+ Value :: from ( 2 ) ,
630
+ Value :: from ( 1 ) ,
631
+ Value :: from ( 3 ) ,
632
+ Value :: from ( true ) ,
633
+ ) ;
634
+ eval_between_op (
635
+ Value :: from ( 2 ) ,
636
+ Value :: from ( 1. ) ,
637
+ Value :: from ( dec ! ( 3. ) ) ,
638
+ Value :: from ( true ) ,
639
+ ) ;
640
+ eval_between_op (
641
+ Value :: from ( 1 ) ,
642
+ Value :: from ( 2 ) ,
643
+ Value :: from ( 3 ) ,
644
+ Value :: from ( false ) ,
645
+ ) ;
646
+ eval_between_op ( Value :: Null , Value :: from ( 1 ) , Value :: from ( 3 ) , Value :: Null ) ;
647
+ eval_between_op ( Value :: from ( 2 ) , Value :: Null , Value :: from ( 3 ) , Value :: Null ) ;
648
+ eval_between_op ( Value :: from ( 2 ) , Value :: from ( 1 ) , Value :: Null , Value :: Null ) ;
649
+ eval_between_op ( Value :: Missing , Value :: from ( 1 ) , Value :: from ( 3 ) , Value :: Null ) ;
650
+ eval_between_op ( Value :: from ( 2 ) , Value :: Missing , Value :: from ( 3 ) , Value :: Null ) ;
651
+ eval_between_op ( Value :: from ( 2 ) , Value :: from ( 1 ) , Value :: Missing , Value :: Null ) ;
652
+ // left part of AND evaluates to false
653
+ eval_between_op (
654
+ Value :: from ( 1 ) ,
655
+ Value :: from ( 2 ) ,
656
+ Value :: Null ,
657
+ Value :: from ( false ) ,
658
+ ) ;
659
+ eval_between_op (
660
+ Value :: from ( 1 ) ,
661
+ Value :: from ( 2 ) ,
662
+ Value :: Missing ,
663
+ Value :: from ( false ) ,
664
+ ) ;
665
+ }
666
+
473
667
fn select_with_cross_join ( ) {
474
668
let mut lg = LogicalPlan :: new ( ) ;
475
669
0 commit comments