1use crate::cast::*;
19
20pub(crate) fn dictionary_cast<K: ArrowDictionaryKeyType>(
25 array: &dyn Array,
26 to_type: &DataType,
27 cast_options: &CastOptions,
28) -> Result<ArrayRef, ArrowError> {
29 use DataType::*;
30
31 let array = array.as_dictionary::<K>();
32 let from_child_type = array.values().data_type();
33 match (from_child_type, to_type) {
34 (_, Dictionary(to_index_type, to_value_type)) => {
35 dictionary_to_dictionary_cast(array, to_index_type, to_value_type, cast_options)
36 }
37 (Utf8, Utf8View) => view_from_dict_values::<K, Utf8Type, StringViewType>(
43 array.keys(),
44 array.values().as_string::<i32>(),
45 ),
46 (Binary, BinaryView) => view_from_dict_values::<K, BinaryType, BinaryViewType>(
47 array.keys(),
48 array.values().as_binary::<i32>(),
49 ),
50 _ => unpack_dictionary(array, to_type, cast_options),
51 }
52}
53
54fn dictionary_to_dictionary_cast<K: ArrowDictionaryKeyType>(
55 array: &DictionaryArray<K>,
56 to_index_type: &DataType,
57 to_value_type: &DataType,
58 cast_options: &CastOptions,
59) -> Result<ArrayRef, ArrowError> {
60 use DataType::*;
61
62 if matches!(array.values().data_type(), Dictionary(_, _)) {
69 let flattened = take(array.values().as_ref(), array.keys(), None)?;
70 return cast_with_options(
71 &flattened,
72 &Dictionary(
73 Box::new(to_index_type.clone()),
74 Box::new(to_value_type.clone()),
75 ),
76 cast_options,
77 );
78 }
79
80 let keys_array: ArrayRef = Arc::new(PrimitiveArray::<K>::from(array.keys().to_data()));
81 let values_array = array.values();
82 let cast_keys = cast_with_options(&keys_array, to_index_type, cast_options)?;
83 let cast_values = cast_with_options(values_array, to_value_type, cast_options)?;
84
85 if cast_keys.null_count() > keys_array.null_count() {
88 return Err(ArrowError::ComputeError(format!(
89 "Could not convert {} dictionary indexes from {:?} to {:?}",
90 cast_keys.null_count() - keys_array.null_count(),
91 keys_array.data_type(),
92 to_index_type
93 )));
94 }
95
96 let data = cast_keys.into_data();
97 let builder = data
98 .into_builder()
99 .data_type(Dictionary(
100 Box::new(to_index_type.clone()),
101 Box::new(to_value_type.clone()),
102 ))
103 .child_data(vec![cast_values.into_data()]);
104
105 let data = unsafe { builder.build_unchecked() };
108
109 let new_array: ArrayRef = match to_index_type {
111 Int8 => Arc::new(DictionaryArray::<Int8Type>::from(data)),
112 Int16 => Arc::new(DictionaryArray::<Int16Type>::from(data)),
113 Int32 => Arc::new(DictionaryArray::<Int32Type>::from(data)),
114 Int64 => Arc::new(DictionaryArray::<Int64Type>::from(data)),
115 UInt8 => Arc::new(DictionaryArray::<UInt8Type>::from(data)),
116 UInt16 => Arc::new(DictionaryArray::<UInt16Type>::from(data)),
117 UInt32 => Arc::new(DictionaryArray::<UInt32Type>::from(data)),
118 UInt64 => Arc::new(DictionaryArray::<UInt64Type>::from(data)),
119 _ => {
120 return Err(ArrowError::CastError(format!(
121 "Unsupported type {to_index_type} for dictionary index"
122 )));
123 }
124 };
125
126 Ok(new_array)
127}
128
129fn view_from_dict_values<K: ArrowDictionaryKeyType, V: ByteArrayType, T: ByteViewType>(
130 keys: &PrimitiveArray<K>,
131 values: &GenericByteArray<V>,
132) -> Result<ArrayRef, ArrowError> {
133 let value_buffer = values.values();
134 let value_offsets = values.value_offsets();
135 let values_have_nulls = values.null_count() != 0;
137 let mut builder = GenericByteViewBuilder::<T>::with_capacity(keys.len());
138 builder.append_block(value_buffer.clone());
139 for i in keys.iter() {
140 match i {
141 Some(v) => {
142 let idx = v.to_usize().ok_or_else(|| {
143 ArrowError::ComputeError("Invalid dictionary index".to_string())
144 })?;
145
146 if values_have_nulls && values.is_null(idx) {
147 builder.append_null();
148 continue;
149 }
150
151 unsafe {
155 let offset = value_offsets.get_unchecked(idx).as_usize();
156 let end = value_offsets.get_unchecked(idx + 1).as_usize();
157 let length = end - offset;
158 builder.append_view_unchecked(0, offset as u32, length as u32)
159 }
160 }
161 None => {
162 builder.append_null();
163 }
164 }
165 }
166 Ok(Arc::new(builder.finish()))
167}
168
169pub(crate) fn unpack_dictionary<K: ArrowDictionaryKeyType>(
171 array: &DictionaryArray<K>,
172 to_type: &DataType,
173 cast_options: &CastOptions,
174) -> Result<ArrayRef, ArrowError> {
175 let cast_dict_values = cast_with_options(array.values(), to_type, cast_options)?;
176 take(cast_dict_values.as_ref(), array.keys(), None)
177}
178
179pub(crate) fn pack_array_to_dictionary_via_primitive<K: ArrowDictionaryKeyType>(
181 array: &dyn Array,
182 primitive_type: DataType,
183 dict_value_type: &DataType,
184 cast_options: &CastOptions,
185) -> Result<ArrayRef, ArrowError> {
186 let primitive = cast_with_options(array, &primitive_type, cast_options)?;
187 let dict = cast_with_options(
188 primitive.as_ref(),
189 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(primitive_type)),
190 cast_options,
191 )?;
192 cast_with_options(
193 dict.as_ref(),
194 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(dict_value_type.clone())),
195 cast_options,
196 )
197}
198
199pub(crate) fn cast_to_dictionary<K: ArrowDictionaryKeyType>(
204 array: &dyn Array,
205 dict_value_type: &DataType,
206 cast_options: &CastOptions,
207) -> Result<ArrayRef, ArrowError> {
208 use DataType::*;
209
210 match *dict_value_type {
211 Int8 => pack_numeric_to_dictionary::<K, Int8Type>(array, dict_value_type, cast_options),
212 Int16 => pack_numeric_to_dictionary::<K, Int16Type>(array, dict_value_type, cast_options),
213 Int32 => pack_numeric_to_dictionary::<K, Int32Type>(array, dict_value_type, cast_options),
214 Int64 => pack_numeric_to_dictionary::<K, Int64Type>(array, dict_value_type, cast_options),
215 UInt8 => pack_numeric_to_dictionary::<K, UInt8Type>(array, dict_value_type, cast_options),
216 UInt16 => pack_numeric_to_dictionary::<K, UInt16Type>(array, dict_value_type, cast_options),
217 UInt32 => pack_numeric_to_dictionary::<K, UInt32Type>(array, dict_value_type, cast_options),
218 UInt64 => pack_numeric_to_dictionary::<K, UInt64Type>(array, dict_value_type, cast_options),
219 Decimal32(p, s) => pack_decimal_to_dictionary::<K, Decimal32Type>(
220 array,
221 dict_value_type,
222 p,
223 s,
224 cast_options,
225 ),
226 Decimal64(p, s) => pack_decimal_to_dictionary::<K, Decimal64Type>(
227 array,
228 dict_value_type,
229 p,
230 s,
231 cast_options,
232 ),
233 Decimal128(p, s) => pack_decimal_to_dictionary::<K, Decimal128Type>(
234 array,
235 dict_value_type,
236 p,
237 s,
238 cast_options,
239 ),
240 Decimal256(p, s) => pack_decimal_to_dictionary::<K, Decimal256Type>(
241 array,
242 dict_value_type,
243 p,
244 s,
245 cast_options,
246 ),
247 Float16 => {
248 pack_numeric_to_dictionary::<K, Float16Type>(array, dict_value_type, cast_options)
249 }
250 Float32 => {
251 pack_numeric_to_dictionary::<K, Float32Type>(array, dict_value_type, cast_options)
252 }
253 Float64 => {
254 pack_numeric_to_dictionary::<K, Float64Type>(array, dict_value_type, cast_options)
255 }
256 Date32 => pack_array_to_dictionary_via_primitive::<K>(
257 array,
258 DataType::Int32,
259 dict_value_type,
260 cast_options,
261 ),
262 Date64 => pack_array_to_dictionary_via_primitive::<K>(
263 array,
264 DataType::Int64,
265 dict_value_type,
266 cast_options,
267 ),
268 Time32(_) => pack_array_to_dictionary_via_primitive::<K>(
269 array,
270 DataType::Int32,
271 dict_value_type,
272 cast_options,
273 ),
274 Time64(_) => pack_array_to_dictionary_via_primitive::<K>(
275 array,
276 DataType::Int64,
277 dict_value_type,
278 cast_options,
279 ),
280 Timestamp(_, _) => pack_array_to_dictionary_via_primitive::<K>(
281 array,
282 DataType::Int64,
283 dict_value_type,
284 cast_options,
285 ),
286 Utf8 => {
287 if array.data_type() == &DataType::Utf8View {
289 return string_view_to_dictionary::<K, i32>(array);
290 }
291 pack_byte_to_dictionary::<K, GenericStringType<i32>>(array, cast_options)
292 }
293 LargeUtf8 => {
294 if array.data_type() == &DataType::Utf8View {
296 return string_view_to_dictionary::<K, i64>(array);
297 }
298 pack_byte_to_dictionary::<K, GenericStringType<i64>>(array, cast_options)
299 }
300 Utf8View => {
301 let base_value_type = match array.data_type() {
302 DataType::LargeUtf8 | DataType::Utf8View => DataType::LargeUtf8,
303 _ => DataType::Utf8,
304 };
305
306 let dict_base = cast_to_dictionary::<K>(array, &base_value_type, cast_options)?;
307 dictionary_cast::<K>(
308 dict_base.as_ref(),
309 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(DataType::Utf8View)),
310 cast_options,
311 )
312 }
313 Binary => {
314 if array.data_type() == &DataType::BinaryView {
316 return binary_view_to_dictionary::<K, i32>(array);
317 }
318 pack_byte_to_dictionary::<K, GenericBinaryType<i32>>(array, cast_options)
319 }
320 LargeBinary => {
321 if array.data_type() == &DataType::BinaryView {
323 return binary_view_to_dictionary::<K, i64>(array);
324 }
325 pack_byte_to_dictionary::<K, GenericBinaryType<i64>>(array, cast_options)
326 }
327 BinaryView => {
328 let base_value_type = match array.data_type() {
329 DataType::LargeBinary | DataType::BinaryView => DataType::LargeBinary,
330 _ => DataType::Binary,
331 };
332
333 let dict_base = cast_to_dictionary::<K>(array, &base_value_type, cast_options)?;
334 dictionary_cast::<K>(
335 dict_base.as_ref(),
336 &DataType::Dictionary(Box::new(K::DATA_TYPE), Box::new(DataType::BinaryView)),
337 cast_options,
338 )
339 }
340 FixedSizeBinary(byte_size) => {
341 pack_byte_to_fixed_size_dictionary::<K>(array, cast_options, byte_size)
342 }
343 Struct(_) => pack_struct_to_dictionary::<K>(array, dict_value_type, cast_options),
344 _ => Err(ArrowError::CastError(format!(
345 "Unsupported output type for dictionary packing: {dict_value_type}"
346 ))),
347 }
348}
349
350fn pack_struct_to_dictionary<K: ArrowDictionaryKeyType>(
360 array: &dyn Array,
361 dict_value_type: &DataType,
362 cast_options: &CastOptions,
363) -> Result<ArrayRef, ArrowError> {
364 let cast_values = cast_with_options(array, dict_value_type, cast_options)?;
365 let len = cast_values.len();
366
367 let mut builder = PrimitiveBuilder::<K>::with_capacity(len);
370 for i in 0..len {
371 if cast_values.is_null(i) {
372 builder.append_null();
373 } else {
374 let key = K::Native::from_usize(i).ok_or_else(|| {
375 ArrowError::CastError(format!(
376 "Cannot fit {len} dictionary keys in {:?}",
377 K::DATA_TYPE,
378 ))
379 })?;
380 builder.append_value(key);
381 }
382 }
383 let keys = builder.finish();
384
385 Ok(Arc::new(DictionaryArray::<K>::try_new(keys, cast_values)?))
386}
387
388pub(crate) fn pack_numeric_to_dictionary<K, V>(
391 array: &dyn Array,
392 dict_value_type: &DataType,
393 cast_options: &CastOptions,
394) -> Result<ArrayRef, ArrowError>
395where
396 K: ArrowDictionaryKeyType,
397 V: ArrowPrimitiveType,
398{
399 let cast_values = cast_with_options(array, dict_value_type, cast_options)?;
401 let values = cast_values.as_primitive::<V>();
402
403 let mut b = PrimitiveDictionaryBuilder::<K, V>::with_capacity(values.len(), values.len());
404
405 for i in 0..values.len() {
407 if values.is_null(i) {
408 b.append_null();
409 } else {
410 b.append(values.value(i))?;
411 }
412 }
413 Ok(Arc::new(b.finish()))
414}
415
416pub(crate) fn pack_decimal_to_dictionary<K, D>(
417 array: &dyn Array,
418 dict_value_type: &DataType,
419 precision: u8,
420 scale: i8,
421 cast_options: &CastOptions,
422) -> Result<ArrayRef, ArrowError>
423where
424 K: ArrowDictionaryKeyType,
425 D: DecimalType + ArrowPrimitiveType,
426{
427 let dict = pack_numeric_to_dictionary::<K, D>(array, dict_value_type, cast_options)?;
428 let dict = dict.as_dictionary::<K>();
429 let typed = dict.downcast_dict::<PrimitiveArray<D>>().ok_or_else(|| {
430 ArrowError::ComputeError(format!(
431 "Internal Error: Cannot cast dict to {}Array",
432 D::PREFIX
433 ))
434 })?;
435 let value = typed
436 .values()
437 .clone()
438 .with_precision_and_scale(precision, scale)?;
439 Ok(Arc::new(dict.with_values(Arc::new(value))))
440}
441
442pub(crate) fn string_view_to_dictionary<K, O: OffsetSizeTrait>(
443 array: &dyn Array,
444) -> Result<ArrayRef, ArrowError>
445where
446 K: ArrowDictionaryKeyType,
447{
448 let mut b = GenericByteDictionaryBuilder::<K, GenericStringType<O>>::with_capacity(
449 array.len(),
450 1024,
451 1024,
452 );
453 let string_view = array
454 .as_any()
455 .downcast_ref::<StringViewArray>()
456 .ok_or_else(|| {
457 ArrowError::ComputeError("Internal Error: Cannot cast to StringViewArray".to_string())
458 })?;
459 for v in string_view.iter() {
460 match v {
461 Some(v) => {
462 b.append(v)?;
463 }
464 None => {
465 b.append_null();
466 }
467 }
468 }
469
470 Ok(Arc::new(b.finish()))
471}
472
473pub(crate) fn binary_view_to_dictionary<K, O: OffsetSizeTrait>(
474 array: &dyn Array,
475) -> Result<ArrayRef, ArrowError>
476where
477 K: ArrowDictionaryKeyType,
478{
479 let mut b = GenericByteDictionaryBuilder::<K, GenericBinaryType<O>>::with_capacity(
480 array.len(),
481 1024,
482 1024,
483 );
484 let binary_view = array
485 .as_any()
486 .downcast_ref::<BinaryViewArray>()
487 .ok_or_else(|| {
488 ArrowError::ComputeError("Internal Error: Cannot cast to BinaryViewArray".to_string())
489 })?;
490 for v in binary_view.iter() {
491 match v {
492 Some(v) => {
493 b.append(v)?;
494 }
495 None => {
496 b.append_null();
497 }
498 }
499 }
500
501 Ok(Arc::new(b.finish()))
502}
503
504pub(crate) fn pack_byte_to_dictionary<K, T>(
507 array: &dyn Array,
508 cast_options: &CastOptions,
509) -> Result<ArrayRef, ArrowError>
510where
511 K: ArrowDictionaryKeyType,
512 T: ByteArrayType,
513{
514 let cast_values = cast_with_options(array, &T::DATA_TYPE, cast_options)?;
515 let values = cast_values
516 .as_any()
517 .downcast_ref::<GenericByteArray<T>>()
518 .ok_or_else(|| {
519 ArrowError::ComputeError("Internal Error: Cannot cast to GenericByteArray".to_string())
520 })?;
521 let mut b = GenericByteDictionaryBuilder::<K, T>::with_capacity(values.len(), 1024, 1024);
522
523 for i in 0..values.len() {
525 if values.is_null(i) {
526 b.append_null();
527 } else {
528 b.append(values.value(i))?;
529 }
530 }
531 Ok(Arc::new(b.finish()))
532}
533
534pub(crate) fn pack_byte_to_fixed_size_dictionary<K>(
537 array: &dyn Array,
538 cast_options: &CastOptions,
539 byte_width: i32,
540) -> Result<ArrayRef, ArrowError>
541where
542 K: ArrowDictionaryKeyType,
543{
544 let cast_values =
545 cast_with_options(array, &DataType::FixedSizeBinary(byte_width), cast_options)?;
546 let values = cast_values
547 .as_any()
548 .downcast_ref::<FixedSizeBinaryArray>()
549 .ok_or_else(|| {
550 ArrowError::ComputeError("Internal Error: Cannot cast to GenericByteArray".to_string())
551 })?;
552 let mut b = FixedSizeBinaryDictionaryBuilder::<K>::with_capacity(1024, 1024, byte_width);
553
554 for i in 0..values.len() {
556 if values.is_null(i) {
557 b.append_null();
558 } else {
559 b.append(values.value(i))?;
560 }
561 }
562 Ok(Arc::new(b.finish()))
563}