1use std::sync::Arc;
21
22use crate::filter::filter;
23use crate::interleave::interleave;
24use ahash::RandomState;
25use arrow_array::builder::BooleanBufferBuilder;
26use arrow_array::types::{
27 ArrowDictionaryKeyType, ArrowPrimitiveType, BinaryType, ByteArrayType, LargeBinaryType,
28 LargeUtf8Type, Utf8Type,
29};
30use arrow_array::{
31 AnyDictionaryArray, Array, ArrayRef, ArrowNativeTypeOp, BooleanArray, DictionaryArray,
32 GenericByteArray, PrimitiveArray, downcast_dictionary_array,
33};
34use arrow_array::{cast::AsArray, downcast_primitive};
35use arrow_buffer::{ArrowNativeType, BooleanBuffer, ScalarBuffer, ToByteSlice};
36use arrow_schema::{ArrowError, DataType};
37
38pub fn garbage_collect_dictionary<K: ArrowDictionaryKeyType>(
46 dictionary: &DictionaryArray<K>,
47) -> Result<DictionaryArray<K>, ArrowError> {
48 let keys = dictionary.keys();
49 let values = dictionary.values();
50
51 let mask = dictionary.occupancy();
52
53 if mask.count_set_bits() == values.len() {
55 return Ok(dictionary.clone());
56 }
57
58 let mut key_remap = vec![K::Native::ZERO; values.len()];
60 for (new_idx, old_idx) in mask.set_indices().enumerate() {
61 key_remap[old_idx] = K::Native::from_usize(new_idx)
62 .expect("new index should fit in K::Native, as old index was in range");
63 }
64
65 let new_keys = keys.unary(|key| {
67 key_remap
68 .get(key.as_usize())
69 .copied()
70 .unwrap_or(K::Native::ZERO)
73 });
74
75 let values = filter(dictionary.values(), &BooleanArray::new(mask, None))?;
77
78 DictionaryArray::try_new(new_keys, values)
79}
80
81pub fn garbage_collect_any_dictionary(
83 dictionary: &dyn AnyDictionaryArray,
84) -> Result<ArrayRef, ArrowError> {
85 let dictionary: &dyn Array = dictionary;
86 downcast_dictionary_array!(
87 dictionary => garbage_collect_dictionary(dictionary).map(|dict| Arc::new(dict) as ArrayRef),
88 _ => unreachable!("have a dictionary array")
89 )
90}
91
92struct Interner<'a, V> {
97 state: RandomState,
98 buckets: Vec<Option<InternerBucket<'a, V>>>,
99 shift: u32,
100}
101
102type InternerBucket<'a, V> = (Option<&'a [u8]>, V);
104
105impl<'a, V> Interner<'a, V> {
106 fn new(capacity: usize) -> Self {
111 let shift = (capacity as u64 + 128).leading_zeros();
113 let num_buckets = (u64::MAX >> shift) as usize;
114 let buckets = (0..num_buckets.saturating_add(1)).map(|_| None).collect();
115 Self {
116 state: RandomState::with_seeds(0, 0, 0, 0),
118 buckets,
119 shift,
120 }
121 }
122
123 fn intern<F: FnOnce() -> Result<V, E>, E>(
124 &mut self,
125 new: Option<&'a [u8]>,
126 f: F,
127 ) -> Result<&V, E> {
128 let hash = self.state.hash_one(new);
129 let bucket_idx = hash >> self.shift;
130 Ok(match &mut self.buckets[bucket_idx as usize] {
131 Some((current, v)) => {
132 if *current != new {
133 *v = f()?;
134 *current = new;
135 }
136 v
137 }
138 slot => &slot.insert((new, f()?)).1,
139 })
140 }
141}
142
143pub(crate) struct MergedDictionaries<K: ArrowDictionaryKeyType> {
144 pub key_mappings: Vec<Vec<K::Native>>,
146 pub values: ArrayRef,
148}
149
150fn bytes_ptr_eq<T: ByteArrayType>(a: &dyn Array, b: &dyn Array) -> bool {
154 match (a.as_bytes_opt::<T>(), b.as_bytes_opt::<T>()) {
155 (Some(a), Some(b)) => {
156 let values_eq = a.values().ptr_eq(b.values()) && a.offsets().ptr_eq(b.offsets());
157 match (a.nulls(), b.nulls()) {
158 (Some(a), Some(b)) => values_eq && a.inner().ptr_eq(b.inner()),
159 (None, None) => values_eq,
160 _ => false,
161 }
162 }
163 _ => false,
164 }
165}
166
167type PtrEq = fn(&dyn Array, &dyn Array) -> bool;
169
170pub(crate) fn should_merge_dictionary_values<K: ArrowDictionaryKeyType>(
180 dictionaries: &[&DictionaryArray<K>],
181 len: usize,
182) -> (bool, bool) {
183 use DataType::*;
184 let first_values = dictionaries[0].values().as_ref();
185 let ptr_eq: PtrEq = match first_values.data_type() {
186 Utf8 => bytes_ptr_eq::<Utf8Type>,
187 LargeUtf8 => bytes_ptr_eq::<LargeUtf8Type>,
188 Binary => bytes_ptr_eq::<BinaryType>,
189 LargeBinary => bytes_ptr_eq::<LargeBinaryType>,
190 dt => {
191 if !dt.is_primitive() {
192 return (
193 false,
194 K::Native::from_usize(dictionaries.iter().map(|d| d.values().len()).sum())
195 .is_none(),
196 );
197 }
198 |a, b| a.to_data().ptr_eq(&b.to_data())
199 }
200 };
201
202 let mut single_dictionary = true;
203 let mut total_values = first_values.len();
204 for dict in dictionaries.iter().skip(1) {
205 let values = dict.values().as_ref();
206 total_values += values.len();
207 if single_dictionary {
208 single_dictionary = ptr_eq(first_values, values)
209 }
210 }
211
212 let overflow = K::Native::from_usize(total_values).is_none();
213 let values_exceed_length = total_values >= len;
214
215 (
216 !single_dictionary && (overflow || values_exceed_length),
217 overflow,
218 )
219}
220
221pub(crate) fn merge_dictionary_values<K: ArrowDictionaryKeyType>(
230 dictionaries: &[&DictionaryArray<K>],
231 masks: Option<&[BooleanBuffer]>,
232) -> Result<MergedDictionaries<K>, ArrowError> {
233 let mut num_values = 0;
234
235 let mut values_arrays = Vec::with_capacity(dictionaries.len());
236 let mut value_slices = Vec::with_capacity(dictionaries.len());
237
238 for (idx, dictionary) in dictionaries.iter().enumerate() {
239 let mask = masks.and_then(|m| m.get(idx));
240 let key_mask_owned;
241 let key_mask = match (dictionary.nulls(), mask) {
242 (Some(n), None) => Some(n.inner()),
243 (None, Some(n)) => Some(n),
244 (Some(n), Some(m)) => {
245 key_mask_owned = n.inner() & m;
246 Some(&key_mask_owned)
247 }
248 (None, None) => None,
249 };
250 let keys = dictionary.keys().values();
251 let values = dictionary.values().as_ref();
252 let values_mask = compute_values_mask(keys, key_mask, values.len());
253
254 let masked_values = get_masked_values(values, &values_mask);
255 num_values += masked_values.len();
256 value_slices.push(masked_values);
257 values_arrays.push(values)
258 }
259
260 let mut interner = Interner::new(num_values);
262 let mut indices = Vec::with_capacity(num_values);
264
265 let key_mappings = dictionaries
267 .iter()
268 .enumerate()
269 .zip(value_slices)
270 .map(|((dictionary_idx, dictionary), values)| {
271 let zero = K::Native::from_usize(0).unwrap();
272 let mut mapping = vec![zero; dictionary.values().len()];
273
274 for (value_idx, value) in values {
275 mapping[value_idx] =
276 *interner.intern(value, || match K::Native::from_usize(indices.len()) {
277 Some(idx) => {
278 indices.push((dictionary_idx, value_idx));
279 Ok(idx)
280 }
281 None => Err(ArrowError::DictionaryKeyOverflowError),
282 })?;
283 }
284 Ok(mapping)
285 })
286 .collect::<Result<Vec<_>, ArrowError>>()?;
287
288 Ok(MergedDictionaries {
289 key_mappings,
290 values: interleave(&values_arrays, &indices)?,
291 })
292}
293
294fn compute_values_mask<K: ArrowNativeType>(
297 keys: &ScalarBuffer<K>,
298 mask: Option<&BooleanBuffer>,
299 max_key: usize,
300) -> BooleanBuffer {
301 let mut builder = BooleanBufferBuilder::new(max_key);
302 builder.advance(max_key);
303
304 match mask {
305 Some(n) => n
306 .set_indices()
307 .for_each(|idx| builder.set_bit(keys[idx].as_usize(), true)),
308 None => keys
309 .iter()
310 .for_each(|k| builder.set_bit(k.as_usize(), true)),
311 }
312 builder.finish()
313}
314
315fn masked_primitives_to_bytes<'a, T: ArrowPrimitiveType>(
317 array: &'a PrimitiveArray<T>,
318 mask: &BooleanBuffer,
319) -> Vec<(usize, Option<&'a [u8]>)>
320where
321 T::Native: ToByteSlice,
322{
323 let mut out = Vec::with_capacity(mask.count_set_bits());
324 let values = array.values();
325 for idx in mask.set_indices() {
326 out.push((
327 idx,
328 array.is_valid(idx).then_some(values[idx].to_byte_slice()),
329 ))
330 }
331 out
332}
333
334macro_rules! masked_primitive_to_bytes_helper {
335 ($t:ty, $array:expr, $mask:expr) => {
336 masked_primitives_to_bytes::<$t>($array.as_primitive(), $mask)
337 };
338}
339
340fn get_masked_values<'a>(
342 array: &'a dyn Array,
343 mask: &BooleanBuffer,
344) -> Vec<(usize, Option<&'a [u8]>)> {
345 downcast_primitive! {
346 array.data_type() => (masked_primitive_to_bytes_helper, array, mask),
347 DataType::Utf8 => masked_bytes(array.as_string::<i32>(), mask),
348 DataType::LargeUtf8 => masked_bytes(array.as_string::<i64>(), mask),
349 DataType::Binary => masked_bytes(array.as_binary::<i32>(), mask),
350 DataType::LargeBinary => masked_bytes(array.as_binary::<i64>(), mask),
351 _ => unimplemented!("Dictionary merging for type {} is not implemented", array.data_type()),
352 }
353}
354
355fn masked_bytes<'a, T: ByteArrayType>(
359 array: &'a GenericByteArray<T>,
360 mask: &BooleanBuffer,
361) -> Vec<(usize, Option<&'a [u8]>)> {
362 let mut out = Vec::with_capacity(mask.count_set_bits());
363 for idx in mask.set_indices() {
364 out.push((
365 idx,
366 array.is_valid(idx).then_some(array.value(idx).as_ref()),
367 ))
368 }
369 out
370}
371
372#[cfg(test)]
373mod tests {
374 use super::*;
375
376 use arrow_array::cast::as_string_array;
377 use arrow_array::types::Int8Type;
378 use arrow_array::types::Int32Type;
379 use arrow_array::{DictionaryArray, Int8Array, Int32Array, StringArray};
380 use arrow_buffer::{BooleanBuffer, Buffer, NullBuffer, OffsetBuffer};
381 use std::sync::Arc;
382
383 #[test]
384 fn test_garbage_collect_i32_dictionary() {
385 let values = StringArray::from_iter_values(["a", "b", "c", "d"]);
386 let keys = Int32Array::from_iter_values([0, 1, 1, 3, 0, 0, 1]);
387 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
388
389 let gc = garbage_collect_dictionary(&dict).unwrap();
391
392 let expected_values = StringArray::from_iter_values(["a", "b", "d"]);
393 let expected_keys = Int32Array::from_iter_values([0, 1, 1, 2, 0, 0, 1]);
394 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
395
396 assert_eq!(gc, expected);
397 }
398
399 #[test]
400 fn test_garbage_collect_any_dictionary() {
401 let values = StringArray::from_iter_values(["a", "b", "c", "d"]);
402 let keys = Int32Array::from_iter_values([0, 1, 1, 3, 0, 0, 1]);
403 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
404
405 let gc = garbage_collect_any_dictionary(&dict).unwrap();
406
407 let expected_values = StringArray::from_iter_values(["a", "b", "d"]);
408 let expected_keys = Int32Array::from_iter_values([0, 1, 1, 2, 0, 0, 1]);
409 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
410
411 assert_eq!(gc.as_ref(), &expected);
412 }
413
414 #[test]
415 fn test_garbage_collect_with_nulls() {
416 let values = StringArray::from_iter_values(["a", "b", "c"]);
417 let keys = Int8Array::from(vec![Some(2), None, Some(0)]);
418 let dict = DictionaryArray::<Int8Type>::new(keys, Arc::new(values));
419
420 let gc = garbage_collect_dictionary(&dict).unwrap();
421
422 let expected_values = StringArray::from_iter_values(["a", "c"]);
423 let expected_keys = Int8Array::from(vec![Some(1), None, Some(0)]);
424 let expected = DictionaryArray::<Int8Type>::new(expected_keys, Arc::new(expected_values));
425
426 assert_eq!(gc, expected);
427 }
428
429 #[test]
430 fn test_garbage_collect_empty_dictionary() {
431 let values = StringArray::from_iter_values::<&str, _>([]);
432 let keys = Int32Array::from_iter_values([]);
433 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
434
435 let gc = garbage_collect_dictionary(&dict).unwrap();
436
437 assert_eq!(gc, dict);
438 }
439
440 #[test]
441 fn test_garbage_collect_dictionary_all_unreferenced() {
442 let values = StringArray::from_iter_values(["a", "b", "c"]);
443 let keys = Int32Array::from(vec![None, None, None]);
444 let dict = DictionaryArray::<Int32Type>::new(keys, Arc::new(values));
445
446 let gc = garbage_collect_dictionary(&dict).unwrap();
447
448 let expected_values = StringArray::from_iter_values::<&str, _>([]);
450 let expected_keys = Int32Array::from(vec![None, None, None]);
451 let expected = DictionaryArray::<Int32Type>::new(expected_keys, Arc::new(expected_values));
452
453 assert_eq!(gc, expected);
454 }
455
456 #[test]
457 fn test_merge_strings() {
458 let a = DictionaryArray::<Int32Type>::from_iter(["a", "b", "a", "b", "d", "c", "e"]);
459 let b = DictionaryArray::<Int32Type>::from_iter(["c", "f", "c", "d", "a", "d"]);
460 let merged = merge_dictionary_values(&[&a, &b], None).unwrap();
461
462 let values = as_string_array(merged.values.as_ref());
463 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
464 assert_eq!(&actual, &["a", "b", "d", "c", "e", "f"]);
465
466 assert_eq!(merged.key_mappings.len(), 2);
467 assert_eq!(&merged.key_mappings[0], &[0, 1, 2, 3, 4]);
468 assert_eq!(&merged.key_mappings[1], &[3, 5, 2, 0]);
469
470 let a_slice = a.slice(1, 4);
471 let merged = merge_dictionary_values(&[&a_slice, &b], None).unwrap();
472
473 let values = as_string_array(merged.values.as_ref());
474 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
475 assert_eq!(&actual, &["a", "b", "d", "c", "f"]);
476
477 assert_eq!(merged.key_mappings.len(), 2);
478 assert_eq!(&merged.key_mappings[0], &[0, 1, 2, 0, 0]);
479 assert_eq!(&merged.key_mappings[1], &[3, 4, 2, 0]);
480
481 let a_mask = BooleanBuffer::from_iter([false, true, false, true, true, false, false]);
483 let b_mask = BooleanBuffer::new_set(b.len());
484 let merged = merge_dictionary_values(&[&a, &b], Some(&[a_mask, b_mask])).unwrap();
485
486 let values = as_string_array(merged.values.as_ref());
487 let actual: Vec<_> = values.iter().map(Option::unwrap).collect();
488 assert_eq!(&actual, &["b", "d", "c", "f", "a"]);
489
490 assert_eq!(merged.key_mappings.len(), 2);
491 assert_eq!(&merged.key_mappings[0], &[0, 0, 1, 0, 0]);
492 assert_eq!(&merged.key_mappings[1], &[2, 3, 1, 4]);
493 }
494
495 #[test]
496 fn test_merge_nulls() {
497 let buffer = Buffer::from(b"helloworldbingohelloworld");
498 let offsets = OffsetBuffer::from_lengths([5, 5, 5, 5, 5]);
499 let nulls = NullBuffer::from(vec![true, false, true, true, true]);
500 let values = StringArray::new(offsets, buffer, Some(nulls));
501
502 let key_values = vec![1, 2, 3, 1, 8, 2, 3];
503 let key_nulls = NullBuffer::from(vec![true, true, false, true, false, true, true]);
504 let keys = Int32Array::new(key_values.into(), Some(key_nulls));
505 let a = DictionaryArray::new(keys, Arc::new(values));
506 let b = DictionaryArray::new(Int32Array::new_null(10), Arc::new(StringArray::new_null(0)));
509
510 let merged = merge_dictionary_values(&[&a, &b], None).unwrap();
511 let expected = StringArray::from(vec![None, Some("bingo"), Some("hello")]);
512 assert_eq!(merged.values.as_ref(), &expected);
513 assert_eq!(merged.key_mappings.len(), 2);
514 assert_eq!(&merged.key_mappings[0], &[0, 0, 1, 2, 0]);
515 assert_eq!(&merged.key_mappings[1], &[] as &[i32; 0]);
516 }
517
518 #[test]
519 fn test_merge_keys_smaller() {
520 let values = StringArray::from_iter_values(["a", "b"]);
521 let keys = Int32Array::from_iter_values([1]);
522 let a = DictionaryArray::new(keys, Arc::new(values));
523
524 let merged = merge_dictionary_values(&[&a], None).unwrap();
525 let expected = StringArray::from(vec!["b"]);
526 assert_eq!(merged.values.as_ref(), &expected);
527 }
528}