1616// under the License.
1717
1818use std:: fmt:: Debug ;
19+ use std:: marker:: PhantomData ;
1920use std:: mem:: size_of;
2021use std:: sync:: Arc ;
2122
@@ -28,10 +29,10 @@ use datafusion_common::{DataFusionError, Result, internal_datafusion_err};
2829use datafusion_expr_common:: groups_accumulator:: { EmitTo , GroupsAccumulator } ;
2930
3031use crate :: aggregate:: groups_accumulator:: accumulate:: {
31- BlockedNullState , FlatNullState , NullState , SeenValueStore ,
32+ BlockedNullState , BooleanBlock , FlatNullState , NullState , SeenValueStore ,
3233} ;
3334use crate :: aggregate:: groups_accumulator:: block_store:: {
34- BlockStore , FlatBlockStore , VecValues , VecValuesBlockStore ,
35+ FlatBlockStore , VecValues , VecValuesBlockStore ,
3536} ;
3637use crate :: aggregate:: groups_accumulator:: blocks:: Blocks ;
3738use crate :: aggregate:: groups_accumulator:: group_index_operations:: {
@@ -51,10 +52,11 @@ use crate::aggregate::groups_accumulator::group_index_operations::{
5152pub struct PrimitiveGroupsAccumulator < T , F >
5253where
5354 T : ArrowPrimitiveType + Send ,
55+ T :: Native : Debug + Send ,
5456 F : Fn ( & mut T :: Native , T :: Native ) + Send + Sync + ' static ,
5557{
5658 /// Values and null state per group, stored according to the current group mode.
57- state : PrimitiveGroupsState < T :: Native > ,
59+ state : PrimitiveGroupsStateAdapter < T :: Native > ,
5860
5961 /// The output type (needed for Decimal precision and scale)
6062 data_type : DataType ,
@@ -66,29 +68,15 @@ where
6668 prim_fn : F ,
6769}
6870
69- #[ derive( Debug ) ]
70- enum PrimitiveGroupsState < V : Clone + Debug > {
71- Flat {
72- values : FlatBlockStore < VecValues < V > > ,
73- null_state : FlatNullState ,
74- } ,
75- Blocked {
76- values : Blocks < VecValues < V > > ,
77- null_state : BlockedNullState ,
78- } ,
79- }
80-
8171impl < T , F > PrimitiveGroupsAccumulator < T , F >
8272where
8373 T : ArrowPrimitiveType + Send ,
74+ T :: Native : Debug + Send ,
8475 F : Fn ( & mut T :: Native , T :: Native ) + Send + Sync + ' static ,
8576{
8677 pub fn new ( data_type : & DataType , prim_fn : F ) -> Self {
8778 Self {
88- state : PrimitiveGroupsState :: Flat {
89- values : FlatBlockStore :: new ( ) ,
90- null_state : FlatNullState :: new ( None ) ,
91- } ,
79+ state : PrimitiveGroupsStateAdapter :: new_flat ( ) ,
9280 data_type : data_type. clone ( ) ,
9381 starting_value : T :: default_value ( ) ,
9482 prim_fn,
@@ -110,59 +98,155 @@ struct UpdateBatchInput<'a, T: ArrowPrimitiveType> {
11098 total_num_groups : usize ,
11199}
112100
113- fn update_batch_for < T , F , O , V , N > (
114- values_store : & mut V ,
115- null_state : & mut NullState < O , N > ,
116- input : & UpdateBatchInput < ' _ , T > ,
117- starting_value : T :: Native ,
118- prim_fn : & F ,
119- ) where
120- T : ArrowPrimitiveType + Send ,
121- T :: Native : Debug ,
122- F : Fn ( & mut T :: Native , T :: Native ) + Send + Sync + ' static ,
101+ #[ derive( Debug ) ]
102+ struct PrimitiveGroupsState < V , VB , O , S >
103+ where
104+ V : Clone + Debug ,
105+ VB : VecValuesBlockStore < V > + Send ,
123106 O : GroupIndexOperations ,
124- V : BlockStore < VecValues < T :: Native > > + Send ,
125- N : SeenValueStore + Send ,
107+ S : SeenValueStore + Send ,
126108{
127- // Expand to ensure values are large enough
128- let new_block = |block_size : Option < usize > | {
129- // In blocked mode, pre-allocate the full block capacity.
130- // In flat mode (block_size=None), start with an empty Vec
131- // and let `resize` grow it to exactly `total_num_groups`,
132- // matching the standard Vec growth behavior.
133- match block_size {
134- Some ( cap) => VecValues :: with_capacity ( cap) ,
135- None => VecValues :: default ( ) ,
109+ values : VB ,
110+ null_state : NullState < O , S > ,
111+ _phantom : PhantomData < V > ,
112+ }
113+
114+ impl < V , VB , O , S > PrimitiveGroupsState < V , VB , O , S >
115+ where
116+ V : Clone + Debug ,
117+ VB : VecValuesBlockStore < V > + Send ,
118+ O : GroupIndexOperations ,
119+ S : SeenValueStore + Send ,
120+ {
121+ fn new ( values : VB , null_state : NullState < O , S > ) -> Self {
122+ Self {
123+ values,
124+ null_state,
125+ _phantom : PhantomData ,
136126 }
137- } ;
138- values_store. resize ( input. total_num_groups , new_block, starting_value) ;
139-
140- null_state. accumulate (
141- input. group_indices ,
142- input. values ,
143- input. opt_filter ,
144- input. total_num_groups ,
145- |block_id, block_offset, new_value| {
146- // SAFETY: `block_id` and `block_offset` are guaranteed to be in bounds
147- let value = unsafe {
148- values_store[ block_id as usize ] . get_unchecked_mut ( block_offset as usize )
149- } ;
150- prim_fn ( value, new_value) ;
151- } ,
152- ) ;
127+ }
128+
129+ fn update_batch < T , F > (
130+ & mut self ,
131+ input : & UpdateBatchInput < ' _ , T > ,
132+ starting_value : V ,
133+ prim_fn : & F ,
134+ ) where
135+ T : ArrowPrimitiveType < Native = V > + Send ,
136+ F : Fn ( & mut V , V ) + Send + Sync + ' static ,
137+ {
138+ // Expand to ensure values are large enough
139+ let new_block = |block_size : Option < usize > | {
140+ // In blocked mode, pre-allocate the full block capacity.
141+ // In flat mode (block_size=None), start with an empty Vec
142+ // and let `resize` grow it to exactly `total_num_groups`,
143+ // matching the standard Vec growth behavior.
144+ match block_size {
145+ Some ( cap) => VecValues :: with_capacity ( cap) ,
146+ None => VecValues :: default ( ) ,
147+ }
148+ } ;
149+ self . values
150+ . resize ( input. total_num_groups , new_block, starting_value) ;
151+
152+ self . null_state . accumulate (
153+ input. group_indices ,
154+ input. values ,
155+ input. opt_filter ,
156+ input. total_num_groups ,
157+ |block_id, block_offset, new_value| {
158+ // SAFETY: `block_id` and `block_offset` are guaranteed to be in bounds
159+ let value = unsafe {
160+ self . values [ block_id as usize ]
161+ . get_unchecked_mut ( block_offset as usize )
162+ } ;
163+ prim_fn ( value, new_value) ;
164+ } ,
165+ ) ;
166+ }
167+
168+ fn evaluate ( & mut self , emit_to : EmitTo ) -> Result < ( Vec < V > , Option < NullBuffer > ) > {
169+ Ok ( ( self . values . emit ( emit_to) ?, self . null_state . build ( emit_to) ) )
170+ }
171+
172+ fn size ( & self ) -> usize {
173+ if self . values . is_empty ( ) {
174+ return 0 ;
175+ }
176+ self . values . num_blocks ( ) * self . values [ 0 ] . capacity ( ) * size_of :: < V > ( )
177+ + self . null_state . size ( )
178+ }
153179}
154180
155- fn values_size < T : Clone + Debug , V : BlockStore < VecValues < T > > > ( values : & V ) -> usize {
156- if values. is_empty ( ) {
157- return 0 ;
181+ type FlatPrimitiveGroupsState < V > = PrimitiveGroupsState <
182+ V ,
183+ FlatBlockStore < VecValues < V > > ,
184+ FlatGroupIndexOperations ,
185+ FlatBlockStore < BooleanBlock > ,
186+ > ;
187+
188+ type BlockedPrimitiveGroupsState < V > = PrimitiveGroupsState <
189+ V ,
190+ Blocks < VecValues < V > > ,
191+ BlockedGroupIndexOperations ,
192+ Blocks < BooleanBlock > ,
193+ > ;
194+
195+ #[ derive( Debug ) ]
196+ enum PrimitiveGroupsStateAdapter < V : Clone + Debug + Send > {
197+ Flat ( FlatPrimitiveGroupsState < V > ) ,
198+ Blocked ( BlockedPrimitiveGroupsState < V > ) ,
199+ }
200+
201+ impl < V : Clone + Debug + Send > PrimitiveGroupsStateAdapter < V > {
202+ fn new_flat ( ) -> Self {
203+ Self :: Flat ( PrimitiveGroupsState :: new (
204+ FlatBlockStore :: new ( ) ,
205+ FlatNullState :: new ( None ) ,
206+ ) )
207+ }
208+
209+ fn new_blocked ( block_size : usize ) -> Self {
210+ Self :: Blocked ( PrimitiveGroupsState :: new (
211+ Blocks :: new ( Some ( block_size) ) ,
212+ BlockedNullState :: new ( Some ( block_size) ) ,
213+ ) )
214+ }
215+
216+ fn update_batch < T , F > (
217+ & mut self ,
218+ input : & UpdateBatchInput < ' _ , T > ,
219+ starting_value : V ,
220+ prim_fn : & F ,
221+ ) where
222+ T : ArrowPrimitiveType < Native = V > + Send ,
223+ F : Fn ( & mut V , V ) + Send + Sync + ' static ,
224+ {
225+ match self {
226+ Self :: Flat ( state) => state. update_batch ( input, starting_value, prim_fn) ,
227+ Self :: Blocked ( state) => state. update_batch ( input, starting_value, prim_fn) ,
228+ }
229+ }
230+
231+ fn evaluate ( & mut self , emit_to : EmitTo ) -> Result < ( Vec < V > , Option < NullBuffer > ) > {
232+ match self {
233+ Self :: Flat ( state) => state. evaluate ( emit_to) ,
234+ Self :: Blocked ( state) => state. evaluate ( emit_to) ,
235+ }
236+ }
237+
238+ fn size ( & self ) -> usize {
239+ match self {
240+ Self :: Flat ( state) => state. size ( ) ,
241+ Self :: Blocked ( state) => state. size ( ) ,
242+ }
158243 }
159- values. num_blocks ( ) * values[ 0 ] . capacity ( ) * size_of :: < T > ( )
160244}
161245
162246impl < T , F > GroupsAccumulator for PrimitiveGroupsAccumulator < T , F >
163247where
164248 T : ArrowPrimitiveType + Send ,
165- T :: Native : Debug ,
249+ T :: Native : Debug + Send ,
166250 F : Fn ( & mut T :: Native , T :: Native ) + Send + Sync + ' static ,
167251{
168252 fn update_batch (
@@ -174,52 +258,22 @@ where
174258 ) -> Result < ( ) > {
175259 assert_eq ! ( values. len( ) , 1 , "single argument to update_batch" ) ;
176260 let input_values = values[ 0 ] . as_primitive :: < T > ( ) ;
177-
178- match & mut self . state {
179- PrimitiveGroupsState :: Flat { values, null_state } => {
180- update_batch_for :: < T , F , FlatGroupIndexOperations , _ , _ > (
181- values,
182- null_state,
183- & UpdateBatchInput {
184- values : input_values,
185- group_indices,
186- opt_filter,
187- total_num_groups,
188- } ,
189- self . starting_value ,
190- & self . prim_fn ,
191- ) ;
192- }
193- PrimitiveGroupsState :: Blocked { values, null_state } => {
194- update_batch_for :: < T , F , BlockedGroupIndexOperations , _ , _ > (
195- values,
196- null_state,
197- & UpdateBatchInput {
198- values : input_values,
199- group_indices,
200- opt_filter,
201- total_num_groups,
202- } ,
203- self . starting_value ,
204- & self . prim_fn ,
205- ) ;
206- }
207- }
261+ self . state . update_batch (
262+ & UpdateBatchInput {
263+ values : input_values,
264+ group_indices,
265+ opt_filter,
266+ total_num_groups,
267+ } ,
268+ self . starting_value ,
269+ & self . prim_fn ,
270+ ) ;
208271
209272 Ok ( ( ) )
210273 }
211274
212275 fn evaluate ( & mut self , emit_to : EmitTo ) -> Result < ArrayRef > {
213- let ( values, nulls) : ( Vec < T :: Native > , _ ) = match & mut self . state {
214- PrimitiveGroupsState :: Flat { values, null_state } => (
215- VecValuesBlockStore :: emit ( values, emit_to) ?,
216- null_state. build ( emit_to) ,
217- ) ,
218- PrimitiveGroupsState :: Blocked { values, null_state } => (
219- VecValuesBlockStore :: emit ( values, emit_to) ?,
220- null_state. build ( emit_to) ,
221- ) ,
222- } ;
276+ let ( values, nulls) = self . state . evaluate ( emit_to) ?;
223277 let values = PrimitiveArray :: < T > :: new ( values. into ( ) , nulls) // no copy
224278 . with_data_type ( self . data_type . clone ( ) ) ;
225279 Ok ( Arc :: new ( values) )
@@ -298,20 +352,7 @@ where
298352 }
299353
300354 fn size ( & self ) -> usize {
301- match & self . state {
302- PrimitiveGroupsState :: Flat { values, null_state } => {
303- if values. is_empty ( ) {
304- return 0 ;
305- }
306- values_size :: < T :: Native , _ > ( values) + null_state. size ( )
307- }
308- PrimitiveGroupsState :: Blocked { values, null_state } => {
309- if values. is_empty ( ) {
310- return 0 ;
311- }
312- values_size :: < T :: Native , _ > ( values) + null_state. size ( )
313- }
314- }
355+ self . state . size ( )
315356 }
316357
317358 fn supports_blocked_groups ( & self ) -> bool {
@@ -320,15 +361,9 @@ where
320361
321362 fn alter_block_size ( & mut self , block_size : Option < usize > ) -> Result < ( ) > {
322363 self . state = if let Some ( block_size) = block_size {
323- PrimitiveGroupsState :: Blocked {
324- values : Blocks :: new ( Some ( block_size) ) ,
325- null_state : BlockedNullState :: new ( Some ( block_size) ) ,
326- }
364+ PrimitiveGroupsStateAdapter :: new_blocked ( block_size)
327365 } else {
328- PrimitiveGroupsState :: Flat {
329- values : FlatBlockStore :: new ( ) ,
330- null_state : FlatNullState :: new ( None ) ,
331- }
366+ PrimitiveGroupsStateAdapter :: new_flat ( )
332367 } ;
333368
334369 Ok ( ( ) )
0 commit comments