Skip to content

Commit

Permalink
fix: Stop losing precision and scale when casting decimal to dictiona…
Browse files Browse the repository at this point in the history
…ry (#6383)

* Stop losing precision and scale when casting decimal to dictionary

* address feedback
  • Loading branch information
andygrove authored Sep 19, 2024
1 parent e7598a4 commit d274b69
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 4 deletions.
38 changes: 34 additions & 4 deletions arrow-cast/src/cast/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,41 @@ pub(crate) fn cast_to_dictionary<K: ArrowDictionaryKeyType>(
UInt16 => pack_numeric_to_dictionary::<K, UInt16Type>(array, dict_value_type, cast_options),
UInt32 => pack_numeric_to_dictionary::<K, UInt32Type>(array, dict_value_type, cast_options),
UInt64 => pack_numeric_to_dictionary::<K, UInt64Type>(array, dict_value_type, cast_options),
Decimal128(_, _) => {
pack_numeric_to_dictionary::<K, Decimal128Type>(array, dict_value_type, cast_options)
Decimal128(p, s) => {
let dict = pack_numeric_to_dictionary::<K, Decimal128Type>(
array,
dict_value_type,
cast_options,
)?;
let dict = dict
.as_dictionary::<K>()
.downcast_dict::<Decimal128Array>()
.unwrap();
let value = dict.values().clone();
// Set correct precision/scale
let value = value.with_precision_and_scale(p, s)?;
Ok(Arc::new(DictionaryArray::<K>::try_new(
dict.keys().clone(),
Arc::new(value),
)?))
}
Decimal256(_, _) => {
pack_numeric_to_dictionary::<K, Decimal256Type>(array, dict_value_type, cast_options)
Decimal256(p, s) => {
let dict = pack_numeric_to_dictionary::<K, Decimal256Type>(
array,
dict_value_type,
cast_options,
)?;
let dict = dict
.as_dictionary::<K>()
.downcast_dict::<Decimal256Array>()
.unwrap();
let value = dict.values().clone();
// Set correct precision/scale
let value = value.with_precision_and_scale(p, s)?;
Ok(Arc::new(DictionaryArray::<K>::try_new(
dict.keys().clone(),
Arc::new(value),
)?))
}
Float16 => {
pack_numeric_to_dictionary::<K, Float16Type>(array, dict_value_type, cast_options)
Expand Down
32 changes: 32 additions & 0 deletions arrow-cast/src/cast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2650,6 +2650,38 @@ mod tests {
err.unwrap_err().to_string());
}

#[test]
fn test_cast_decimal128_to_decimal128_dict() {
let p = 20;
let s = 3;
let input_type = DataType::Decimal128(p, s);
let output_type = DataType::Dictionary(
Box::new(DataType::Int32),
Box::new(DataType::Decimal128(p, s)),
);
assert!(can_cast_types(&input_type, &output_type));
let array = vec![Some(1123456), Some(2123456), Some(3123456), None];
let array = create_decimal_array(array, p, s).unwrap();
let cast_array = cast_with_options(&array, &output_type, &CastOptions::default()).unwrap();
assert_eq!(cast_array.data_type(), &output_type);
}

#[test]
fn test_cast_decimal256_to_decimal256_dict() {
let p = 20;
let s = 3;
let input_type = DataType::Decimal256(p, s);
let output_type = DataType::Dictionary(
Box::new(DataType::Int32),
Box::new(DataType::Decimal256(p, s)),
);
assert!(can_cast_types(&input_type, &output_type));
let array = vec![Some(1123456), Some(2123456), Some(3123456), None];
let array = create_decimal_array(array, p, s).unwrap();
let cast_array = cast_with_options(&array, &output_type, &CastOptions::default()).unwrap();
assert_eq!(cast_array.data_type(), &output_type);
}

#[test]
fn test_cast_decimal128_to_decimal128_overflow() {
let input_type = DataType::Decimal128(38, 3);
Expand Down

0 comments on commit d274b69

Please sign in to comment.