@@ -20,6 +20,7 @@ use crate::aggregates::group_values::multi_group_by::GroupColumn;
2020use arrow:: array:: {
2121 Array , ArrayRef , AsArray , BooleanBufferBuilder , DictionaryArray , PrimitiveArray ,
2222} ;
23+ use arrow:: compute:: concat;
2324use arrow:: datatypes:: { ArrowDictionaryKeyType , ArrowNativeType , Field } ;
2425use datafusion_common:: Result ;
2526use std:: marker:: PhantomData ;
@@ -28,6 +29,8 @@ use std::sync::Arc;
2829pub struct DictionaryGroupValuesColumn < K : ArrowDictionaryKeyType + Send + Sync > {
2930 inner : Box < dyn GroupColumn > ,
3031 null_array : ArrayRef ,
32+ cached_values : Option < ArrayRef > ,
33+ cached_combined : Option < ArrayRef > ,
3134 _phantom : PhantomData < K > ,
3235}
3336
@@ -37,10 +40,26 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> DictionaryGroupValuesColumn<K> {
3740 Self {
3841 inner,
3942 null_array,
43+ cached_values : None ,
44+ cached_combined : None ,
4045 _phantom : PhantomData ,
4146 }
4247 }
4348
49+ #[ inline]
50+ fn get_combined ( & mut self , values : & ArrayRef ) -> Result < ArrayRef > {
51+ let is_cached = self
52+ . cached_values
53+ . as_ref ( )
54+ . is_some_and ( |cached| Arc :: ptr_eq ( cached, values) ) ;
55+ if !is_cached {
56+ self . cached_combined =
57+ Some ( concat ( & [ values. as_ref ( ) , self . null_array . as_ref ( ) ] ) ?) ;
58+ self . cached_values = Some ( Arc :: clone ( values) ) ;
59+ }
60+ Ok ( Arc :: clone ( self . cached_combined . as_ref ( ) . unwrap ( ) ) )
61+ }
62+
4463 #[ inline]
4564 fn into_dict ( values : ArrayRef ) -> ArrayRef {
4665 // at some point in the future we may want to support bumping the key types
@@ -119,14 +138,14 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> GroupColumn
119138 rows. iter ( ) . map ( |& r| keys. value ( r) . as_usize ( ) ) . collect ( ) ;
120139 self . inner . vectorized_append ( dict. values ( ) , & key_indices)
121140 } else {
122- let values = dict. values ( ) ;
123- for & row in rows {
124- match dict . key ( row ) {
125- None => self . inner . append_val ( & self . null_array , 0 ) ? ,
126- Some ( k ) => self . inner . append_val ( values , k ) ? ,
127- }
128- }
129- Ok ( ( ) )
141+ let combined = self . get_combined ( dict. values ( ) ) ? ;
142+ // last element of combined is always the null sentinel appended by get_combined
143+ let null_idx = combined . len ( ) - 1 ;
144+ let key_indices : Vec < usize > = rows
145+ . iter ( )
146+ . map ( | & r| dict . key ( r ) . unwrap_or ( null_idx ) )
147+ . collect ( ) ;
148+ self . inner . vectorized_append ( & combined , & key_indices )
130149 }
131150 }
132151
0 commit comments