@@ -23,7 +23,7 @@ use std::borrow::Cow;
23
23
24
24
use partiql_value:: BindingsName ;
25
25
26
- use std:: collections:: { HashMap , HashSet } ;
26
+ use std:: collections:: HashMap ;
27
27
28
28
use crate :: builtins:: { FnSymTab , FN_SYM_TAB } ;
29
29
use itertools:: Itertools ;
@@ -57,12 +57,21 @@ macro_rules! eq_or_fault {
57
57
58
58
#[ macro_export]
59
59
macro_rules! true_or_fault {
60
+ ( $self: ident, $expr: expr, $msg: expr) => {
61
+ if !$expr {
62
+ true_or_fault_err!( $self, $expr, $msg) ;
63
+ return partiql_ast:: visit:: Traverse :: Stop ;
64
+ }
65
+ } ;
66
+ }
67
+
68
+ #[ macro_export]
69
+ macro_rules! true_or_fault_err {
60
70
( $self: ident, $expr: expr, $msg: expr) => {
61
71
if !$expr {
62
72
$self
63
73
. errors
64
74
. push( AstTransformError :: IllegalState ( $msg. to_string( ) ) ) ;
65
- return partiql_ast:: visit:: Traverse :: Stop ;
66
75
}
67
76
} ;
68
77
}
@@ -161,9 +170,6 @@ pub struct AstToLogical<'a> {
161
170
path_stack : Vec < Vec < PathComponent > > ,
162
171
sort_stack : Vec < Vec < logical:: SortSpec > > ,
163
172
aggregate_exprs : Vec < AggregateExpression > ,
164
-
165
- from_lets : HashSet < NodeId > ,
166
-
167
173
projection_renames : Vec < FnvIndexMap < String , BindingsName < ' a > > > ,
168
174
169
175
aliases : FnvIndexMap < NodeId , SymbolPrimitive > ,
@@ -173,7 +179,7 @@ pub struct AstToLogical<'a> {
173
179
agg_id : IdGenerator ,
174
180
175
181
// output
176
- plan : LogicalPlan < BindingsOp > ,
182
+ plan_stack : Vec < LogicalPlan < BindingsOp > > ,
177
183
178
184
// catalog & data flow data
179
185
key_registry : name_resolver:: KeyRegistry ,
@@ -233,8 +239,6 @@ impl<'a> AstToLogical<'a> {
233
239
sort_stack : Default :: default ( ) ,
234
240
aggregate_exprs : Default :: default ( ) ,
235
241
236
- from_lets : Default :: default ( ) ,
237
-
238
242
projection_renames : Default :: default ( ) ,
239
243
240
244
aliases : Default :: default ( ) ,
@@ -244,7 +248,7 @@ impl<'a> AstToLogical<'a> {
244
248
agg_id : Default :: default ( ) ,
245
249
246
250
// output
247
- plan : Default :: default ( ) ,
251
+ plan_stack : Default :: default ( ) ,
248
252
249
253
key_registry : registry,
250
254
fnsym_tab,
@@ -258,13 +262,19 @@ impl<'a> AstToLogical<'a> {
258
262
mut self ,
259
263
query : & ast:: AstNode < ast:: TopLevelQuery > ,
260
264
) -> Result < logical:: LogicalPlan < logical:: BindingsOp > , AstTransformationError > {
265
+ self . enter_plan ( ) ;
261
266
query. visit ( & mut self ) ;
267
+ true_or_fault_err ! (
268
+ self ,
269
+ self . plan_stack. len( ) == 1 ,
270
+ "self.plan_stack.len() != 1"
271
+ ) ;
262
272
if !self . errors . is_empty ( ) {
263
273
return Err ( AstTransformationError {
264
274
errors : self . errors ,
265
275
} ) ;
266
276
}
267
- Ok ( self . plan )
277
+ Ok ( self . plan_stack . pop ( ) . unwrap ( ) )
268
278
}
269
279
270
280
#[ inline]
@@ -509,6 +519,21 @@ impl<'a> AstToLogical<'a> {
509
519
self . q_stack . last_mut ( ) . unwrap ( )
510
520
}
511
521
522
+ #[ inline]
523
+ fn enter_plan ( & mut self ) {
524
+ self . plan_stack . push ( LogicalPlan :: default ( ) ) ;
525
+ }
526
+
527
+ #[ inline]
528
+ fn exit_plan ( & mut self ) -> LogicalPlan < BindingsOp > {
529
+ self . plan_stack . pop ( ) . expect ( "environment level" )
530
+ }
531
+
532
+ #[ inline]
533
+ fn curr_plan ( & mut self ) -> & mut LogicalPlan < BindingsOp > {
534
+ self . plan_stack . last_mut ( ) . expect ( "plan" )
535
+ }
536
+
512
537
#[ inline]
513
538
fn enter_benv ( & mut self ) {
514
539
self . bexpr_stack . push ( vec ! [ ] ) ;
@@ -691,8 +716,8 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
691
716
let mut benv = self . exit_benv ( ) ;
692
717
eq_or_fault ! ( self , benv. len( ) , 1 , "Expect benv.len() == 1" ) ;
693
718
let out = benv. pop ( ) . unwrap ( ) ;
694
- let sink_id = self . plan . add_operator ( BindingsOp :: Sink ) ;
695
- self . plan . add_flow ( out, sink_id) ;
719
+ let sink_id = self . curr_plan ( ) . add_operator ( BindingsOp :: Sink ) ;
720
+ self . curr_plan ( ) . add_flow ( out, sink_id) ;
696
721
Traverse :: Continue
697
722
}
698
723
@@ -712,7 +737,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
712
737
let mut clauses = clauses. evaluation_order ( ) . into_iter ( ) ;
713
738
if let Some ( mut src_id) = clauses. next ( ) {
714
739
for dst_id in clauses {
715
- self . plan . add_flow ( src_id, dst_id) ;
740
+ self . curr_plan ( ) . add_flow ( src_id, dst_id) ;
716
741
src_id = dst_id;
717
742
}
718
743
self . push_bexpr ( src_id) ;
@@ -726,7 +751,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
726
751
) ;
727
752
let mut out = * benv. first ( ) . unwrap ( ) ;
728
753
benv. into_iter ( ) . skip ( 1 ) . for_each ( |op| {
729
- self . plan . add_flow ( out, op) ;
754
+ self . curr_plan ( ) . add_flow ( out, op) ;
730
755
out = op;
731
756
} ) ;
732
757
self . push_bexpr ( out) ;
@@ -759,7 +784,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
759
784
760
785
match query_set {
761
786
QuerySet :: BagOp ( bag_op) => {
762
- eq_or_fault ! ( self , benv. len( ) , 2 , "benv.len() != 2" ) ;
787
+ eq_or_fault ! ( self , benv. len( ) , 2 , "qs benv.len() != 2" ) ;
763
788
let rid = benv. pop ( ) . unwrap ( ) ;
764
789
let lid = benv. pop ( ) . unwrap ( ) ;
765
790
@@ -777,20 +802,20 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
777
802
None => logical:: SetQuantifier :: Distinct ,
778
803
} ;
779
804
780
- let id = self . plan . add_operator ( BindingsOp :: BagOp ( BagOp {
805
+ let id = self . curr_plan ( ) . add_operator ( BindingsOp :: BagOp ( BagOp {
781
806
bag_op : bag_operator,
782
807
setq,
783
808
} ) ) ;
784
- self . plan . add_flow_with_branch_num ( lid, id, 0 ) ;
785
- self . plan . add_flow_with_branch_num ( rid, id, 1 ) ;
809
+ self . curr_plan ( ) . add_flow_with_branch_num ( lid, id, 0 ) ;
810
+ self . curr_plan ( ) . add_flow_with_branch_num ( rid, id, 1 ) ;
786
811
self . push_bexpr ( id) ;
787
812
}
788
813
QuerySet :: Select ( _) => { }
789
814
QuerySet :: Expr ( _) => {
790
815
eq_or_fault ! ( self , env. len( ) , 1 , "env.len() != 1" ) ;
791
816
let expr = env. into_iter ( ) . next ( ) . unwrap ( ) ;
792
817
let op = BindingsOp :: ExprQuery ( logical:: ExprQuery { expr } ) ;
793
- let id = self . plan . add_operator ( op) ;
818
+ let id = self . curr_plan ( ) . add_operator ( op) ;
794
819
self . push_bexpr ( id) ;
795
820
}
796
821
QuerySet :: Values ( _) => {
@@ -839,7 +864,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
839
864
aggregate_exprs : self . aggregate_exprs . clone ( ) ,
840
865
group_as_alias : None ,
841
866
} ) ;
842
- let id = self . plan . add_operator ( group_by) ;
867
+ let id = self . curr_plan ( ) . add_operator ( group_by) ;
843
868
self . current_clauses_mut ( ) . group_by_clause . replace ( id) ;
844
869
}
845
870
Traverse :: Continue
@@ -859,7 +884,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
859
884
eq_or_fault ! ( self , env. len( ) , 0 , "env.len() != 0" ) ;
860
885
861
886
if let Some ( SetQuantifier :: Distinct ) = projection. setq {
862
- let id = self . plan . add_operator ( BindingsOp :: Distinct ) ;
887
+ let id = self . curr_plan ( ) . add_operator ( BindingsOp :: Distinct ) ;
863
888
self . current_clauses_mut ( ) . distinct . replace ( id) ;
864
889
}
865
890
Traverse :: Continue
@@ -934,7 +959,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
934
959
logical:: BindingsOp :: ProjectValue ( logical:: ProjectValue { expr } )
935
960
}
936
961
} ;
937
- let id = self . plan . add_operator ( select) ;
962
+ let id = self . curr_plan ( ) . add_operator ( select) ;
938
963
self . current_clauses_mut ( ) . select_clause . replace ( id) ;
939
964
Traverse :: Continue
940
965
}
@@ -1468,8 +1493,9 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1468
1493
}
1469
1494
1470
1495
fn enter_from_let ( & mut self , from_let : & ' ast FromLet ) -> Traverse {
1471
- self . from_lets . insert ( * self . current_node ( ) ) ;
1472
1496
* self . current_ctx_mut ( ) = QueryContext :: FromLet ;
1497
+ self . enter_plan ( ) ;
1498
+ self . enter_benv ( ) ;
1473
1499
self . enter_env ( ) ;
1474
1500
1475
1501
let id = * self . current_node ( ) ;
@@ -1485,10 +1511,20 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1485
1511
1486
1512
fn exit_from_let ( & mut self , from_let : & ' ast FromLet ) -> Traverse {
1487
1513
* self . current_ctx_mut ( ) = QueryContext :: Query ;
1514
+ let subplan = self . exit_plan ( ) ;
1515
+ let benv = self . exit_benv ( ) ;
1488
1516
let mut env = self . exit_env ( ) ;
1489
- eq_or_fault ! ( self , env. len( ) , 1 , "env.len() != 1" ) ;
1517
+ eq_or_fault ! ( self , env. len( ) + benv . len ( ) , 1 , "env.len()+benv .len() != 1" ) ;
1490
1518
1491
- let expr = env. pop ( ) . unwrap ( ) ;
1519
+ let expr = if !benv. is_empty ( ) {
1520
+ // Subquery in From Let
1521
+ let subq = logical:: SubQueryExpr { plan : subplan } ;
1522
+ ValueExpr :: SubQueryExpr ( subq)
1523
+ } else {
1524
+ // Expression in From Let
1525
+ self . curr_plan ( ) . merge_plan ( subplan) ; // merge in subplan, as there is no subquery
1526
+ env. pop ( ) . unwrap ( )
1527
+ } ;
1492
1528
1493
1529
let FromLet {
1494
1530
kind,
@@ -1527,10 +1563,13 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1527
1563
ProjectAllMode :: Unwrap ,
1528
1564
) ,
1529
1565
} ;
1530
- let id = self . plan . add_operator ( bexpr) ;
1566
+
1567
+ let id = self . curr_plan ( ) . add_operator ( bexpr) ;
1531
1568
self . push_bexpr ( id) ;
1569
+
1532
1570
if let Some ( select_id) = self . current_clauses_mut ( ) . select_clause {
1533
- if let Some ( BindingsOp :: ProjectAll ( mode) ) = self . plan . operator_as_mut ( select_id) {
1571
+ if let Some ( BindingsOp :: ProjectAll ( mode) ) = self . curr_plan ( ) . operator_as_mut ( select_id)
1572
+ {
1534
1573
* mode = project_all_mode
1535
1574
}
1536
1575
}
@@ -1546,7 +1585,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1546
1585
1547
1586
fn exit_join ( & mut self , join : & ' ast Join ) -> Traverse {
1548
1587
let mut benv = self . exit_benv ( ) ;
1549
- eq_or_fault ! ( self , benv. len( ) , 2 , "benv.len() != 2" ) ;
1588
+ eq_or_fault ! ( self , benv. len( ) , 2 , "j benv.len() != 2" ) ;
1550
1589
1551
1590
let mut env = self . exit_env ( ) ;
1552
1591
true_or_fault ! (
@@ -1569,17 +1608,17 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1569
1608
1570
1609
let rid = benv. pop ( ) . unwrap ( ) ;
1571
1610
let lid = benv. pop ( ) . unwrap ( ) ;
1572
- let left = Box :: new ( self . plan . operator ( lid) . unwrap ( ) . clone ( ) ) ;
1573
- let right = Box :: new ( self . plan . operator ( rid) . unwrap ( ) . clone ( ) ) ;
1611
+ let left = Box :: new ( self . curr_plan ( ) . operator ( lid) . unwrap ( ) . clone ( ) ) ;
1612
+ let right = Box :: new ( self . curr_plan ( ) . operator ( rid) . unwrap ( ) . clone ( ) ) ;
1574
1613
let join = logical:: BindingsOp :: Join ( logical:: Join {
1575
1614
kind,
1576
1615
left,
1577
1616
right,
1578
1617
on,
1579
1618
} ) ;
1580
- let join = self . plan . add_operator ( join) ;
1581
- self . plan . add_flow_with_branch_num ( lid, join, 0 ) ;
1582
- self . plan . add_flow_with_branch_num ( rid, join, 1 ) ;
1619
+ let join = self . curr_plan ( ) . add_operator ( join) ;
1620
+ self . curr_plan ( ) . add_flow_with_branch_num ( lid, join, 0 ) ;
1621
+ self . curr_plan ( ) . add_flow_with_branch_num ( rid, join, 1 ) ;
1583
1622
self . push_bexpr ( join) ;
1584
1623
Traverse :: Continue
1585
1624
}
@@ -1611,7 +1650,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1611
1650
let filter = logical:: BindingsOp :: Filter ( logical:: Filter {
1612
1651
expr : env. pop ( ) . unwrap ( ) ,
1613
1652
} ) ;
1614
- let id = self . plan . add_operator ( filter) ;
1653
+ let id = self . curr_plan ( ) . add_operator ( filter) ;
1615
1654
1616
1655
self . current_clauses_mut ( ) . where_clause . replace ( id) ;
1617
1656
Traverse :: Continue
@@ -1629,7 +1668,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1629
1668
let having = BindingsOp :: Having ( logical:: Having {
1630
1669
expr : env. pop ( ) . unwrap ( ) ,
1631
1670
} ) ;
1632
- let id = self . plan . add_operator ( having) ;
1671
+ let id = self . curr_plan ( ) . add_operator ( having) ;
1633
1672
1634
1673
self . current_clauses_mut ( ) . having_clause . replace ( id) ;
1635
1674
Traverse :: Continue
@@ -1679,8 +1718,9 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1679
1718
) ) ;
1680
1719
return Traverse :: Stop ;
1681
1720
}
1721
+ let mut errors = Vec :: default ( ) ;
1682
1722
let select_clause = self
1683
- . plan
1723
+ . curr_plan ( )
1684
1724
. operator_as_mut ( select_clause_op_id. expect ( "select_clause_op_id not None" ) )
1685
1725
. unwrap ( ) ;
1686
1726
let mut binding = Vec :: new ( ) ;
@@ -1705,14 +1745,14 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1705
1745
logical:: Lit :: String ( s) => s. clone ( ) ,
1706
1746
_ => {
1707
1747
// Report error but allow visitor to continue
1708
- self . errors . push ( AstTransformError :: IllegalState (
1748
+ errors. push ( AstTransformError :: IllegalState (
1709
1749
"Unexpected literal type" . to_string ( ) ,
1710
1750
) ) ;
1711
1751
String :: new ( )
1712
1752
}
1713
1753
} ,
1714
1754
_ => {
1715
- self . errors . push ( AstTransformError :: IllegalState (
1755
+ errors. push ( AstTransformError :: IllegalState (
1716
1756
"Unexpected alias type" . to_string ( ) ,
1717
1757
) ) ;
1718
1758
return Traverse :: Stop ;
@@ -1728,14 +1768,16 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1728
1768
exprs. insert ( alias, value) ;
1729
1769
}
1730
1770
1771
+ self . errors . extend ( errors) ;
1772
+
1731
1773
let group_by: BindingsOp = BindingsOp :: GroupBy ( logical:: GroupBy {
1732
1774
strategy,
1733
1775
exprs,
1734
1776
aggregate_exprs,
1735
1777
group_as_alias,
1736
1778
} ) ;
1737
1779
1738
- let id = self . plan . add_operator ( group_by) ;
1780
+ let id = self . curr_plan ( ) . add_operator ( group_by) ;
1739
1781
self . current_clauses_mut ( ) . group_by_clause . replace ( id) ;
1740
1782
Traverse :: Continue
1741
1783
}
@@ -1763,7 +1805,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1763
1805
fn exit_order_by_expr ( & mut self , _order_by_expr : & ' ast OrderByExpr ) -> Traverse {
1764
1806
let specs = self . exit_sort ( ) ;
1765
1807
let order_by = logical:: BindingsOp :: OrderBy ( logical:: OrderBy { specs } ) ;
1766
- let id = self . plan . add_operator ( order_by) ;
1808
+ let id = self . curr_plan ( ) . add_operator ( order_by) ;
1767
1809
if matches ! ( self . current_ctx( ) , Some ( QueryContext :: Query ) ) {
1768
1810
self . current_clauses_mut ( ) . order_by_clause . replace ( id) ;
1769
1811
} else {
@@ -1836,7 +1878,7 @@ impl<'ast> Visitor<'ast> for AstToLogical<'_> {
1836
1878
} ;
1837
1879
1838
1880
let limit_offset = logical:: BindingsOp :: LimitOffset ( logical:: LimitOffset { limit, offset } ) ;
1839
- let id = self . plan . add_operator ( limit_offset) ;
1881
+ let id = self . curr_plan ( ) . add_operator ( limit_offset) ;
1840
1882
if matches ! ( self . current_ctx( ) , Some ( QueryContext :: Query ) ) {
1841
1883
self . current_clauses_mut ( ) . limit_offset_clause . replace ( id) ;
1842
1884
} else {
0 commit comments