@@ -3360,6 +3360,87 @@ fn snowflake_flatten_composed_expression_with_limit() -> Result<(), DataFusionEr
33603360 Ok ( ( ) )
33613361}
33623362
3363+ #[ test]
3364+ fn snowflake_flatten_multi_expression_projection ( ) -> Result < ( ) , DataFusionError > {
3365+ // Build: Projection([CAST(placeholder AS Int64) AS a, CAST(placeholder AS Utf8) AS b])
3366+ // → Unnest → Projection → TableScan
3367+ // The outer Projection has TWO expressions — both reference the placeholder.
3368+ // The FLATTEN code path must fire even when p.expr.len() > 1.
3369+ let schema = Schema :: new ( vec ! [ Field :: new(
3370+ "items" ,
3371+ DataType :: List ( Arc :: new( Field :: new_list_field( DataType :: Utf8 , true ) ) ) ,
3372+ true ,
3373+ ) ] ) ;
3374+
3375+ let plan = table_scan ( Some ( "source" ) , & schema, None ) ?
3376+ . project ( vec ! [ col( "items" ) . alias( "__unnest_placeholder(items)" ) ] ) ?
3377+ . unnest_column ( "__unnest_placeholder(items)" ) ?
3378+ . project ( vec ! [
3379+ cast( col( "__unnest_placeholder(items)" ) , DataType :: Int64 ) . alias( "a" ) ,
3380+ cast( col( "__unnest_placeholder(items)" ) , DataType :: Utf8 ) . alias( "b" ) ,
3381+ ] ) ?
3382+ . build ( ) ?;
3383+
3384+ let snowflake = SnowflakeDialect :: new ( ) ;
3385+ let unparser = Unparser :: new ( & snowflake) ;
3386+ let result = unparser. plan_to_sql ( & plan) ?;
3387+ let actual = result. to_string ( ) ;
3388+
3389+ assert ! (
3390+ actual. contains( "LATERAL FLATTEN" ) ,
3391+ "Expected LATERAL FLATTEN in SQL, got: {actual}"
3392+ ) ;
3393+ // Both expressions should be present
3394+ assert ! (
3395+ actual. contains( "CAST" ) ,
3396+ "Expected CAST in SQL, got: {actual}"
3397+ ) ;
3398+ assert ! (
3399+ actual. contains( r#"AS "a""# ) ,
3400+ "Expected alias 'a' in SQL, got: {actual}"
3401+ ) ;
3402+ assert ! (
3403+ actual. contains( r#"AS "b""# ) ,
3404+ "Expected alias 'b' in SQL, got: {actual}"
3405+ ) ;
3406+ Ok ( ( ) )
3407+ }
3408+
3409+ #[ test]
3410+ fn snowflake_flatten_multi_expression_with_limit ( ) -> Result < ( ) , DataFusionError > {
3411+ // Multi-expression + Limit between Projection and Unnest
3412+ let schema = Schema :: new ( vec ! [ Field :: new(
3413+ "items" ,
3414+ DataType :: List ( Arc :: new( Field :: new_list_field( DataType :: Utf8 , true ) ) ) ,
3415+ true ,
3416+ ) ] ) ;
3417+
3418+ let plan = table_scan ( Some ( "source" ) , & schema, None ) ?
3419+ . project ( vec ! [ col( "items" ) . alias( "__unnest_placeholder(items)" ) ] ) ?
3420+ . unnest_column ( "__unnest_placeholder(items)" ) ?
3421+ . limit ( 0 , Some ( 10 ) ) ?
3422+ . project ( vec ! [
3423+ cast( col( "__unnest_placeholder(items)" ) , DataType :: Int64 ) . alias( "a" ) ,
3424+ cast( col( "__unnest_placeholder(items)" ) , DataType :: Utf8 ) . alias( "b" ) ,
3425+ ] ) ?
3426+ . build ( ) ?;
3427+
3428+ let snowflake = SnowflakeDialect :: new ( ) ;
3429+ let unparser = Unparser :: new ( & snowflake) ;
3430+ let result = unparser. plan_to_sql ( & plan) ?;
3431+ let actual = result. to_string ( ) ;
3432+
3433+ assert ! (
3434+ actual. contains( "LATERAL FLATTEN" ) ,
3435+ "Expected LATERAL FLATTEN in SQL, got: {actual}"
3436+ ) ;
3437+ assert ! (
3438+ actual. contains( "LIMIT 10" ) ,
3439+ "Expected LIMIT 10 in SQL, got: {actual}"
3440+ ) ;
3441+ Ok ( ( ) )
3442+ }
3443+
33633444#[ test]
33643445fn snowflake_unnest_through_subquery_alias ( ) -> Result < ( ) , DataFusionError > {
33653446 // Build: Projection → Unnest → SubqueryAlias → Projection → TableScan
0 commit comments