1717
1818//! Vectorized [`GroupsAccumulator`]
1919
20+ use std:: collections:: VecDeque ;
21+
2022use arrow:: array:: { ArrayRef , BooleanArray } ;
2123use datafusion_common:: { not_impl_err, DataFusionError , Result } ;
2224
@@ -31,15 +33,40 @@ pub enum EmitTo {
3133 /// For example, if `n=10`, group_index `0, 1, ... 9` are emitted
3234 /// and group indexes `10, 11, 12, ...` become `0, 1, 2, ...`.
3335 First ( usize ) ,
36+ /// Emit next block in the blocked managed groups
37+ ///
38+ /// The flag's meaning:
39+ /// - `true` represents new groups still will be added,
40+ /// and we need to shift the values down.
41+ /// - `false` represents no new groups will be added again,
42+ /// and we don't need to shift the values down.
43+ NextBlock ( bool ) ,
3444}
3545
3646impl EmitTo {
47+ /// Remove and return `needed values` from `values`.
48+ pub fn take_needed < T > (
49+ & self ,
50+ values : & mut VecDeque < Vec < T > > ,
51+ is_blocked_groups : bool ,
52+ ) -> Vec < T > {
53+ if is_blocked_groups {
54+ self . take_needed_block ( values)
55+ } else {
56+ assert_eq ! ( values. len( ) , 1 ) ;
57+ self . take_needed_rows ( values. back_mut ( ) . unwrap ( ) )
58+ }
59+ }
60+
3761 /// Removes the number of rows from `v` required to emit the right
3862 /// number of rows, returning a `Vec` with elements taken, and the
3963 /// remaining values in `v`.
4064 ///
4165 /// This avoids copying if Self::All
42- pub fn take_needed < T > ( & self , v : & mut Vec < T > ) -> Vec < T > {
66+ ///
67+ /// NOTICE: only support emit strategies: `Self::All` and `Self::First`
68+ ///
69+ pub fn take_needed_rows < T > ( & self , v : & mut Vec < T > ) -> Vec < T > {
4370 match self {
4471 Self :: All => {
4572 // Take the entire vector, leave new (empty) vector
@@ -52,8 +79,23 @@ impl EmitTo {
5279 std:: mem:: swap ( v, & mut t) ;
5380 t
5481 }
82+ Self :: NextBlock ( _) => unreachable ! ( "don't support take block in take_needed" ) ,
5583 }
5684 }
85+
86+ /// Removes one block required to emit and return it
87+ ///
88+ /// NOTICE: only support emit strategy `Self::NextBlock`
89+ ///
90+ fn take_needed_block < T > ( & self , blocks : & mut VecDeque < Vec < T > > ) -> Vec < T > {
91+ assert ! (
92+ matches!( self , Self :: NextBlock ( _) ) ,
93+ "only support take block in take_needed_block"
94+ ) ;
95+ blocks
96+ . pop_front ( )
97+ . expect ( "should not call emit for empty blocks" )
98+ }
5799}
58100
59101/// `GroupsAccumulator` implements a single aggregate (e.g. AVG) and
0 commit comments