@@ -21,7 +21,8 @@ use datafusion_expr::planner::PlannerResult;
21
21
use datafusion_expr:: planner:: RawDictionaryExpr ;
22
22
use datafusion_expr:: planner:: RawFieldAccessExpr ;
23
23
use sqlparser:: ast:: {
24
- CastKind , DictionaryField , Expr as SQLExpr , Subscript , TrimWhereField , Value ,
24
+ CastKind , DictionaryField , Expr as SQLExpr , StructField , Subscript , TrimWhereField ,
25
+ Value ,
25
26
} ;
26
27
27
28
use datafusion_common:: {
@@ -597,7 +598,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
597
598
}
598
599
599
600
SQLExpr :: Struct { values, fields } => {
600
- self . parse_struct ( values , fields , schema , planner_context )
601
+ self . parse_struct ( schema , planner_context , values , fields )
601
602
}
602
603
SQLExpr :: Position { expr, r#in } => {
603
604
self . sql_position_to_expr ( * expr, * r#in, schema, planner_context)
@@ -629,6 +630,36 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
629
630
}
630
631
}
631
632
633
+ /// Parses a struct(..) expression and plans it creation
634
+ fn parse_struct (
635
+ & self ,
636
+ schema : & DFSchema ,
637
+ planner_context : & mut PlannerContext ,
638
+ values : Vec < sqlparser:: ast:: Expr > ,
639
+ fields : Vec < StructField > ,
640
+ ) -> Result < Expr > {
641
+ if !fields. is_empty ( ) {
642
+ return not_impl_err ! ( "Struct fields are not supported yet" ) ;
643
+ }
644
+ let is_named_struct = values
645
+ . iter ( )
646
+ . any ( |value| matches ! ( value, SQLExpr :: Named { .. } ) ) ;
647
+
648
+ let mut create_struct_args = if is_named_struct {
649
+ self . create_named_struct_expr ( values, schema, planner_context) ?
650
+ } else {
651
+ self . create_struct_expr ( values, schema, planner_context) ?
652
+ } ;
653
+
654
+ for planner in self . planners . iter ( ) {
655
+ match planner. plan_struct_literal ( create_struct_args, is_named_struct) ? {
656
+ PlannerResult :: Planned ( expr) => return Ok ( expr) ,
657
+ PlannerResult :: Original ( args) => create_struct_args = args,
658
+ }
659
+ }
660
+ not_impl_err ! ( "Struct not supported by UserDefinedExtensionPlanners: {create_struct_args:?}" )
661
+ }
662
+
632
663
fn sql_position_to_expr (
633
664
& self ,
634
665
substr_expr : SQLExpr ,
@@ -683,37 +714,15 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
683
714
not_impl_err ! ( "Unsupported dictionary literal: {raw_expr:?}" )
684
715
}
685
716
686
- /// Parses a struct(..) expression
687
- fn parse_struct (
688
- & self ,
689
- values : Vec < SQLExpr > ,
690
- fields : Vec < sqlparser:: ast:: StructField > ,
691
- input_schema : & DFSchema ,
692
- planner_context : & mut PlannerContext ,
693
- ) -> Result < Expr > {
694
- if !fields. is_empty ( ) {
695
- return not_impl_err ! ( "Struct fields are not supported yet" ) ;
696
- }
697
-
698
- if values
699
- . iter ( )
700
- . any ( |value| matches ! ( value, SQLExpr :: Named { .. } ) )
701
- {
702
- self . create_named_struct ( values, input_schema, planner_context)
703
- } else {
704
- self . create_struct ( values, input_schema, planner_context)
705
- }
706
- }
707
-
708
717
// Handles a call to struct(...) where the arguments are named. For example
709
718
// `struct (v as foo, v2 as bar)` by creating a call to the `named_struct` function
710
- fn create_named_struct (
719
+ fn create_named_struct_expr (
711
720
& self ,
712
721
values : Vec < SQLExpr > ,
713
722
input_schema : & DFSchema ,
714
723
planner_context : & mut PlannerContext ,
715
- ) -> Result < Expr > {
716
- let args = values
724
+ ) -> Result < Vec < Expr > > {
725
+ Ok ( values
717
726
. into_iter ( )
718
727
. enumerate ( )
719
728
. map ( |( i, value) | {
@@ -742,47 +751,24 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
742
751
. collect :: < Result < Vec < _ > > > ( ) ?
743
752
. into_iter ( )
744
753
. flatten ( )
745
- . collect ( ) ;
746
-
747
- let named_struct_func = self
748
- . context_provider
749
- . get_function_meta ( "named_struct" )
750
- . ok_or_else ( || {
751
- internal_datafusion_err ! ( "Unable to find expected 'named_struct' function" )
752
- } ) ?;
753
-
754
- Ok ( Expr :: ScalarFunction ( ScalarFunction :: new_udf (
755
- named_struct_func,
756
- args,
757
- ) ) )
754
+ . collect ( ) )
758
755
}
759
756
760
757
// Handles a call to struct(...) where the arguments are not named. For example
761
758
// `struct (v, v2)` by creating a call to the `struct` function
762
759
// which will create a struct with fields named `c0`, `c1`, etc.
763
- fn create_struct (
760
+ fn create_struct_expr (
764
761
& self ,
765
762
values : Vec < SQLExpr > ,
766
763
input_schema : & DFSchema ,
767
764
planner_context : & mut PlannerContext ,
768
- ) -> Result < Expr > {
769
- let args = values
765
+ ) -> Result < Vec < Expr > > {
766
+ values
770
767
. into_iter ( )
771
768
. map ( |value| {
772
769
self . sql_expr_to_logical_expr ( value, input_schema, planner_context)
773
770
} )
774
- . collect :: < Result < Vec < _ > > > ( ) ?;
775
- let struct_func = self
776
- . context_provider
777
- . get_function_meta ( "struct" )
778
- . ok_or_else ( || {
779
- internal_datafusion_err ! ( "Unable to find expected 'struct' function" )
780
- } ) ?;
781
-
782
- Ok ( Expr :: ScalarFunction ( ScalarFunction :: new_udf (
783
- struct_func,
784
- args,
785
- ) ) )
771
+ . collect :: < Result < Vec < _ > > > ( )
786
772
}
787
773
788
774
fn sql_in_list_to_expr (
0 commit comments