@@ -29,11 +29,9 @@ use itertools::Itertools;
2929use super :: prune_by_children;
3030use crate :: binder:: scalar:: ScalarBinder ;
3131use crate :: binder:: select:: SelectList ;
32- use crate :: binder:: window:: WindowFunctionInfo ;
3332use crate :: binder:: Binder ;
3433use crate :: binder:: ColumnBinding ;
3534use crate :: binder:: Visibility ;
36- use crate :: binder:: WindowOrderByInfo ;
3735use crate :: optimizer:: SExpr ;
3836use crate :: plans:: Aggregate ;
3937use crate :: plans:: AggregateFunction ;
@@ -86,16 +84,20 @@ pub struct AggregateInfo {
8684 pub grouping_sets : Vec < Vec < IndexType > > ,
8785}
8886
89- pub ( super ) struct AggregateAndWindowRewriter < ' a > {
87+ pub ( super ) struct AggregateRewriter < ' a > {
9088 pub bind_context : & ' a mut BindContext ,
9189 pub metadata : MetadataRef ,
90+ // If the aggregate function is in the arguments of window function,
91+ // ignore it here, it will be processed later when analyzing window.
92+ in_window : bool ,
9293}
9394
94- impl < ' a > AggregateAndWindowRewriter < ' a > {
95+ impl < ' a > AggregateRewriter < ' a > {
9596 pub fn new ( bind_context : & ' a mut BindContext , metadata : MetadataRef ) -> Self {
9697 Self {
9798 bind_context,
9899 metadata,
100+ in_window : false ,
99101 }
100102 }
101103
@@ -154,8 +156,55 @@ impl<'a> AggregateAndWindowRewriter<'a> {
154156
155157 ScalarExpr :: AggregateFunction ( agg_func) => self . replace_aggregate_function ( agg_func) ,
156158
157- // already resolved in `analyze_window_select`
158- ScalarExpr :: WindowFunction ( window) => self . replace_window_function ( window) ,
159+ ScalarExpr :: WindowFunction ( window) => {
160+ self . in_window = true ;
161+
162+ let partition_by = window
163+ . partition_by
164+ . iter ( )
165+ . map ( |part| self . visit ( part) )
166+ . collect :: < Result < Vec < _ > > > ( ) ?;
167+ let order_by = window
168+ . order_by
169+ . iter ( )
170+ . map ( |order| {
171+ Ok ( WindowOrderBy {
172+ expr : self . visit ( & order. expr ) ?,
173+ asc : order. asc ,
174+ nulls_first : order. nulls_first ,
175+ } )
176+ } )
177+ . collect :: < Result < Vec < _ > > > ( ) ?;
178+ let func = match & window. func {
179+ WindowFuncType :: Aggregate ( agg) => {
180+ let new_args = agg
181+ . args
182+ . iter ( )
183+ . map ( |arg| self . visit ( arg) )
184+ . collect :: < Result < Vec < _ > > > ( ) ?;
185+ WindowFuncType :: Aggregate ( AggregateFunction {
186+ func_name : agg. func_name . clone ( ) ,
187+ args : new_args,
188+ display_name : agg. display_name . clone ( ) ,
189+ distinct : agg. distinct ,
190+ params : agg. params . clone ( ) ,
191+ return_type : agg. return_type . clone ( ) ,
192+ } )
193+ }
194+ func => func. clone ( ) ,
195+ } ;
196+
197+ self . in_window = false ;
198+
199+ Ok ( WindowFunc {
200+ display_name : window. display_name . clone ( ) ,
201+ func,
202+ partition_by,
203+ order_by,
204+ frame : window. frame . clone ( ) ,
205+ }
206+ . into ( ) )
207+ }
159208 }
160209 }
161210
@@ -272,205 +321,17 @@ impl<'a> AggregateAndWindowRewriter<'a> {
272321
273322 Ok ( replaced_func. into ( ) )
274323 }
275-
276- fn replace_window_function ( & mut self , window : & WindowFunc ) -> Result < ScalarExpr > {
277- let window_infos = & mut self . bind_context . windows ;
278-
279- let mut replaced_partition_items: Vec < ScalarExpr > =
280- Vec :: with_capacity ( window. partition_by . len ( ) ) ;
281- let mut replaced_order_by_items: Vec < WindowOrderBy > =
282- Vec :: with_capacity ( window. order_by . len ( ) ) ;
283- let mut agg_args = vec ! [ ] ;
284-
285- let window_func_name = window. func . func_name ( ) ;
286- let func = match & window. func {
287- WindowFuncType :: Aggregate ( agg) => {
288- // resolve aggregate function args in window function.
289- let mut replaced_args: Vec < ScalarExpr > = Vec :: with_capacity ( agg. args . len ( ) ) ;
290- for ( i, arg) in agg. args . iter ( ) . enumerate ( ) {
291- let name = format ! ( "{}_arg_{}" , & window_func_name, i) ;
292- if let ScalarExpr :: BoundColumnRef ( column_ref) = arg {
293- replaced_args. push ( column_ref. clone ( ) . into ( ) ) ;
294- agg_args. push ( ScalarItem {
295- index : column_ref. column . index ,
296- scalar : arg. clone ( ) ,
297- } ) ;
298- } else {
299- let index = self
300- . metadata
301- . write ( )
302- . add_derived_column ( name. clone ( ) , arg. data_type ( ) ?) ;
303-
304- // Generate a ColumnBinding for each argument of aggregates
305- let column_binding = ColumnBinding {
306- database_name : None ,
307- table_name : None ,
308- column_name : name,
309- index,
310- data_type : Box :: new ( arg. data_type ( ) ?) ,
311- visibility : Visibility :: Visible ,
312- } ;
313- replaced_args. push (
314- BoundColumnRef {
315- span : arg. span ( ) ,
316- column : column_binding. clone ( ) ,
317- }
318- . into ( ) ,
319- ) ;
320- agg_args. push ( ScalarItem {
321- index,
322- scalar : arg. clone ( ) ,
323- } ) ;
324- }
325- }
326- WindowFuncType :: Aggregate ( AggregateFunction {
327- display_name : agg. display_name . clone ( ) ,
328- func_name : agg. func_name . clone ( ) ,
329- distinct : agg. distinct ,
330- params : agg. params . clone ( ) ,
331- args : replaced_args,
332- return_type : agg. return_type . clone ( ) ,
333- } )
334- }
335- func => func. clone ( ) ,
336- } ;
337-
338- // resolve partition by
339- let mut partition_by_items = vec ! [ ] ;
340- for ( i, part) in window. partition_by . iter ( ) . enumerate ( ) {
341- let name = format ! ( "{}_part_{}" , & window_func_name, i) ;
342- if let ScalarExpr :: BoundColumnRef ( column_ref) = part {
343- replaced_partition_items. push ( column_ref. clone ( ) . into ( ) ) ;
344- partition_by_items. push ( ScalarItem {
345- index : column_ref. column . index ,
346- scalar : part. clone ( ) ,
347- } ) ;
348- } else {
349- let index = self
350- . metadata
351- . write ( )
352- . add_derived_column ( name. clone ( ) , part. data_type ( ) ?) ;
353-
354- // Generate a ColumnBinding for each argument of aggregates
355- let column_binding = ColumnBinding {
356- database_name : None ,
357- table_name : None ,
358- column_name : name,
359- index,
360- data_type : Box :: new ( part. data_type ( ) ?) ,
361- visibility : Visibility :: Visible ,
362- } ;
363- replaced_partition_items. push (
364- BoundColumnRef {
365- span : part. span ( ) ,
366- column : column_binding. clone ( ) ,
367- }
368- . into ( ) ,
369- ) ;
370- partition_by_items. push ( ScalarItem {
371- index,
372- scalar : part. clone ( ) ,
373- } ) ;
374- }
375- }
376-
377- // resolve order by
378- let mut order_by_items = vec ! [ ] ;
379- for ( i, order) in window. order_by . iter ( ) . enumerate ( ) {
380- let name = format ! ( "{}_order_{}" , & window_func_name, i) ;
381- if let ScalarExpr :: BoundColumnRef ( column_ref) = & order. expr {
382- replaced_order_by_items. push ( WindowOrderBy {
383- expr : column_ref. clone ( ) . into ( ) ,
384- asc : order. asc ,
385- nulls_first : order. nulls_first ,
386- } ) ;
387- order_by_items. push ( WindowOrderByInfo {
388- order_by_item : ScalarItem {
389- index : column_ref. column . index ,
390- scalar : order. expr . clone ( ) ,
391- } ,
392- asc : order. asc ,
393- nulls_first : order. nulls_first ,
394- } )
395- } else {
396- let index = self
397- . metadata
398- . write ( )
399- . add_derived_column ( name. clone ( ) , order. expr . data_type ( ) ?) ;
400-
401- // Generate a ColumnBinding for each argument of aggregates
402- let column_binding = ColumnBinding {
403- database_name : None ,
404- table_name : None ,
405- column_name : name,
406- index,
407- data_type : Box :: new ( order. expr . data_type ( ) ?) ,
408- visibility : Visibility :: Visible ,
409- } ;
410- replaced_order_by_items. push ( WindowOrderBy {
411- expr : BoundColumnRef {
412- span : order. expr . span ( ) ,
413- column : column_binding,
414- }
415- . into ( ) ,
416- asc : order. asc ,
417- nulls_first : order. nulls_first ,
418- } ) ;
419- order_by_items. push ( WindowOrderByInfo {
420- order_by_item : ScalarItem {
421- index,
422- scalar : order. expr . clone ( ) ,
423- } ,
424- asc : order. asc ,
425- nulls_first : order. nulls_first ,
426- } )
427- }
428- }
429-
430- let index = self
431- . metadata
432- . write ( )
433- . add_derived_column ( window. display_name . clone ( ) , window. func . return_type ( ) ) ;
434-
435- // create window info
436- let window_info = WindowFunctionInfo {
437- index,
438- func : func. clone ( ) ,
439- arguments : agg_args,
440- partition_by_items,
441- order_by_items,
442- frame : window. frame . clone ( ) ,
443- } ;
444-
445- // push window info to BindContext
446- window_infos. window_functions . push ( window_info) ;
447- window_infos. window_functions_map . insert (
448- window. display_name . clone ( ) ,
449- window_infos. window_functions . len ( ) - 1 ,
450- ) ;
451-
452- let replaced_window = WindowFunc {
453- display_name : window. display_name . clone ( ) ,
454- func,
455- partition_by : replaced_partition_items,
456- order_by : replaced_order_by_items,
457- frame : window. frame . clone ( ) ,
458- } ;
459-
460- Ok ( replaced_window. into ( ) )
461- }
462324}
463-
464325impl Binder {
465- /// Analyze aggregates and windows in select clause, this will rewrite aggregate and window functions.
466- /// See `AggregateRewriter` for more details.
467- pub ( crate ) fn analyze_aggregate_and_window_select (
326+ /// Analyze aggregates in select clause, this will rewrite aggregate functions.
327+ /// See [ `AggregateRewriter`] for more details.
328+ pub ( crate ) fn analyze_aggregate_select (
468329 & mut self ,
469330 bind_context : & mut BindContext ,
470331 select_list : & mut SelectList ,
471332 ) -> Result < ( ) > {
472333 for item in select_list. items . iter_mut ( ) {
473- let mut rewriter = AggregateAndWindowRewriter :: new ( bind_context, self . metadata . clone ( ) ) ;
334+ let mut rewriter = AggregateRewriter :: new ( bind_context, self . metadata . clone ( ) ) ;
474335 let new_scalar = rewriter. visit ( & item. scalar ) ?;
475336 item. scalar = new_scalar;
476337 }
0 commit comments