1use std::{collections::HashMap, sync::Arc};
8
9use crate::filter::filter;
10use crate::interleave::interleave;
11use ahash::RandomState;
12use arrow_array::builder::BooleanBufferBuilder;
13use arrow_array::types::{
14 ArrowDictionaryKeyType, ArrowPrimitiveType, BinaryType, ByteArrayType, LargeBinaryType,
15 LargeUtf8Type, Utf8Type,
16};
17use arrow_array::{
18 AnyDictionaryArray, Array, ArrayRef, ArrowNativeTypeOp, BooleanArray, DictionaryArray,
19 GenericByteArray, PrimitiveArray, downcast_dictionary_array,
20};
21use arrow_array::{cast::AsArray, downcast_primitive};
22use arrow_buffer::{ArrowNativeType, BooleanBuffer, ScalarBuffer, ToByteSlice};
23use arrow_schema::{ArrowError, DataType};
24
25pub fn garbage_collect_dictionary<K: ArrowDictionaryKeyType>(
33 dictionary: &DictionaryArray<K>,
34) -> Result<DictionaryArray<K>, ArrowError> {
35 let keys = dictionary.keys();
36 let values = dictionary.values();
37
38 let mask = dictionary.occupancy();
39
40 if mask.count_set_bits() == values.len() {
42 return Ok(dictionary.clone());
43 }
44
45 let mut key_remap = vec![K::Native::ZERO; values.len()];
47 for (new_idx, old_idx) in mask.set_indices().enumerate() {
48 key_remap[old_idx] =
49 K::Native::from_usize(new_idx).ok_or(ArrowError::DictionaryKeyOverflowError)?;
50 }
51
52 let new_keys = keys.unary(|key| {
54 key_remap
55 .get(key.as_usize())
56 .copied()
57 .unwrap_or(K::Native::ZERO)
60 });
61
62 let values = filter(dictionary.values(), &BooleanArray::new(mask, None))?;
64
65 DictionaryArray::try_new(new_keys, values)
66}
67
68pub fn garbage_collect_any_dictionary(
70 dictionary: &dyn AnyDictionaryArray,
71) -> Result<ArrayRef, ArrowError> {
72 let dictionary: &dyn Array = dictionary;
73 downcast_dictionary_array!(
74 dictionary => garbage_collect_dictionary(dictionary).map(|dict| Arc::new(dict) as ArrayRef),
75 _ => unreachable!("have a dictionary array")
76 )
77}
78
79struct Interner<'a, V> {
84 state: RandomState,
85 buckets: Vec<Option<InternerBucket<'a, V>>>,
86 shift: u32,
87}
88
89type InternerBucket<'a, V> = (Option<&'a [u8]>, V);
91
92impl<'a, V> Interner<'a, V> {
93 fn new(capacity: usize) -> Self {
98 let shift = (capacity as u64 + 128).leading_zeros();
100 let num_buckets = (u64::MAX >> shift) as usize;
101 let buckets = (0..num_buckets.saturating_add(1)).map(|_| None).collect();
102 Self {
103 state: RandomState::with_seeds(0, 0, 0, 0),
105 buckets,
106 shift,
107 }
108 }
109
110 fn intern<F: FnOnce() -> Result<V, E>, E>(
111 &mut self,
112 new: Option<&'a [u8]>,
113 f: F,
114 ) -> Result<&V, E> {
115 let hash = self.state.hash_one(new);
116 let bucket_idx = hash >> self.shift;
117 Ok(match &mut self.buckets[bucket_idx as usize] {
118 Some((current, v)) => {
119 if *current != new {
120 *v = f()?;
121 *current = new;
122 }
123 v
124 }
125 slot => &slot.insert((new, f()?)).1,
126 })
127 }
128}
129
130pub(crate) const MAX_DENSE_MAPPING_VALUES_PER_ROW: usize = 256;
132
133pub(crate) enum KeyMapping<K: ArrowDictionaryKeyType> {
134 Dense(Vec<K::Native>),
135 Sparse(HashMap<usize, K::Native, RandomState>),
136}
137
138impl<K: ArrowDictionaryKeyType> KeyMapping<K> {
139 fn new_dense(len: usize) -> Self {
140 Self::Dense(vec![K::Native::ZERO; len])
141 }
142
143 fn new_sparse(capacity: usize) -> Self {
144 Self::Sparse(HashMap::with_capacity_and_hasher(
145 capacity,
146 RandomState::with_seeds(0, 0, 0, 0),
147 ))
148 }
149
150 fn insert(&mut self, old_key: usize, new_key: K::Native) {
151 match self {
152 Self::Dense(mapping) => mapping[old_key] = new_key,
153 Self::Sparse(mapping) => {
154 mapping.insert(old_key, new_key);
155 }
156 }
157 }
158
159 #[inline]
160 pub fn get(&self, old_key: usize) -> Option<K::Native> {
161 match self {
162 Self::Dense(mapping) => mapping.get(old_key).copied(),
163 Self::Sparse(mapping) => mapping.get(&old_key).copied(),
164 }
165 }
166}
167
168pub(crate) struct MergedDictionaries<K: ArrowDictionaryKeyType> {
169 pub key_mappings: Vec<KeyMapping<K>>,
171 pub values: ArrayRef,
173}
174
175fn bytes_ptr_eq<T: ByteArrayType>(a: &dyn Array, b: &dyn Array) -> bool {
179 match (a.as_bytes_opt::<T>(), b.as_bytes_opt::<T>()) {
180 (Some(a), Some(b)) => {
181 let values_eq = a.values().ptr_eq(b.values()) && a.offsets().ptr_eq(b.offsets());
182 match (a.nulls(), b.nulls()) {
183 (Some(a), Some(b)) => values_eq && a.inner().ptr_eq(b.inner()),
184 (None, None) => values_eq,
185 _ => false,
186 }
187 }
188 _ => false,
189 }
190}
191
192pub(crate) fn child_values_ptr_eq(left: &ArrayRef, right: &ArrayRef) -> bool {
203 if Arc::ptr_eq(left, right) {
204 return true;
205 }
206
207 match left.data_type() {
208 DataType::Utf8 => bytes_ptr_eq::<Utf8Type>(left.as_ref(), right.as_ref()),
209 DataType::LargeUtf8 => bytes_ptr_eq::<LargeUtf8Type>(left.as_ref(), right.as_ref()),
210 DataType::Binary => bytes_ptr_eq::<BinaryType>(left.as_ref(), right.as_ref()),
211 DataType::LargeBinary => bytes_ptr_eq::<LargeBinaryType>(left.as_ref(), right.as_ref()),
212 _ => left.to_data().ptr_eq(&right.to_data()),
213 }
214}
215
216type PtrEq = fn(&dyn Array, &dyn Array) -> bool;
218
219pub(crate) fn should_merge_dictionary_values<K: ArrowDictionaryKeyType>(
229 dictionaries: &[&DictionaryArray<K>],
230 len: usize,
231) -> (bool, bool) {
232 use DataType::*;
233 let first_values = dictionaries[0].values().as_ref();
234 let ptr_eq: PtrEq = match first_values.data_type() {
235 Utf8 => bytes_ptr_eq::<Utf8Type>,
236 LargeUtf8 => bytes_ptr_eq::<LargeUtf8Type>,
237 Binary => bytes_ptr_eq::<BinaryType>,
238 LargeBinary => bytes_ptr_eq::<LargeBinaryType>,
239 dt => {
240 if !dt.is_primitive() {
241 return (
242 false,
243 K::Native::from_usize(dictionaries.iter().map(|d| d.values().len()).sum())
244 .is_none(),
245 );
246 }
247 |a, b| a.to_data().ptr_eq(&b.to_data())
248 }
249 };
250
251 let mut single_dictionary = true;
252 let mut total_values = first_values.len();
253 for dict in dictionaries.iter().skip(1) {
254 let values = dict.values().as_ref();
255 total_values += values.len();
256 if single_dictionary {
257 single_dictionary = ptr_eq(first_values, values)
258 }
259 }
260
261 let overflow = K::Native::from_usize(total_values).is_none();
262 let values_exceed_length = total_values >= len;
263
264 (
265 !single_dictionary && (overflow || values_exceed_length),
266 overflow,
267 )
268}
269
270pub(crate) fn merge_dictionary_values<K: ArrowDictionaryKeyType>(
280 dictionaries: &[&DictionaryArray<K>],
281 masks: Option<&[BooleanBuffer]>,
282 key_lookups: Option<&[usize]>,
283) -> Result<MergedDictionaries<K>, ArrowError> {
284 let mut num_values = 0;
285
286 let mut values_arrays = Vec::with_capacity(dictionaries.len());
287 let mut value_slices = Vec::with_capacity(dictionaries.len());
288
289 for (idx, dictionary) in dictionaries.iter().enumerate() {
290 let mask = masks.and_then(|m| m.get(idx));
291 let key_mask_owned;
292 let key_mask = match (dictionary.nulls(), mask) {
293 (Some(n), None) => Some(n.inner()),
294 (None, Some(n)) => Some(n),
295 (Some(n), Some(m)) => {
296 key_mask_owned = n.inner() & m;
297 Some(&key_mask_owned)
298 }
299 (None, None) => None,
300 };
301 let keys = dictionary.keys().values();
302 let values = dictionary.values().as_ref();
303 let lookups = key_lookups.map_or(keys.len(), |lookups| lookups[idx]);
304 let use_sparse_mapping =
305 values.len() > lookups.saturating_mul(MAX_DENSE_MAPPING_VALUES_PER_ROW);
306
307 let selected_values = if use_sparse_mapping {
308 let referenced_keys = compute_referenced_keys(keys, key_mask);
309 let len = referenced_keys.len();
310 get_selected_values(values, referenced_keys.into_iter(), len)
311 } else {
312 let values_mask = compute_values_mask(keys, key_mask, values.len());
313 let len = values_mask.count_set_bits();
314 get_selected_values(values, values_mask.set_indices(), len)
315 };
316 num_values += selected_values.len();
317 value_slices.push((selected_values, use_sparse_mapping));
318 values_arrays.push(values)
319 }
320
321 let mut interner = Interner::new(num_values);
323 let mut indices = Vec::with_capacity(num_values);
325
326 let key_mappings = dictionaries
328 .iter()
329 .enumerate()
330 .zip(value_slices)
331 .map(
332 |((dictionary_idx, dictionary), (values, use_sparse_mapping))| {
333 let mut mapping = match use_sparse_mapping {
334 true => KeyMapping::new_sparse(values.len()),
335 false => KeyMapping::new_dense(dictionary.values().len()),
336 };
337
338 for (value_idx, value) in values {
339 let new_key =
340 *interner.intern(value, || match K::Native::from_usize(indices.len()) {
341 Some(idx) => {
342 indices.push((dictionary_idx, value_idx));
343 Ok(idx)
344 }
345 None => Err(ArrowError::DictionaryKeyOverflowError),
346 })?;
347 mapping.insert(value_idx, new_key);
348 }
349 Ok(mapping)
350 },
351 )
352 .collect::<Result<Vec<_>, ArrowError>>()?;
353
354 Ok(MergedDictionaries {
355 key_mappings,
356 values: interleave(&values_arrays, &indices)?,
357 })
358}
359
360pub(crate) fn merge_dictionary_values_with_masks<K: ArrowDictionaryKeyType>(
371 values_arrays: &[&dyn Array],
372 values_masks: &[BooleanBuffer],
373) -> Result<MergedDictionaries<K>, ArrowError> {
374 assert_eq!(values_arrays.len(), values_masks.len());
375 let num_values = values_masks.iter().map(BooleanBuffer::count_set_bits).sum();
376
377 if num_values == 0 || K::Native::from_usize(num_values - 1).is_some() {
380 let zero = K::Native::from_usize(0).unwrap();
381 let mut indices = Vec::with_capacity(num_values);
382 let key_mappings = values_arrays
383 .iter()
384 .zip(values_masks)
385 .enumerate()
386 .map(|(dictionary_idx, (values, mask))| {
387 let mut mapping = vec![zero; values.len()];
388 for value_idx in mask.set_indices() {
389 mapping[value_idx] = K::Native::from_usize(indices.len()).unwrap();
390 indices.push((dictionary_idx, value_idx));
391 }
392 KeyMapping::Dense(mapping)
393 })
394 .collect();
395 return Ok(MergedDictionaries {
396 key_mappings,
397 values: interleave(values_arrays, &indices)?,
398 });
399 }
400
401 let value_slices = values_arrays
402 .iter()
403 .zip(values_masks)
404 .map(|(values, mask)| {
405 let len = mask.count_set_bits();
406 get_selected_values(*values, mask.set_indices(), len)
407 })
408 .collect::<Vec<_>>();
409 let mut interner = Interner::new(num_values);
410 let mut indices = Vec::with_capacity(num_values);
411
412 let key_mappings = values_arrays
413 .iter()
414 .enumerate()
415 .zip(value_slices)
416 .map(|((dictionary_idx, value_array), values)| {
417 let zero = K::Native::ZERO;
418 let mut mapping = vec![zero; value_array.len()];
419
420 for (value_idx, value) in values {
421 mapping[value_idx] =
422 *interner.intern(value, || match K::Native::from_usize(indices.len()) {
423 Some(idx) => {
424 indices.push((dictionary_idx, value_idx));
425 Ok(idx)
426 }
427 None => Err(ArrowError::DictionaryKeyOverflowError),
428 })?;
429 }
430 Ok(KeyMapping::Dense(mapping))
431 })
432 .collect::<Result<Vec<_>, ArrowError>>()?;
433
434 Ok(MergedDictionaries {
435 key_mappings,
436 values: interleave(values_arrays, &indices)?,
437 })
438}
439
440fn compute_referenced_keys<K: ArrowNativeType>(
446 keys: &ScalarBuffer<K>,
447 mask: Option<&BooleanBuffer>,
448) -> Vec<usize> {
449 let mut indices = match mask {
450 Some(mask) => mask
451 .set_indices()
452 .map(|idx| keys[idx].as_usize())
453 .collect::<Vec<_>>(),
454 None => keys.iter().map(|key| key.as_usize()).collect(),
455 };
456 indices.sort_unstable();
457 indices.dedup();
458 indices
459}
460
461fn compute_values_mask<K: ArrowNativeType>(
464 keys: &ScalarBuffer<K>,
465 mask: Option<&BooleanBuffer>,
466 max_key: usize,
467) -> BooleanBuffer {
468 let mut builder = BooleanBufferBuilder::new(max_key);
469 builder.advance(max_key);
470
471 match mask {
472 Some(n) => n
473 .set_indices()
474 .for_each(|idx| builder.set_bit(keys[idx].as_usize(), true)),
475 None => keys
476 .iter()
477 .for_each(|k| builder.set_bit(k.as_usize(), true)),
478 }
479 builder.finish()
480}
481
482fn selected_primitives_to_bytes<T: ArrowPrimitiveType, I: Iterator<Item = usize>>(
483 array: &PrimitiveArray<T>,
484 indices: I,
485 len: usize,
486) -> Vec<(usize, Option<&[u8]>)>
487where
488 T::Native: ToByteSlice,
489{
490 let mut out = Vec::with_capacity(len);
491 let values = array.values();
492 for idx in indices {
493 out.push((
494 idx,
495 array.is_valid(idx).then_some(values[idx].to_byte_slice()),
496 ))
497 }
498 out
499}
500
501macro_rules! selected_primitive_to_bytes_helper {
502 ($t:ty, $array:expr, $indices:expr, $len:expr) => {
503 selected_primitives_to_bytes::<$t, _>($array.as_primitive(), $indices, $len)
504 };
505}
506
507fn get_selected_values<I: Iterator<Item = usize>>(
508 array: &dyn Array,
509 indices: I,
510 len: usize,
511) -> Vec<(usize, Option<&[u8]>)> {
512 downcast_primitive! {
513 array.data_type() => (selected_primitive_to_bytes_helper, array, indices, len),
514 DataType::Utf8 => selected_bytes(array.as_string::<i32>(), indices, len),
515 DataType::LargeUtf8 => selected_bytes(array.as_string::<i64>(), indices, len),
516 DataType::Binary => selected_bytes(array.as_binary::<i32>(), indices, len),
517 DataType::LargeBinary => selected_bytes(array.as_binary::<i64>(), indices, len),
518 _ => unimplemented!("Dictionary merging for type {} is not implemented", array.data_type()),
519 }
520}
521
522fn selected_bytes<T: ByteArrayType, I: Iterator<Item = usize>>(
523 array: &GenericByteArray<T>,
524 indices: I,
525 len: usize,
526) -> Vec<(usize, Option<&[u8]>)> {
527 let mut out = Vec::with_capacity(len);
528 for idx in indices {
529 out.push((
530 idx,
531 array.is_valid(idx).then_some(array.value(idx).as_ref()),
532 ))
533 }
534 out
535}
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540
541 use arrow_array::cast::as_string_array;
542 use arrow_array::types::{Int8Type, Int32Type, UInt8Type};
543 use arrow_array::{
544 ArrayRef, DictionaryArray, Int8Array, Int32Array, ListArray, NullArray, RunArray,
545 StringArray, StringViewArray, UInt8Array,
546 };
547 use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer, OffsetBuffer};
548 use arrow_schema::Field;
549 use std::sync::Arc;
550
551 fn assert_mapping(mapping: &KeyMapping<Int32Type>, expected: &[i32]) {
552 let KeyMapping::Dense(actual) = mapping else {
553 panic!("expected a dense mapping");
554 };
555 assert_eq!(actual, expected);
556 }
557
558 #[test]
559 fn test_child_values_ptr_eq_accepts_reusable_value_mapping() {
560 let dictionary = DictionaryArray::<Int8Type>::new(
561 Int8Array::from(vec![0, 1]),
562 Arc::new(StringArray::from(vec!["a", "b"])),
563 );
564 let same_values = Arc::clone(dictionary.values());
565
566 assert!(Arc::ptr_eq(dictionary.values(), &same_values));
567 assert!(child_values_ptr_eq(dictionary.values(), &same_values));
568
569 let shared_values = StringArray::from(vec!["a", "b"]);
570 let first_dictionary = DictionaryArray::<Int8Type>::new(
571 Int8Array::from(vec![0, 1]),
572 Arc::new(shared_values.clone()),
573 );
574 let cloned_dictionary =
575 DictionaryArray::<Int8Type>::new(Int8Array::from(vec![0, 1]), Arc::new(shared_values));
576
577 assert!(!Arc::ptr_eq(
578 first_dictionary.values(),
579 cloned_dictionary.values()
580 ));
581 assert!(child_values_ptr_eq(
582 first_dictionary.values(),
583 cloned_dictionary.values()
584 ));
585
586 let run_values = StringArray::from(vec!["a", "b"]);
588 let first_runs =
589 RunArray::<Int32Type>::try_new(&Int32Array::from(vec![1, 3]), &run_values).unwrap();
590 let second_runs =
591 RunArray::<Int32Type>::try_new(&Int32Array::from(vec![2, 3]), &run_values).unwrap();
592
593 assert!(!Arc::ptr_eq(first_runs.values(), second_runs.values()));
594 assert!(child_values_ptr_eq(
595 first_runs.values(),
596 second_runs.values()
597 ));
598
599 let empty_left: ArrayRef = Arc::new(Int32Array::from(Vec::<i32>::new()));
601 let empty_right: ArrayRef = Arc::new(Int32Array::from(Vec::<i32>::new()));
602 assert!(child_values_ptr_eq(&empty_left, &empty_right));
603
604 let null_left: ArrayRef = Arc::new(NullArray::new(3));
605 let null_right: ArrayRef = Arc::new(NullArray::new(3));
606 assert!(child_values_ptr_eq(&null_left, &null_right));
607 }
608
609 #[test]
610 fn test_child_values_ptr_eq_rejects_different_storage_or_layout() {
611 let independent_left: ArrayRef = Arc::new(StringArray::from(vec!["a", "b"]));
612 let independent_right: ArrayRef = Arc::new(StringArray::from(vec!["a", "b"]));
613
614 assert!(!child_values_ptr_eq(&independent_left, &independent_right));
615
616 let storage = Int32Array::from(vec![1, 2, 3]);
617 let prefix: ArrayRef = Arc::new(storage.slice(0, 2));
618 let shifted: ArrayRef = Arc::new(storage.slice(1, 2));
619 let shorter: ArrayRef = Arc::new(storage.slice(0, 1));
620
621 assert!(!child_values_ptr_eq(&prefix, &shifted));
622 assert!(!child_values_ptr_eq(&prefix, &shorter));
623 }
624
625 #[test]
626 fn test_child_values_ptr_eq_rejects_different_nested_or_view_storage() {
627 let list_field = Arc::new(Field::new_list_field(DataType::Int32, false));
629 let shared_offsets = OffsetBuffer::new(vec![0_i32, 2].into());
630 let first_list: ArrayRef = Arc::new(ListArray::new(
631 Arc::clone(&list_field),
632 shared_offsets.clone(),
633 Arc::new(Int32Array::from(vec![1, 2])),
634 None,
635 ));
636 let second_list: ArrayRef = Arc::new(ListArray::new(
637 list_field,
638 shared_offsets,
639 Arc::new(Int32Array::from(vec![1, 3])),
640 None,
641 ));
642 assert!(!child_values_ptr_eq(&first_list, &second_list));
643
644 let first_payload: &[u8] = b"same payload one";
645 let second_payload: &[u8] = b"same payload two";
646 let view = arrow_data::ByteView::new(first_payload.len() as u32, &first_payload[..4]);
647 let shared_views = ScalarBuffer::from(vec![view.into()]);
648 let first_view: ArrayRef = Arc::new(StringViewArray::new(
649 shared_views.clone(),
650 vec![Buffer::from_slice_ref(first_payload)],
651 None,
652 ));
653 let second_view: ArrayRef = Arc::new(StringViewArray::new(
654 shared_views,
655 vec![Buffer::from_slice_ref(second_payload)],
656 None,
657 ));
658 assert!(!child_values_ptr_eq(&first_view, &second_view));
659 }
660
661 #[test]
662 fn test_garbage_collect_i32_dictionary() {
663 let values = StringArray::from_iter_values(["a", "b", "c", "d"]);
664 let keys = Int32Array::from_iter_values([0, 1, 1, 3, 0, 0, 1]);
665 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
666
667 let gc = garbage_collect_dictionary(&dict).unwrap();
669
670 let expected_values = StringArray::from_iter_values(["a", "b", "d"]);
671 let expected_keys = Int32Array::from_iter_values([0, 1, 1, 2, 0, 0, 1]);
672 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
673
674 assert_eq!(gc, expected);
675 }
676
677 #[test]
678 fn test_garbage_collect_any_dictionary() {
679 let values = StringArray::from_iter_values(["a", "b", "c", "d"]);
680 let keys = Int32Array::from_iter_values([0, 1, 1, 3, 0, 0, 1]);
681 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
682
683 let gc = garbage_collect_any_dictionary(&dict).unwrap();
684
685 let expected_values = StringArray::from_iter_values(["a", "b", "d"]);
686 let expected_keys = Int32Array::from_iter_values([0, 1, 1, 2, 0, 0, 1]);
687 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
688
689 assert_eq!(gc.as_ref(), &expected);
690 }
691
692 #[test]
693 fn test_garbage_collect_with_nulls() {
694 let values = StringArray::from_iter_values(["a", "b", "c"]);
695 let keys = Int8Array::from(vec![Some(2), None, Some(0)]);
696 let dict = DictionaryArray::<Int8Type>::new(keys, Arc::new(values));
697
698 let gc = garbage_collect_dictionary(&dict).unwrap();
699
700 let expected_values = StringArray::from_iter_values(["a", "c"]);
701 let expected_keys = Int8Array::from(vec![Some(1), None, Some(0)]);
702 let expected = DictionaryArray::<Int8Type>::new(expected_keys, Arc::new(expected_values));
703
704 assert_eq!(gc, expected);
705 }
706
707 #[test]
708 fn test_garbage_collect_empty_dictionary() {
709 let values = StringArray::from_iter_values::<&str, _>([]);
710 let keys = Int32Array::from_iter_values([]);
711 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
712
713 let gc = garbage_collect_dictionary(&dict).unwrap();
714
715 assert_eq!(gc, dict);
716 }
717
718 #[test]
719 fn test_garbage_collect_dictionary_all_unreferenced() {
720 let values = StringArray::from_iter_values(["a", "b", "c"]);
721 let keys = Int32Array::from(vec![None, None, None]);
722 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
723
724 let gc = garbage_collect_dictionary(&dict).unwrap();
725
726 let expected_values = StringArray::from_iter_values::<&str, _>([]);
728 let expected_keys = Int32Array::from(vec![None, None, None]);
729 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
730
731 assert_eq!(gc, expected);
732 }
733
734 #[test]
735 fn test_merge_strings() {
736 let a = DictionaryArray::<Int32Type>::from_iter(["a", "b", "a", "b", "d", "c", "e"]);
737 let b = DictionaryArray::<Int32Type>::from_iter(["c", "f", "c", "d", "a", "d"]);
738 let merged = merge_dictionary_values(&[&a, &b], None, None).unwrap();
739
740 let values = as_string_array(merged.values.as_ref());
741 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
742 assert_eq!(&actual, &["a", "b", "d", "c", "e", "f"]);
743
744 assert_eq!(merged.key_mappings.len(), 2);
745 assert_mapping(&merged.key_mappings[0], &[0, 1, 2, 3, 4]);
746 assert_mapping(&merged.key_mappings[1], &[3, 5, 2, 0]);
747
748 let a_slice = a.slice(1, 4);
749 let merged = merge_dictionary_values(&[&a_slice, &b], None, None).unwrap();
750
751 let values = as_string_array(merged.values.as_ref());
752 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
753 assert_eq!(&actual, &["a", "b", "d", "c", "f"]);
754
755 assert_eq!(merged.key_mappings.len(), 2);
756 assert_mapping(&merged.key_mappings[0], &[0, 1, 2, 0, 0]);
757 assert_mapping(&merged.key_mappings[1], &[3, 4, 2, 0]);
758
759 let a_mask = BooleanBuffer::from_iter([false, true, false, true, true, false, false]);
761 let b_mask = BooleanBuffer::new_set(b.len());
762 let merged = merge_dictionary_values(&[&a, &b], Some(&[a_mask, b_mask]), None).unwrap();
763
764 let values = as_string_array(merged.values.as_ref());
765 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
766 assert_eq!(&actual, &["b", "d", "c", "f", "a"]);
767
768 assert_eq!(merged.key_mappings.len(), 2);
769 assert_mapping(&merged.key_mappings[0], &[0, 0, 1, 0, 0]);
770 assert_mapping(&merged.key_mappings[1], &[2, 3, 1, 4]);
771 }
772
773 #[test]
774 fn test_merge_dictionary_values_with_masks() {
775 let first = StringArray::from_iter_values(["a", "unused-a", "shared"]);
776 let second = StringArray::from_iter_values(["shared", "b", "unused-b"]);
777 let values = [&first as &dyn Array, &second as &dyn Array];
778 let masks = [
779 BooleanBuffer::from_iter([true, false, true]),
780 BooleanBuffer::from_iter([true, true, false]),
781 ];
782
783 let merged = merge_dictionary_values_with_masks::<Int32Type>(&values, &masks).unwrap();
784
785 let expected = StringArray::from_iter_values(["a", "shared", "shared", "b"]);
786 assert_eq!(merged.values.as_ref(), &expected);
787 assert_mapping(&merged.key_mappings[0], &[0, 0, 1]);
788 assert_mapping(&merged.key_mappings[1], &[2, 3, 0]);
789 }
790
791 #[test]
792 fn test_merge_nulls() {
793 let buffer = Buffer::from(b"helloworldbingohelloworld");
794 let offsets = OffsetBuffer::from_lengths([5, 5, 5, 5, 5]);
795 let nulls = NullBuffer::from(vec![true, false, true, true, true]);
796 let values = StringArray::new(offsets, buffer, Some(nulls));
797
798 let key_values = vec![1, 2, 3, 1, 8, 2, 3];
799 let key_nulls = NullBuffer::from(vec![true, true, false, true, false, true, true]);
800 let keys = Int32Array::new(key_values.into(), Some(key_nulls));
801 let a = DictionaryArray::new(keys, Arc::new(values));
802 let b = DictionaryArray::new(Int32Array::new_null(10), Arc::new(StringArray::new_null(0)));
805
806 let merged = merge_dictionary_values(&[&a, &b], None, None).unwrap();
807 let expected = StringArray::from(vec![None, Some("bingo"), Some("hello")]);
808 assert_eq!(merged.values.as_ref(), &expected);
809 assert_eq!(merged.key_mappings.len(), 2);
810 assert_mapping(&merged.key_mappings[0], &[0, 0, 1, 2, 0]);
811 assert_mapping(&merged.key_mappings[1], &[]);
812 }
813
814 #[test]
815 fn test_merge_keys_smaller() {
816 let values = StringArray::from_iter_values(["a", "b"]);
817 let keys = Int32Array::from_iter_values([1]);
818 let a = DictionaryArray::new(keys, Arc::new(values));
819
820 let merged = merge_dictionary_values(&[&a], None, None).unwrap();
821 let expected = StringArray::from(vec!["b"]);
822 assert_eq!(merged.values.as_ref(), &expected);
823 }
824
825 #[test]
826 fn test_compute_referenced_keys_preserves_dense_order() {
827 let keys = Int32Array::from_iter_values([999, 1, 500, 1, 999]);
828
829 let actual = compute_referenced_keys(keys.values(), None);
830
831 assert_eq!(actual, vec![1, 500, 999]);
832 }
833
834 #[test]
835 fn test_sparse_gate_counts_key_lookups() {
836 let values: ArrayRef = Arc::new(StringArray::from_iter_values(
837 (0..8 * MAX_DENSE_MAPPING_VALUES_PER_ROW).map(|idx| idx.to_string()),
838 ));
839 let is_sparse = |dictionary: &DictionaryArray<Int32Type>,
840 masks: Option<&[BooleanBuffer]>,
841 lookups: Option<&[usize]>| {
842 let merged = merge_dictionary_values(&[dictionary], masks, lookups).unwrap();
843 matches!(merged.key_mappings[0], KeyMapping::Sparse(_))
844 };
845
846 let keys = Int32Array::from_iter((0..10).map(|idx| (idx == 0).then_some(999)));
848 let mostly_null = DictionaryArray::new(keys, Arc::clone(&values));
849 assert!(!is_sparse(&mostly_null, None, None));
850
851 let keys = Int32Array::from_iter_values([999; 7]);
853 let short = DictionaryArray::new(keys, Arc::clone(&values));
854 assert!(is_sparse(&short, None, None));
855
856 let mask = BooleanBuffer::collect_bool(7, |idx| idx == 0);
858 assert!(!is_sparse(
859 &short,
860 Some(std::slice::from_ref(&mask)),
861 Some(&[10]),
862 ));
863 assert!(is_sparse(&short, Some(&[mask]), Some(&[7])));
864 }
865
866 #[test]
867 fn test_merge_oversized_dictionary_slice() {
868 let values_len = 4 * MAX_DENSE_MAPPING_VALUES_PER_ROW + 1;
869 let values = StringArray::from_iter_values((0..values_len).map(|idx| idx.to_string()));
870 let last = values_len as i32 - 1;
871 let keys = Int32Array::from(vec![Some(last), None, Some(1), Some(last)]);
872 let dictionary = DictionaryArray::new(keys, Arc::new(values));
873
874 let merged = merge_dictionary_values(&[&dictionary], None, None).unwrap();
875 let values = as_string_array(merged.values.as_ref());
876 let actual = values.iter().collect::<Vec<_>>();
877 let last_value = last.to_string();
878
879 assert_eq!(actual, vec![Some("1"), Some(last_value.as_str())]);
880 assert!(matches!(merged.key_mappings[0], KeyMapping::Sparse(_)));
881 assert_eq!(merged.key_mappings[0].get(1), Some(0));
882 assert_eq!(merged.key_mappings[0].get(last as usize), Some(1));
883 assert_eq!(merged.key_mappings[0].get(500), None);
884 }
885
886 #[test]
887 fn test_merge_sparse_dictionary_overflow() {
888 const UNIQUE_VALUES: usize = u8::MAX as usize + 2;
889
890 let dictionaries = (0..UNIQUE_VALUES)
892 .map(|dictionary_idx| {
893 let values = StringArray::from_iter_values(
894 (0..=MAX_DENSE_MAPPING_VALUES_PER_ROW)
895 .map(|value_idx| format!("{dictionary_idx}-{value_idx}")),
896 );
897 let keys = UInt8Array::from_iter_values([0]);
898 DictionaryArray::<UInt8Type>::new(keys, Arc::new(values))
899 })
900 .collect::<Vec<_>>();
901 let dictionaries = dictionaries.iter().collect::<Vec<_>>();
902
903 let result = merge_dictionary_values(&dictionaries, None, None);
904
905 assert!(matches!(
906 result,
907 Err(ArrowError::DictionaryKeyOverflowError)
908 ));
909 }
910}