1
1
use super :: {
2
2
plan:: {
3
- Aggregate , JoinInfo , Operation , Plan , ResultSetColumn , SelectPlan , SelectQueryType ,
3
+ Aggregate , EvalAt , JoinInfo , Operation , Plan , ResultSetColumn , SelectPlan , SelectQueryType ,
4
4
TableReference , WhereTerm ,
5
5
} ,
6
6
select:: prepare_select_plan,
@@ -534,11 +534,11 @@ pub fn parse_where(
534
534
bind_column_references ( expr, table_references, result_columns) ?;
535
535
}
536
536
for expr in predicates {
537
- let eval_at_loop = get_rightmost_table_referenced_in_expr ( & expr) ?;
537
+ let eval_at = determine_where_to_eval_expr ( & expr) ?;
538
538
out_where_clause. push ( WhereTerm {
539
539
expr,
540
540
from_outer_join : false ,
541
- eval_at_loop ,
541
+ eval_at ,
542
542
} ) ;
543
543
}
544
544
Ok ( ( ) )
@@ -554,48 +554,118 @@ pub fn parse_where(
554
554
and it needs to be the rightmost table referenced in the expression, because otherwise
555
555
the condition would be evaluated before a row is read from that table.
556
556
*/
557
- fn get_rightmost_table_referenced_in_expr < ' a > ( predicate : & ' a ast:: Expr ) -> Result < usize > {
558
- let mut max_table_idx = 0 ;
557
+ fn determine_where_to_eval_expr < ' a > ( predicate : & ' a ast:: Expr ) -> Result < EvalAt > {
558
+ let mut eval_at : EvalAt = EvalAt :: BeforeLoop ;
559
559
match predicate {
560
560
ast:: Expr :: Binary ( e1, _, e2) => {
561
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( e1) ?) ;
562
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( e2) ?) ;
561
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( e1) ?) ;
562
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( e2) ?) ;
563
563
}
564
- ast:: Expr :: Column { table, .. } => {
565
- max_table_idx = max_table_idx . max ( * table) ;
564
+ ast:: Expr :: Column { table, .. } | ast :: Expr :: RowId { table , .. } => {
565
+ eval_at = eval_at . max ( EvalAt :: Loop ( * table) ) ;
566
566
}
567
567
ast:: Expr :: Id ( _) => {
568
568
/* Id referring to column will already have been rewritten as an Expr::Column */
569
569
/* we only get here with literal 'true' or 'false' etc */
570
570
}
571
571
ast:: Expr :: Qualified ( _, _) => {
572
- unreachable ! ( "Qualified should be resolved to a Column before optimizer " )
572
+ unreachable ! ( "Qualified should be resolved to a Column before resolving eval_at " )
573
573
}
574
574
ast:: Expr :: Literal ( _) => { }
575
575
ast:: Expr :: Like { lhs, rhs, .. } => {
576
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( lhs) ?) ;
577
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( rhs) ?) ;
576
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( lhs) ?) ;
577
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( rhs) ?) ;
578
578
}
579
579
ast:: Expr :: FunctionCall {
580
580
args : Some ( args) , ..
581
581
} => {
582
582
for arg in args {
583
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( arg) ?) ;
583
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( arg) ?) ;
584
584
}
585
585
}
586
586
ast:: Expr :: InList { lhs, rhs, .. } => {
587
- max_table_idx = max_table_idx . max ( get_rightmost_table_referenced_in_expr ( lhs) ?) ;
587
+ eval_at = eval_at . max ( determine_where_to_eval_expr ( lhs) ?) ;
588
588
if let Some ( rhs_list) = rhs {
589
589
for rhs_expr in rhs_list {
590
- max_table_idx =
591
- max_table_idx. max ( get_rightmost_table_referenced_in_expr ( rhs_expr) ?) ;
590
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( rhs_expr) ?) ;
592
591
}
593
592
}
594
593
}
595
- _ => { }
594
+ Expr :: Between {
595
+ lhs,
596
+ not,
597
+ start,
598
+ end,
599
+ } => {
600
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( lhs) ?) ;
601
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( start) ?) ;
602
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( end) ?) ;
603
+ }
604
+ Expr :: Case {
605
+ base,
606
+ when_then_pairs,
607
+ else_expr,
608
+ } => {
609
+ if let Some ( base) = base {
610
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( base) ?) ;
611
+ }
612
+ for ( when, then) in when_then_pairs {
613
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( when) ?) ;
614
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( then) ?) ;
615
+ }
616
+ if let Some ( else_expr) = else_expr {
617
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( else_expr) ?) ;
618
+ }
619
+ }
620
+ Expr :: Cast { expr, .. } => {
621
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
622
+ }
623
+ Expr :: Collate ( expr, _) => {
624
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
625
+ }
626
+ Expr :: DoublyQualified ( _, _, _) => {
627
+ unreachable ! ( "DoublyQualified should be resolved to a Column before resolving eval_at" )
628
+ }
629
+ Expr :: Exists ( _) => {
630
+ todo ! ( "exists not supported yet" )
631
+ }
632
+ Expr :: FunctionCall { args, .. } => {
633
+ for arg in args. as_ref ( ) . unwrap_or ( & vec ! [ ] ) . iter ( ) {
634
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( arg) ?) ;
635
+ }
636
+ }
637
+ Expr :: FunctionCallStar { .. } => { }
638
+ Expr :: InSelect { .. } => {
639
+ todo ! ( "in select not supported yet" )
640
+ }
641
+ Expr :: InTable { .. } => {
642
+ todo ! ( "in table not supported yet" )
643
+ }
644
+ Expr :: IsNull ( expr) => {
645
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
646
+ }
647
+ Expr :: Name ( _) => { }
648
+ Expr :: NotNull ( expr) => {
649
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
650
+ }
651
+ Expr :: Parenthesized ( exprs) => {
652
+ for expr in exprs. iter ( ) {
653
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
654
+ }
655
+ }
656
+ Expr :: Raise ( _, _) => {
657
+ todo ! ( "raise not supported yet" )
658
+ }
659
+ Expr :: Subquery ( _) => {
660
+ todo ! ( "subquery not supported yet" )
661
+ }
662
+ Expr :: Unary ( _, expr) => {
663
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
664
+ }
665
+ Expr :: Variable ( _) => { }
596
666
}
597
667
598
- Ok ( max_table_idx )
668
+ Ok ( eval_at )
599
669
}
600
670
601
671
fn parse_join < ' a > (
@@ -679,15 +749,15 @@ fn parse_join<'a>(
679
749
}
680
750
for pred in preds {
681
751
let cur_table_idx = scope. tables . len ( ) - 1 ;
682
- let eval_at_loop = if outer {
683
- cur_table_idx
752
+ let eval_at = if outer {
753
+ EvalAt :: Loop ( cur_table_idx)
684
754
} else {
685
- get_rightmost_table_referenced_in_expr ( & pred) ?
755
+ determine_where_to_eval_expr ( & pred) ?
686
756
} ;
687
757
out_where_clause. push ( WhereTerm {
688
758
expr : pred,
689
759
from_outer_join : outer,
690
- eval_at_loop ,
760
+ eval_at ,
691
761
} ) ;
692
762
}
693
763
}
@@ -749,15 +819,15 @@ fn parse_join<'a>(
749
819
is_rowid_alias : right_col. is_rowid_alias ,
750
820
} ) ,
751
821
) ;
752
- let eval_at_loop = if outer {
753
- cur_table_idx
822
+ let eval_at = if outer {
823
+ EvalAt :: Loop ( cur_table_idx)
754
824
} else {
755
- get_rightmost_table_referenced_in_expr ( & expr) ?
825
+ determine_where_to_eval_expr ( & expr) ?
756
826
} ;
757
827
out_where_clause. push ( WhereTerm {
758
828
expr,
759
829
from_outer_join : outer,
760
- eval_at_loop ,
830
+ eval_at ,
761
831
} ) ;
762
832
}
763
833
using = Some ( distinct_names) ;
0 commit comments