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 ( ( ) )
@@ -548,54 +548,121 @@ pub fn parse_where(
548
548
}
549
549
550
550
/**
551
- Returns the rightmost table index that is referenced in the given AST expression .
552
- Rightmost = innermost loop.
553
- This is used to determine where we should evaluate a given condition expression,
554
- and it needs to be the rightmost table referenced in the expression, because otherwise
555
- the condition would be evaluated before a row is read from that table.
551
+ Returns the earliest point at which a WHERE term can be evaluated .
552
+ For expressions referencing tables, this is the innermost loop that contains a row for each
553
+ table referenced in the expression.
554
+ For expressions not referencing any tables (e.g. constants), this is before the main loop is
555
+ opened, because they do not need any table data .
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, start, end, ..
596
+ } => {
597
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( lhs) ?) ;
598
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( start) ?) ;
599
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( end) ?) ;
600
+ }
601
+ Expr :: Case {
602
+ base,
603
+ when_then_pairs,
604
+ else_expr,
605
+ } => {
606
+ if let Some ( base) = base {
607
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( base) ?) ;
608
+ }
609
+ for ( when, then) in when_then_pairs {
610
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( when) ?) ;
611
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( then) ?) ;
612
+ }
613
+ if let Some ( else_expr) = else_expr {
614
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( else_expr) ?) ;
615
+ }
616
+ }
617
+ Expr :: Cast { expr, .. } => {
618
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
619
+ }
620
+ Expr :: Collate ( expr, _) => {
621
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
622
+ }
623
+ Expr :: DoublyQualified ( _, _, _) => {
624
+ unreachable ! ( "DoublyQualified should be resolved to a Column before resolving eval_at" )
625
+ }
626
+ Expr :: Exists ( _) => {
627
+ todo ! ( "exists not supported yet" )
628
+ }
629
+ Expr :: FunctionCall { args, .. } => {
630
+ for arg in args. as_ref ( ) . unwrap_or ( & vec ! [ ] ) . iter ( ) {
631
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( arg) ?) ;
632
+ }
633
+ }
634
+ Expr :: FunctionCallStar { .. } => { }
635
+ Expr :: InSelect { .. } => {
636
+ todo ! ( "in select not supported yet" )
637
+ }
638
+ Expr :: InTable { .. } => {
639
+ todo ! ( "in table not supported yet" )
640
+ }
641
+ Expr :: IsNull ( expr) => {
642
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
643
+ }
644
+ Expr :: Name ( _) => { }
645
+ Expr :: NotNull ( expr) => {
646
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
647
+ }
648
+ Expr :: Parenthesized ( exprs) => {
649
+ for expr in exprs. iter ( ) {
650
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
651
+ }
652
+ }
653
+ Expr :: Raise ( _, _) => {
654
+ todo ! ( "raise not supported yet" )
655
+ }
656
+ Expr :: Subquery ( _) => {
657
+ todo ! ( "subquery not supported yet" )
658
+ }
659
+ Expr :: Unary ( _, expr) => {
660
+ eval_at = eval_at. max ( determine_where_to_eval_expr ( expr) ?) ;
661
+ }
662
+ Expr :: Variable ( _) => { }
596
663
}
597
664
598
- Ok ( max_table_idx )
665
+ Ok ( eval_at )
599
666
}
600
667
601
668
fn parse_join < ' a > (
@@ -679,15 +746,15 @@ fn parse_join<'a>(
679
746
}
680
747
for pred in preds {
681
748
let cur_table_idx = scope. tables . len ( ) - 1 ;
682
- let eval_at_loop = if outer {
683
- cur_table_idx
749
+ let eval_at = if outer {
750
+ EvalAt :: Loop ( cur_table_idx)
684
751
} else {
685
- get_rightmost_table_referenced_in_expr ( & pred) ?
752
+ determine_where_to_eval_expr ( & pred) ?
686
753
} ;
687
754
out_where_clause. push ( WhereTerm {
688
755
expr : pred,
689
756
from_outer_join : outer,
690
- eval_at_loop ,
757
+ eval_at ,
691
758
} ) ;
692
759
}
693
760
}
@@ -749,15 +816,15 @@ fn parse_join<'a>(
749
816
is_rowid_alias : right_col. is_rowid_alias ,
750
817
} ) ,
751
818
) ;
752
- let eval_at_loop = if outer {
753
- cur_table_idx
819
+ let eval_at = if outer {
820
+ EvalAt :: Loop ( cur_table_idx)
754
821
} else {
755
- get_rightmost_table_referenced_in_expr ( & expr) ?
822
+ determine_where_to_eval_expr ( & expr) ?
756
823
} ;
757
824
out_where_clause. push ( WhereTerm {
758
825
expr,
759
826
from_outer_join : outer,
760
- eval_at_loop ,
827
+ eval_at ,
761
828
} ) ;
762
829
}
763
830
using = Some ( distinct_names) ;
0 commit comments