@@ -26,9 +26,9 @@ use super::{
2626 subquery_alias_inner_query_and_columns, TableAliasRewriter ,
2727 } ,
2828 utils:: {
29- find_agg_node_within_select, find_window_nodes_within_select ,
30- try_transform_to_simple_table_scan_with_filters , unproject_sort_expr ,
31- unproject_window_exprs,
29+ find_agg_node_within_select, find_unnest_node_within_select ,
30+ find_window_nodes_within_select , try_transform_to_simple_table_scan_with_filters ,
31+ unproject_sort_expr , unproject_unnest_expr , unproject_window_exprs,
3232 } ,
3333 Unparser ,
3434} ;
@@ -174,15 +174,24 @@ impl Unparser<'_> {
174174 p : & Projection ,
175175 select : & mut SelectBuilder ,
176176 ) -> Result < ( ) > {
177+ let mut exprs = p. expr . clone ( ) ;
178+
179+ // If an Unnest node is found within the select, find and unproject the unnest column
180+ if let Some ( unnest) = find_unnest_node_within_select ( plan) {
181+ exprs = exprs
182+ . into_iter ( )
183+ . map ( |e| unproject_unnest_expr ( e, unnest) )
184+ . collect :: < Result < Vec < _ > > > ( ) ?;
185+ } ;
186+
177187 match (
178188 find_agg_node_within_select ( plan, true ) ,
179189 find_window_nodes_within_select ( plan, None , true ) ,
180190 ) {
181191 ( Some ( agg) , window) => {
182192 let window_option = window. as_deref ( ) ;
183- let items = p
184- . expr
185- . iter ( )
193+ let items = exprs
194+ . into_iter ( )
186195 . map ( |proj_expr| {
187196 let unproj = unproject_agg_exprs ( proj_expr, agg, window_option) ?;
188197 self . select_item_to_sql ( & unproj)
@@ -199,9 +208,8 @@ impl Unparser<'_> {
199208 ) ) ;
200209 }
201210 ( None , Some ( window) ) => {
202- let items = p
203- . expr
204- . iter ( )
211+ let items = exprs
212+ . into_iter ( )
205213 . map ( |proj_expr| {
206214 let unproj = unproject_window_exprs ( proj_expr, & window) ?;
207215 self . select_item_to_sql ( & unproj)
@@ -211,8 +219,7 @@ impl Unparser<'_> {
211219 select. projection ( items) ;
212220 }
213221 _ => {
214- let items = p
215- . expr
222+ let items = exprs
216223 . iter ( )
217224 . map ( |e| self . select_item_to_sql ( e) )
218225 . collect :: < Result < Vec < _ > > > ( ) ?;
@@ -319,7 +326,8 @@ impl Unparser<'_> {
319326 if let Some ( agg) =
320327 find_agg_node_within_select ( plan, select. already_projected ( ) )
321328 {
322- let unprojected = unproject_agg_exprs ( & filter. predicate , agg, None ) ?;
329+ let unprojected =
330+ unproject_agg_exprs ( filter. predicate . clone ( ) , agg, None ) ?;
323331 let filter_expr = self . expr_to_sql ( & unprojected) ?;
324332 select. having ( Some ( filter_expr) ) ;
325333 } else {
@@ -652,6 +660,28 @@ impl Unparser<'_> {
652660 Ok ( ( ) )
653661 }
654662 LogicalPlan :: Extension ( _) => not_impl_err ! ( "Unsupported operator: {plan:?}" ) ,
663+ LogicalPlan :: Unnest ( unnest) => {
664+ if !unnest. struct_type_columns . is_empty ( ) {
665+ return internal_err ! (
666+ "Struct type columns are not currently supported in UNNEST: {:?}" ,
667+ unnest. struct_type_columns
668+ ) ;
669+ }
670+
671+ // In the case of UNNEST, the Unnest node is followed by a duplicate Projection node that we should skip.
672+ // Otherwise, there will be a duplicate SELECT clause.
673+ // | Projection: table.col1, UNNEST(table.col2)
674+ // | Unnest: UNNEST(table.col2)
675+ // | Projection: table.col1, table.col2 AS UNNEST(table.col2)
676+ // | Filter: table.col3 = Int64(3)
677+ // | TableScan: table projection=None
678+ if let LogicalPlan :: Projection ( p) = unnest. input . as_ref ( ) {
679+ // continue with projection input
680+ self . select_to_sql_recursively ( & p. input , query, select, relation)
681+ } else {
682+ internal_err ! ( "Unnest input is not a Projection: {unnest:?}" )
683+ }
684+ }
655685 _ => not_impl_err ! ( "Unsupported operator: {plan:?}" ) ,
656686 }
657687 }
0 commit comments