Skip to content

Commit

Permalink
fix review comments and fix formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
himadripal committed Dec 5, 2024
1 parent 076cee4 commit 264c29b
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 70 deletions.
64 changes: 24 additions & 40 deletions arrow-cast/src/cast/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,13 @@ where
O::Native::from_decimal(adjusted)
};

Ok(match cast_options.safe {
true => {
array.unary_opt(|x| {
f(x).filter(|v| O::is_valid_decimal_precision(*v, output_precision))
})
}
false => {
array.try_unary(|x| {
f(x).ok_or_else(|| error(x))
.and_then(|v|{
O:: validate_decimal_precision(v, output_precision).map(|_| v)
})
})?
}
Ok(if cast_options.safe {
array.unary_opt(|x| f(x).filter(|v| O::is_valid_decimal_precision(*v, output_precision)))
} else {
array.try_unary(|x| {
f(x).ok_or_else(|| error(x))
.and_then(|v| O::validate_decimal_precision(v, output_precision).map(|_| v))
})?
})
}

Expand All @@ -146,23 +139,15 @@ where
.unwrap()
.pow_checked((output_scale - input_scale) as u32)?;

let f = |x|
O::Native::from_decimal(x).and_then(|x| x.mul_checked(mul).ok());
let f = |x| O::Native::from_decimal(x).and_then(|x| x.mul_checked(mul).ok());

Ok(match cast_options.safe {
true => {
array.unary_opt(|x| {
f(x).filter(|v| O::is_valid_decimal_precision(*v, output_precision))
})
}
false => {
array.try_unary(|x| {
f(x).ok_or_else(|| error(x))
.and_then(|v|{
O:: validate_decimal_precision(v, output_precision).map(|_| v)
})
})?
}
Ok(if cast_options.safe {
array.unary_opt(|x| f(x).filter(|v| O::is_valid_decimal_precision(*v, output_precision)))
} else {
array.try_unary(|x| {
f(x).ok_or_else(|| error(x))
.and_then(|v| O::validate_decimal_precision(v, output_precision).map(|_| v))
})?
})
}

Expand All @@ -178,8 +163,7 @@ where
T: DecimalType,
T::Native: DecimalCast + ArrowNativeTypeOp,
{
let array: PrimitiveArray<T> = match input_scale.cmp(&output_scale) {
Ordering::Equal | Ordering::Less => {
let array: PrimitiveArray<T> = if input_scale <= output_scale {
// input_scale <= output_scale
// the scale doesn't change, but precision may change and cause overflow
convert_to_bigger_or_equal_scale_decimal::<T, T>(
Expand All @@ -189,14 +173,14 @@ where
output_scale,
cast_options,
)?
}
Ordering::Greater => convert_to_smaller_scale_decimal::<T, T>(
array,
input_scale,
output_precision,
output_scale,
cast_options,
)?
} else {
convert_to_smaller_scale_decimal::<T, T>(
array,
input_scale,
output_precision,
output_scale,
cast_options,
)?
};

Ok(Arc::new(array.with_precision_and_scale(
Expand Down
52 changes: 22 additions & 30 deletions arrow-cast/src/cast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2681,13 +2681,13 @@ mod tests {
// negative test
let array = vec![Some(123456), None];
let array = create_decimal_array(array, 10, 0).unwrap();
let result = cast(&array, &DataType::Decimal128(2, 2));
assert!(result.is_ok());
let array = result.unwrap();
let array: &Decimal128Array = array.as_primitive();
let err = array.validate_decimal_precision(2);
let result_safe = cast(&array, &DataType::Decimal128(2, 2));
assert!(result_safe.is_ok());
let options = CastOptions { safe: false, ..Default::default() };

let result_unsafe = cast_with_options(&array, &DataType::Decimal128(2, 2), &options);
assert_eq!("Invalid argument error: 12345600 is too large to store in a Decimal128 of precision 2. Max is 99",
err.unwrap_err().to_string());
result_unsafe.unwrap_err().to_string());
}

#[test]
Expand Down Expand Up @@ -8388,7 +8388,7 @@ mod tests {
let input_type = DataType::Decimal128(10, 3);
let output_type = DataType::Decimal256(10, 5);
assert!(can_cast_types(&input_type, &output_type));
let array = vec![Some(i128::MAX), Some(i128::MIN)];
let array = vec![Some(123456), Some(-123456)];
let input_decimal_array = create_decimal_array(array, 10, 3).unwrap();
let array = Arc::new(input_decimal_array) as ArrayRef;

Expand All @@ -8398,8 +8398,8 @@ mod tests {
Decimal256Array,
&output_type,
vec![
Some(i256::from_i128(i128::MAX).mul_wrapping(hundred)),
Some(i256::from_i128(i128::MIN).mul_wrapping(hundred))
Some(i256::from_i128(123456).mul_wrapping(hundred)),
Some(i256::from_i128(-123456).mul_wrapping(hundred))
]
);
}
Expand Down Expand Up @@ -9829,70 +9829,62 @@ mod tests {
}

#[test]
fn test_decimal_to_decimal_throw_error_on_precision_overflow_same_scale(){
fn test_decimal_to_decimal_throw_error_on_precision_overflow_same_scale() {
let array = vec![Some(123456789)];
let array = create_decimal_array(array, 24, 2).unwrap();
println!("{:?}", array);
let input_type = DataType::Decimal128(24, 2);
let output_type = DataType::Decimal128(6, 2);
assert!(can_cast_types(&input_type, &output_type));
let mut options = CastOptions::default();
options.safe = false;

let options = CastOptions { safe: false, ..Default::default() };
let result = cast_with_options(&array, &output_type, &options);

assert_eq!(result.unwrap_err().to_string(),
"InvalidArgumentError(123456789 is too large to store in a Decimal128 of precision 6. Max is 999999)");
"Invalid argument error: 123456789 is too large to store in a Decimal128 of precision 6. Max is 999999");
}

#[test]
fn test_decimal_to_decimal_throw_error_on_precision_overflow_lower_scale(){
fn test_decimal_to_decimal_throw_error_on_precision_overflow_lower_scale() {
let array = vec![Some(123456789)];
let array = create_decimal_array(array, 24, 2).unwrap();
println!("{:?}", array);
let input_type = DataType::Decimal128(24, 4);
let output_type = DataType::Decimal128(6, 2);
assert!(can_cast_types(&input_type, &output_type));
let mut options = CastOptions::default();
options.safe = false;

let options = CastOptions { safe: false, ..Default::default() };
let result = cast_with_options(&array, &output_type, &options);

assert_eq!(result.unwrap_err().to_string(),
"InvalidArgumentError(123456789 is too large to store in a Decimal128 of precision 6. Max is 999999)");
"Invalid argument error: 123456789 is too large to store in a Decimal128 of precision 6. Max is 999999");
}

#[test]
fn test_decimal_to_decimal_throw_error_on_precision_overflow_greater_scale(){
fn test_decimal_to_decimal_throw_error_on_precision_overflow_greater_scale() {
let array = vec![Some(123456789)];
let array = create_decimal_array(array, 24, 2).unwrap();
println!("{:?}", array);
let input_type = DataType::Decimal128(24, 2);
let output_type = DataType::Decimal128(6, 3);
assert!(can_cast_types(&input_type, &output_type));
let mut options = CastOptions::default();
options.safe = false;

let options = CastOptions { safe: false, ..Default::default() };
let result = cast_with_options(&array, &output_type, &options);

assert_eq!(result.unwrap_err().to_string(),
"InvalidArgumentError(123456789 is too large to store in a Decimal128 of precision 6. Max is 999999)");
"Invalid argument error: 1234567890 is too large to store in a Decimal128 of precision 6. Max is 999999");
}

#[test]
fn test_decimal_to_decimal_throw_error_on_precision_overflow_diff_type(){
fn test_decimal_to_decimal_throw_error_on_precision_overflow_diff_type() {
let array = vec![Some(123456789)];
let array = create_decimal_array(array, 24, 2).unwrap();
println!("{:?}", array);
let input_type = DataType::Decimal128(24, 2);
let output_type = DataType::Decimal256(6, 2);
assert!(can_cast_types(&input_type, &output_type));
let mut options = CastOptions::default();
options.safe = false;

let result = cast_with_options(&array, &output_type, &options);

let options = CastOptions { safe: false, ..Default::default() };
let result = cast_with_options(&array, &output_type, &options);
assert_eq!(result.unwrap_err().to_string(),
"InvalidArgumentError(123456789 is too large to store in a Decimal256 of precision 6. Max is 999999)");
"Invalid argument error: 123456789 is too large to store in a Decimal256 of precision 6. Max is 999999");
}
}

0 comments on commit 264c29b

Please sign in to comment.