jayzhan211 commented on code in PR #12008:
URL: https://github.com/apache/arrow-rs/pull/12008#discussion_r4504315587


##########
arrow-select/src/coalesce/dictionary.rs:
##########
@@ -153,12 +153,18 @@ impl<K: ArrowDictionaryKeyType> 
InProgressDictionaryArray<K> {
             match &chunk.nulls {
                 Some(nulls) => 
keys.extend(chunk.keys.iter().enumerate().map(|(offset, key)| {
                     if nulls.is_valid(offset) {
-                        mapping[key.as_usize()]
+                        mapping

Review Comment:
   Optional cleanup: `merge_dictionary_values_with_masks` only returns dense 
mappings, so matching once per chunk keeps this loop the same as on main 
instead of matching the enum and calling `expect` for every key. The 
`coalesce_kernels` dictionary benchmarks were within noise either way, so this 
is only about keeping the hot loop simple.
   
   ```diff
   -use crate::dictionary::{child_values_ptr_eq, 
merge_dictionary_values_with_masks};
   +use crate::dictionary::{KeyMapping, child_values_ptr_eq, 
merge_dictionary_values_with_masks};
   @@
   -            let mapping = &merged.key_mappings[chunk.source];
   +            let KeyMapping::Dense(mapping) = 
&merged.key_mappings[chunk.source] else {
   +                unreachable!("merge_dictionary_values_with_masks returns 
dense mappings");
   +            };
                match &chunk.nulls {
                    Some(nulls) => 
keys.extend(chunk.keys.iter().enumerate().map(|(offset, key)| {
                        if nulls.is_valid(offset) {
   -                        mapping
   -                            .get(key.as_usize())
   -                            .expect("referenced dictionary key should be 
mapped")
   +                        mapping[key.as_usize()]
                        } else {
                            K::Native::default()
                        }
                    })),
   -                None => keys.extend(chunk.keys.iter().map(|key| {
   -                    mapping
   -                        .get(key.as_usize())
   -                        .expect("referenced dictionary key should be 
mapped")
   -                })),
   +                None => keys.extend(chunk.keys.iter().map(|key| 
mapping[key.as_usize()])),
                }
   ```



##########
arrow-select/src/concat.rs:
##########
@@ -1567,6 +1577,41 @@ mod tests {
         assert!((30..40).contains(&values_len), "{values_len}")
     }
 
+    #[test]
+    fn test_concat_sparse_primitive_dictionaries_with_nulls() {
+        let values_len = 3 * 
crate::dictionary::MAX_DENSE_MAPPING_VALUES_PER_ROW + 1;
+        let last = values_len as i32 - 1;
+        let make_dictionary = |offset, null_value, keys| {
+            let values = Int32Array::from_iter(
+                (0..values_len).map(|idx| (idx != null_value).then_some(offset 
+ idx as i32)),
+            );
+            DictionaryArray::<Int32Type>::new(Int32Array::from(keys), 
Arc::new(values))
+        };
+        let a = make_dictionary(0, 1, vec![Some(last), None, Some(1)]);
+        let b = make_dictionary(10_000, 2, vec![Some(2), Some(last - 1), 
None]);

Review Comment:
   Could you slice the inputs in this test? Since 
`test_concat_oversized_dictionary_slices` was replaced, no test sends a sliced 
dictionary through the sparse path, which is the case in this PR's title. With 
the change below both inputs, including their null buffers, start at offset 1, 
and the test also checks that the gate counts the sliced length: the unsliced 
arrays have 4 keys, and 4 × 256 ≥ 769 would keep them dense.
   
   ```suggestion
           // Slicing moves the keys and their nulls to a non-zero offset; the 
unsliced
           // arrays have 4 keys each and would take the dense path.
           let a = make_dictionary(0, 1, vec![Some(0), Some(last), None, 
Some(1)]).slice(1, 3);
           let b =
               make_dictionary(10_000, 2, vec![Some(0), Some(2), Some(last - 
1), None]).slice(1, 3);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to