1818use crate :: planner:: { ContextProvider , PlannerContext , SqlToRel } ;
1919use datafusion_common:: { not_impl_err, Column , Result } ;
2020use datafusion_expr:: { JoinType , LogicalPlan , LogicalPlanBuilder } ;
21- use sqlparser:: ast:: { Join , JoinConstraint , JoinOperator , TableWithJoins } ;
21+ use sqlparser:: ast:: { Join , JoinConstraint , JoinOperator , TableFactor , TableWithJoins } ;
2222use std:: collections:: HashSet ;
2323
2424impl < ' a , S : ContextProvider > SqlToRel < ' a , S > {
@@ -33,28 +33,20 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
3333 // So always use original global CTEs to plan CTEs in from clause.
3434 // Btw, don't need to add CTEs in from to global CTEs.
3535 let origin_planner_context = planner_context. clone ( ) ;
36- let left = self . create_relation ( t. relation , planner_context) ?;
37- match t. joins . len ( ) {
38- 0 => {
39- * planner_context = origin_planner_context;
40- Ok ( left)
41- }
42- _ => {
43- let mut joins = t. joins . into_iter ( ) ;
36+ let mut left = if is_lateral_factor ( & t. relation ) {
37+ self . create_relation_subquery ( t. relation , planner_context) ?
38+ } else {
39+ self . create_relation ( t. relation , planner_context) ?
40+ } ;
41+ if !t. joins . is_empty ( ) {
42+ for join in t. joins {
4443 * planner_context = origin_planner_context. clone ( ) ;
45- let mut left = self . parse_relation_join (
46- left,
47- joins. next ( ) . unwrap ( ) , // length of joins > 0
48- planner_context,
49- ) ?;
50- for join in joins {
51- * planner_context = origin_planner_context. clone ( ) ;
52- left = self . parse_relation_join ( left, join, planner_context) ?;
53- }
54- * planner_context = origin_planner_context;
55- Ok ( left)
44+ planner_context. extend_outer_from_schema ( left. schema ( ) ) ?;
45+ left = self . parse_relation_join ( left, join, planner_context) ?;
5646 }
5747 }
48+ * planner_context = origin_planner_context;
49+ Ok ( left)
5850 }
5951
6052 fn parse_relation_join (
@@ -63,7 +55,11 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
6355 join : Join ,
6456 planner_context : & mut PlannerContext ,
6557 ) -> Result < LogicalPlan > {
66- let right = self . create_relation ( join. relation , planner_context) ?;
58+ let right = if is_lateral_join ( & join) ? {
59+ self . create_relation_subquery ( join. relation , planner_context) ?
60+ } else {
61+ self . create_relation ( join. relation , planner_context) ?
62+ } ;
6763 match join. join_operator {
6864 JoinOperator :: LeftOuter ( constraint) => {
6965 self . parse_join ( left, right, constraint, JoinType :: Left , planner_context)
@@ -167,3 +163,30 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
167163 }
168164 }
169165}
166+
167+ /// Return `true` iff the given [`TableFactor`] is lateral.
168+ pub ( crate ) fn is_lateral_factor ( factor : & TableFactor ) -> bool {
169+ match factor {
170+ TableFactor :: Derived { lateral, .. } => * lateral,
171+ TableFactor :: Function { lateral, .. } => * lateral,
172+ _ => false ,
173+ }
174+ }
175+
176+ /// Return `true` iff the given [`Join`] is lateral.
177+ pub ( crate ) fn is_lateral_join ( join : & Join ) -> Result < bool > {
178+ let is_lateral_syntax = is_lateral_factor ( & join. relation ) ;
179+ let is_apply_syntax = match join. join_operator {
180+ JoinOperator :: FullOuter ( ..)
181+ | JoinOperator :: RightOuter ( ..)
182+ | JoinOperator :: RightAnti ( ..)
183+ | JoinOperator :: RightSemi ( ..)
184+ if is_lateral_syntax =>
185+ {
186+ return not_impl_err ! ( "NONE constraint is not supported" ) ;
187+ }
188+ JoinOperator :: CrossApply | JoinOperator :: OuterApply => true ,
189+ _ => false ,
190+ } ;
191+ Ok ( is_lateral_syntax || is_apply_syntax)
192+ }
0 commit comments