Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions arrow-cast/src/cast/decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// under the License.

use crate::cast::*;
use crate::parse::*;

/// A utility trait that provides checked conversions between
/// decimal types inspired by [`NumCast`]
Expand Down Expand Up @@ -352,7 +353,7 @@ where
{
if cast_options.safe {
let iter = from.iter().map(|v| {
v.and_then(|v| parse_string_to_decimal_native::<T>(v, scale as usize).ok())
v.and_then(|v| parse_decimal::<T>(v, precision, scale).ok())
.and_then(|v| T::is_valid_decimal_precision(v, precision).then_some(v))
});
// Benefit:
Expand All @@ -368,12 +369,13 @@ where
.iter()
.map(|v| {
v.map(|v| {
parse_string_to_decimal_native::<T>(v, scale as usize)
parse_decimal::<T>(v, precision, scale)
.map_err(|_| {
ArrowError::CastError(format!(
"Cannot cast string '{}' to value of {:?} type",
"Cannot cast string '{}' to decimal type of precision {} and scale {}",
v,
T::DATA_TYPE,
precision,
scale
))
})
.and_then(|v| T::validate_decimal_precision(v, precision).map(|_| v))
Expand Down
44 changes: 34 additions & 10 deletions arrow-cast/src/cast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2383,6 +2383,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::parse::parse_decimal;
use arrow_buffer::{Buffer, IntervalDayTime, NullBuffer};
use chrono::NaiveDate;
use half::f16;
Expand Down Expand Up @@ -2556,6 +2557,22 @@ mod tests {
]
);
}
#[test]
fn test_cast_with_options_utf8_to_decimal() {
let array = StringArray::from(vec!["4e7"]);
let result = cast_with_options(
&array,
&DataType::Decimal128(10, 2),
&CastOptions {
safe: false,
format_options: FormatOptions::default(),
},
)
.unwrap();
let output_array = result.as_any().downcast_ref::<Decimal128Array>();
let result_128 = parse_decimal::<Decimal128Type>("40000000", 10, 2);
assert_eq!(output_array.unwrap().value(0), result_128.unwrap());
}

#[test]
fn test_cast_decimal128_to_decimal128() {
Expand Down Expand Up @@ -8763,16 +8780,17 @@ mod tests {
format_options: FormatOptions::default(),
};
let casted_err = cast_with_options(&array, &output_type, &option).unwrap_err();
assert!(casted_err
.to_string()
.contains("Cannot cast string '4.4.5' to value of Decimal128(38, 10) type"));
println!("{}", casted_err.to_string());
assert!(casted_err.to_string().contains(
"Cast error: Cannot cast string '4.4.5' to decimal type of precision 38 and scale 2"
));

let str_array = StringArray::from(vec![". 0.123"]);
let array = Arc::new(str_array) as ArrayRef;
let casted_err = cast_with_options(&array, &output_type, &option).unwrap_err();
assert!(casted_err
.to_string()
.contains("Cannot cast string '. 0.123' to value of Decimal128(38, 10) type"));
assert!(casted_err.to_string().contains(
"Cast error: Cannot cast string '. 0.123' to decimal type of precision 38 and scale 2"
));
}

fn test_cast_string_to_decimal128_overflow(overflow_array: ArrayRef) {
Expand All @@ -8788,7 +8806,7 @@ mod tests {
decimal_arr.value_as_string(3)
);
assert_eq!(
"100000000000000000000000000000000000.00",
"99999999999999999999999999999999999.99",
decimal_arr.value_as_string(4)
);
}
Expand Down Expand Up @@ -8816,7 +8834,10 @@ mod tests {
format_options: FormatOptions::default(),
},
);
assert_eq!("Invalid argument error: 100000000000 is too large to store in a Decimal128 of precision 10. Max is 9999999999", err.unwrap_err().to_string());
assert_eq!(
"Cast error: Cannot cast string '1000' to decimal type of precision 10 and scale 8",
err.unwrap_err().to_string()
);
}

#[test]
Expand Down Expand Up @@ -8869,7 +8890,7 @@ mod tests {
decimal_arr.value_as_string(3)
);
assert_eq!(
"100000000000000000000000000000000000.00",
"99999999999999999999999999999999999.99",
decimal_arr.value_as_string(4)
);
assert!(decimal_arr.is_null(5));
Expand Down Expand Up @@ -8899,7 +8920,10 @@ mod tests {
format_options: FormatOptions::default(),
},
);
assert_eq!("Invalid argument error: 100000000000 is too large to store in a Decimal256 of precision 10. Max is 9999999999", err.unwrap_err().to_string());
assert_eq!(
"Cast error: Cannot cast string '1000' to decimal type of precision 10 and scale 8",
err.unwrap_err().to_string()
);
}

#[test]
Expand Down
Loading