@@ -36,44 +36,57 @@ use super::arrow_cast::ARROW_CAST_NAME;
3636impl < ' a , S : ContextProvider > SqlToRel < ' a , S > {
3737 pub ( super ) fn sql_function_to_expr (
3838 & self ,
39- mut function : SQLFunction ,
39+ function : SQLFunction ,
4040 schema : & DFSchema ,
4141 planner_context : & mut PlannerContext ,
4242 ) -> Result < Expr > {
43- let name = if function. name . 0 . len ( ) > 1 {
43+ let SQLFunction {
44+ name,
45+ args,
46+ over,
47+ distinct,
48+ filter,
49+ null_treatment,
50+ special : _, // true if not called with trailing parens
51+ order_by,
52+ } = function;
53+
54+ if let Some ( null_treatment) = null_treatment {
55+ return not_impl_err ! ( "Null treatment in aggregate functions is not supported: {null_treatment}" ) ;
56+ }
57+
58+ let name = if name. 0 . len ( ) > 1 {
4459 // DF doesn't handle compound identifiers
4560 // (e.g. "foo.bar") for function names yet
46- function . name . to_string ( )
61+ name. to_string ( )
4762 } else {
48- crate :: utils:: normalize_ident ( function . name . 0 [ 0 ] . clone ( ) )
63+ crate :: utils:: normalize_ident ( name. 0 [ 0 ] . clone ( ) )
4964 } ;
5065
5166 // user-defined function (UDF) should have precedence in case it has the same name as a scalar built-in function
5267 if let Some ( fm) = self . context_provider . get_function_meta ( & name) {
53- let args =
54- self . function_args_to_expr ( function. args , schema, planner_context) ?;
68+ let args = self . function_args_to_expr ( args, schema, planner_context) ?;
5569 return Ok ( Expr :: ScalarUDF ( ScalarUDF :: new ( fm, args) ) ) ;
5670 }
5771
5872 // next, scalar built-in
5973 if let Ok ( fun) = BuiltinScalarFunction :: from_str ( & name) {
60- let args =
61- self . function_args_to_expr ( function. args , schema, planner_context) ?;
74+ let args = self . function_args_to_expr ( args, schema, planner_context) ?;
6275 return Ok ( Expr :: ScalarFunction ( ScalarFunction :: new ( fun, args) ) ) ;
6376 } ;
6477
6578 // If function is a window function (it has an OVER clause),
6679 // it shouldn't have ordering requirement as function argument
6780 // required ordering should be defined in OVER clause.
68- let is_function_window = function . over . is_some ( ) ;
69- if !function . order_by . is_empty ( ) && is_function_window {
81+ let is_function_window = over. is_some ( ) ;
82+ if !order_by. is_empty ( ) && is_function_window {
7083 return plan_err ! (
7184 "Aggregate ORDER BY is not implemented for window functions"
7285 ) ;
7386 }
7487
7588 // then, window function
76- if let Some ( WindowType :: WindowSpec ( window) ) = function . over . take ( ) {
89+ if let Some ( WindowType :: WindowSpec ( window) ) = over {
7790 let partition_by = window
7891 . partition_by
7992 . into_iter ( )
@@ -97,11 +110,8 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
97110 if let Ok ( fun) = self . find_window_func ( & name) {
98111 let expr = match fun {
99112 WindowFunction :: AggregateFunction ( aggregate_fun) => {
100- let args = self . function_args_to_expr (
101- function. args ,
102- schema,
103- planner_context,
104- ) ?;
113+ let args =
114+ self . function_args_to_expr ( args, schema, planner_context) ?;
105115
106116 Expr :: WindowFunction ( expr:: WindowFunction :: new (
107117 WindowFunction :: AggregateFunction ( aggregate_fun) ,
@@ -113,11 +123,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
113123 }
114124 _ => Expr :: WindowFunction ( expr:: WindowFunction :: new (
115125 fun,
116- self . function_args_to_expr (
117- function. args ,
118- schema,
119- planner_context,
120- ) ?,
126+ self . function_args_to_expr ( args, schema, planner_context) ?,
121127 partition_by,
122128 order_by,
123129 window_frame,
@@ -128,26 +134,19 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
128134 } else {
129135 // User defined aggregate functions (UDAF) have precedence in case it has the same name as a scalar built-in function
130136 if let Some ( fm) = self . context_provider . get_aggregate_meta ( & name) {
131- let args =
132- self . function_args_to_expr ( function. args , schema, planner_context) ?;
137+ let args = self . function_args_to_expr ( args, schema, planner_context) ?;
133138 return Ok ( Expr :: AggregateUDF ( expr:: AggregateUDF :: new (
134139 fm, args, None , None ,
135140 ) ) ) ;
136141 }
137142
138143 // next, aggregate built-ins
139144 if let Ok ( fun) = AggregateFunction :: from_str ( & name) {
140- let distinct = function. distinct ;
141- let order_by = self . order_by_to_sort_expr (
142- & function. order_by ,
143- schema,
144- planner_context,
145- ) ?;
145+ let order_by =
146+ self . order_by_to_sort_expr ( & order_by, schema, planner_context) ?;
146147 let order_by = ( !order_by. is_empty ( ) ) . then_some ( order_by) ;
147- let args =
148- self . function_args_to_expr ( function. args , schema, planner_context) ?;
149- let filter: Option < Box < Expr > > = function
150- . filter
148+ let args = self . function_args_to_expr ( args, schema, planner_context) ?;
149+ let filter: Option < Box < Expr > > = filter
151150 . map ( |e| self . sql_expr_to_logical_expr ( * e, schema, planner_context) )
152151 . transpose ( ) ?
153152 . map ( Box :: new) ;
@@ -159,8 +158,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
159158
160159 // Special case arrow_cast (as its type is dependent on its argument value)
161160 if name == ARROW_CAST_NAME {
162- let args =
163- self . function_args_to_expr ( function. args , schema, planner_context) ?;
161+ let args = self . function_args_to_expr ( args, schema, planner_context) ?;
164162 return super :: arrow_cast:: create_arrow_cast ( args, schema) ;
165163 }
166164 }
0 commit comments