@@ -58,12 +58,12 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> DictionaryGroupValuesColumn<K> {
5858
5959 /// Returns an error if adding `additional` groups would overflow the key type's range.
6060 // https://github.com/apache/datafusion/issues/23127
61- fn check_key_overflow ( current_len : usize , additional : usize ) -> Result < ( ) > {
62- if !Self :: valid_bounds :: < K > ( current_len + additional ) {
61+ fn check_key_overflow ( current_len : usize ) -> Result < ( ) > {
62+ if !Self :: valid_bounds :: < K > ( current_len) {
6363 return exec_err ! (
6464 "Dictionary key type {:?} cannot represent {} groups" ,
6565 K :: DATA_TYPE ,
66- current_len + additional
66+ current_len
6767 ) ;
6868 }
6969 Ok ( ( ) )
@@ -97,12 +97,12 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> GroupColumn
9797 }
9898
9999 fn append_val ( & mut self , array : & ArrayRef , row : usize ) -> Result < ( ) > {
100- Self :: check_key_overflow ( self . inner . len ( ) , 1 ) ?;
101100 let dict = array. as_dictionary :: < K > ( ) ;
102101 match dict. key ( row) {
103- None => self . inner . append_val ( & self . null_array , 0 ) ,
104- Some ( key) => self . inner . append_val ( dict. values ( ) , key) ,
102+ None => self . inner . append_val ( & self . null_array , 0 ) ? ,
103+ Some ( key) => self . inner . append_val ( dict. values ( ) , key) ? ,
105104 }
105+ Self :: check_key_overflow ( self . inner . len ( ) )
106106 }
107107
108108 fn vectorized_equal_to (
@@ -161,7 +161,6 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> GroupColumn
161161 }
162162
163163 fn vectorized_append ( & mut self , array : & ArrayRef , rows : & [ usize ] ) -> Result < ( ) > {
164- Self :: check_key_overflow ( self . inner . len ( ) , rows. len ( ) ) ?;
165164 let dict = array. as_dictionary :: < K > ( ) ;
166165 let dict_keys = dict. keys ( ) ;
167166
@@ -170,15 +169,17 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> GroupColumn
170169 . iter ( )
171170 . map ( |& row_index| dict_keys. value ( row_index) . as_usize ( ) )
172171 . collect ( ) ;
173- self . inner . vectorized_append ( dict. values ( ) , & value_indices)
172+ self . inner
173+ . vectorized_append ( dict. values ( ) , & value_indices) ?;
174174 } else if let Some ( sentinel) = Self :: null_sentinel_index ( dict. values ( ) ) {
175175 // Values already contains a null entry; reuse its position as the
176176 // sentinel so null keys map there without any allocation.
177177 let value_indices: Vec < usize > = rows
178178 . iter ( )
179179 . map ( |& row_index| dict. key ( row_index) . unwrap_or ( sentinel) )
180180 . collect ( ) ;
181- self . inner . vectorized_append ( dict. values ( ) , & value_indices)
181+ self . inner
182+ . vectorized_append ( dict. values ( ) , & value_indices) ?;
182183 } else {
183184 // Null keys but values has no null entry: scalar fallback per row.
184185 for & row_index in rows {
@@ -187,8 +188,8 @@ impl<K: ArrowDictionaryKeyType + Send + Sync> GroupColumn
187188 Some ( key) => self . inner . append_val ( dict. values ( ) , key) ?,
188189 }
189190 }
190- Ok ( ( ) )
191191 }
192+ Self :: check_key_overflow ( self . inner . len ( ) )
192193 }
193194
194195 fn len ( & self ) -> usize {
@@ -370,4 +371,37 @@ mod tests {
370371 assert ! ( out. as_dictionary:: <Int32Type >( ) . key( 2 ) . is_none( ) ) ;
371372 assert_eq ! ( u64_val( & out, 3 ) , 99 ) ;
372373 }
374+
375+ // Regression test for https://github.com/apache/datafusion/issues/23127 —
376+ // we should fail early when we can't produce the correct output schema.
377+ #[ test]
378+ fn uint8_key_overflow ( ) {
379+ use arrow:: array:: UInt8Array ;
380+ use arrow:: datatypes:: UInt8Type ;
381+ use datafusion_physical_expr:: binary_map:: OutputType ;
382+
383+ let field = Field :: new ( "" , DataType :: Utf8 , true ) ;
384+ let mut col = DictionaryGroupValuesColumn :: < UInt8Type > :: new (
385+ Box :: new ( ByteGroupValueBuilder :: < i32 > :: new ( OutputType :: Utf8 ) ) ,
386+ & field,
387+ ) ;
388+
389+ // fill all 256 distinct values (u8 key range 0..=255)
390+ let strs: Vec < String > = ( 0 ..=255u16 ) . map ( |i| i. to_string ( ) ) . collect ( ) ;
391+ let str_refs: Vec < & str > = strs. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
392+ let full: ArrayRef = Arc :: new ( DictionaryArray :: < UInt8Type > :: new (
393+ UInt8Array :: from ( ( 0 ..=255u8 ) . map ( Some ) . collect :: < Vec < _ > > ( ) ) ,
394+ Arc :: new ( StringArray :: from ( str_refs) ) ,
395+ ) ) ;
396+ let rows: Vec < usize > = ( 0 ..256 ) . collect ( ) ;
397+ col. vectorized_append ( & full, & rows) . unwrap ( ) ;
398+ assert_eq ! ( col. len( ) , 256 ) ;
399+
400+ // one more must overflow the key range
401+ let extra: ArrayRef = Arc :: new ( DictionaryArray :: < UInt8Type > :: new (
402+ UInt8Array :: from ( vec ! [ Some ( 0u8 ) ] ) ,
403+ Arc :: new ( StringArray :: from ( vec ! [ "overflow" ] ) ) ,
404+ ) ) ;
405+ assert ! ( col. append_val( & extra, 0 ) . is_err( ) ) ;
406+ }
373407}
0 commit comments