@@ -33,13 +33,14 @@ use super::{
3333 Unparser ,
3434} ;
3535use crate :: unparser:: ast:: UnnestRelationBuilder ;
36- use crate :: unparser:: utils:: unproject_agg_exprs;
36+ use crate :: unparser:: utils:: { find_unnest_node_until_relation , unproject_agg_exprs} ;
3737use crate :: utils:: UNNEST_PLACEHOLDER ;
3838use datafusion_common:: {
3939 internal_err, not_impl_err,
4040 tree_node:: { TransformedResult , TreeNode } ,
4141 Column , DataFusionError , Result , TableReference ,
4242} ;
43+ use datafusion_expr:: expr:: OUTER_REFERENCE_COLUMN_PREFIX ;
4344use datafusion_expr:: {
4445 expr:: Alias , BinaryExpr , Distinct , Expr , JoinConstraint , JoinType , LogicalPlan ,
4546 LogicalPlanBuilder , Operator , Projection , SortExpr , TableScan , Unnest ,
@@ -235,9 +236,10 @@ impl Unparser<'_> {
235236 plan : & LogicalPlan ,
236237 relation : & mut RelationBuilder ,
237238 alias : Option < ast:: TableAlias > ,
239+ lateral : bool ,
238240 ) -> Result < ( ) > {
239241 let mut derived_builder = DerivedRelationBuilder :: default ( ) ;
240- derived_builder. lateral ( false ) . alias ( alias) . subquery ( {
242+ derived_builder. lateral ( lateral ) . alias ( alias) . subquery ( {
241243 let inner_statement = self . plan_to_sql ( plan) ?;
242244 if let ast:: Statement :: Query ( inner_query) = inner_statement {
243245 inner_query
@@ -257,15 +259,17 @@ impl Unparser<'_> {
257259 alias : & str ,
258260 plan : & LogicalPlan ,
259261 relation : & mut RelationBuilder ,
262+ lateral : bool ,
260263 ) -> Result < ( ) > {
261264 if self . dialect . requires_derived_table_alias ( ) {
262265 self . derive (
263266 plan,
264267 relation,
265268 Some ( self . new_table_alias ( alias. to_string ( ) , vec ! [ ] ) ) ,
269+ lateral,
266270 )
267271 } else {
268- self . derive ( plan, relation, None )
272+ self . derive ( plan, relation, None , lateral )
269273 }
270274 }
271275
@@ -317,10 +321,12 @@ impl Unparser<'_> {
317321 // Projection can be top-level plan for unnest relation
318322 // The projection generated by the `RecursiveUnnestRewriter` from a UNNEST relation will have
319323 // only one expression, which is the placeholder column generated by the rewriter.
320- if self . dialect . unnest_as_table_factor ( )
321- && p. expr . len ( ) == 1
322- && Self :: is_unnest_placeholder ( & p. expr [ 0 ] )
323- {
324+ let unnest_input_type = if p. expr . len ( ) == 1 {
325+ Self :: check_unnest_placeholder_with_outer_ref ( & p. expr [ 0 ] )
326+ } else {
327+ None
328+ } ;
329+ if self . dialect . unnest_as_table_factor ( ) && unnest_input_type. is_some ( ) {
324330 if let LogicalPlan :: Unnest ( unnest) = & p. input . as_ref ( ) {
325331 return self
326332 . unnest_to_table_factor_sql ( unnest, query, select, relation) ;
@@ -333,6 +339,9 @@ impl Unparser<'_> {
333339 "derived_projection" ,
334340 plan,
335341 relation,
342+ unnest_input_type
343+ . filter ( |t| matches ! ( t, UnnestInputType :: OuterReference ) )
344+ . is_some ( ) ,
336345 ) ;
337346 }
338347 self . reconstruct_select_statement ( plan, p, select) ?;
@@ -365,6 +374,7 @@ impl Unparser<'_> {
365374 "derived_limit" ,
366375 plan,
367376 relation,
377+ false ,
368378 ) ;
369379 }
370380 if let Some ( fetch) = & limit. fetch {
@@ -402,6 +412,7 @@ impl Unparser<'_> {
402412 "derived_sort" ,
403413 plan,
404414 relation,
415+ false ,
405416 ) ;
406417 }
407418 let Some ( query_ref) = query else {
@@ -472,6 +483,7 @@ impl Unparser<'_> {
472483 "derived_distinct" ,
473484 plan,
474485 relation,
486+ false ,
475487 ) ;
476488 }
477489 let ( select_distinct, input) = match distinct {
@@ -658,6 +670,7 @@ impl Unparser<'_> {
658670 "derived_union" ,
659671 plan,
660672 relation,
673+ false ,
661674 ) ;
662675 }
663676
@@ -723,19 +736,54 @@ impl Unparser<'_> {
723736 internal_err ! ( "Unnest input is not a Projection: {unnest:?}" )
724737 }
725738 }
726- _ => not_impl_err ! ( "Unsupported operator: {plan:?}" ) ,
739+ LogicalPlan :: Subquery ( subquery)
740+ if find_unnest_node_until_relation ( subquery. subquery . as_ref ( ) )
741+ . is_some ( ) =>
742+ {
743+ if self . dialect . unnest_as_table_factor ( ) {
744+ self . select_to_sql_recursively (
745+ subquery. subquery . as_ref ( ) ,
746+ query,
747+ select,
748+ relation,
749+ )
750+ } else {
751+ self . derive_with_dialect_alias (
752+ "derived_unnest" ,
753+ subquery. subquery . as_ref ( ) ,
754+ relation,
755+ true ,
756+ )
757+ }
758+ }
759+ _ => {
760+ not_impl_err ! ( "Unsupported operator: {plan:?}" )
761+ }
727762 }
728763 }
729764
730- /// Try to find the placeholder column name generated by `RecursiveUnnestRewriter`
731- /// Only match the pattern `Expr::Alias(Expr::Column("__unnest_placeholder(...)"))`
732- fn is_unnest_placeholder ( expr : & Expr ) -> bool {
765+ /// Try to find the placeholder column name generated by `RecursiveUnnestRewriter`.
766+ ///
767+ /// - If the column is a placeholder column match the pattern `Expr::Alias(Expr::Column("__unnest_placeholder(...)"))`,
768+ /// it means it is a scalar column, return [UnnestInputType::Scalar].
769+ /// - If the column is a placeholder column match the pattern `Expr::Alias(Expr::Column("__unnest_placeholder(outer_ref(...)))")`,
770+ /// it means it is an outer reference column, return [UnnestInputType::OuterReference].
771+ /// - If the column is not a placeholder column, return [None].
772+ ///
773+ /// `outer_ref` is the display result of [Expr::OuterReferenceColumn]
774+ fn check_unnest_placeholder_with_outer_ref ( expr : & Expr ) -> Option < UnnestInputType > {
733775 if let Expr :: Alias ( Alias { expr, .. } ) = expr {
734776 if let Expr :: Column ( Column { name, .. } ) = expr. as_ref ( ) {
735- return name. starts_with ( UNNEST_PLACEHOLDER ) ;
777+ if let Some ( prefix) = name. strip_prefix ( UNNEST_PLACEHOLDER ) {
778+ if prefix. starts_with ( & format ! ( "({}(" , OUTER_REFERENCE_COLUMN_PREFIX ) )
779+ {
780+ return Some ( UnnestInputType :: OuterReference ) ;
781+ }
782+ return Some ( UnnestInputType :: Scalar ) ;
783+ }
736784 }
737785 }
738- false
786+ None
739787 }
740788
741789 fn unnest_to_table_factor_sql (
@@ -1092,3 +1140,12 @@ impl From<BuilderError> for DataFusionError {
10921140 DataFusionError :: External ( Box :: new ( e) )
10931141 }
10941142}
1143+
1144+ /// The type of the input to the UNNEST table factor.
1145+ #[ derive( Debug ) ]
1146+ enum UnnestInputType {
1147+ /// The input is a column reference. It will be presented like `outer_ref(column_name)`.
1148+ OuterReference ,
1149+ /// The input is a scalar value. It will be presented like a scalar array or struct.
1150+ Scalar ,
1151+ }
0 commit comments