You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "yongster (via GitHub)" <gi...@apache.org> on 2026/08/16 07:12:37 UTC
[I] cast from integer to Decimal32/64 silently truncates values that do not fit [arrow-rs]
yongster opened a new issue, #10706:
URL: https://github.com/apache/arrow-rs/issues/10706
### Describe the bug
### Describe the bug
`cast` / `cast_with_options` from an integer array to `Decimal32` or `Decimal64`
can rewrite the value instead of rejecting it.
The conversion first uses `AsPrimitive` (`as`), which wraps when the source
integer does not fit the decimal native type (`i32` / `i64`). The precision
check then runs on the already-truncated value. If that wrapped value happens
to fit the requested precision, it is stored as if it were the original number.
The same input cast to `Decimal128` is correct: `i64 as i128` is lossless, so
the precision check still sees the original value and returns null / an error.
### To Reproduce
Reproduced on `main` (59.2.0).
;
let a = Int64Array::from(vec![5_000_000_000i64]);
let d32 = cast_with_options(&a, &DataType::Decimal32(9, 0), &safe).unwrap();
println!("i64 5e9 -> Decimal32(9,0) safe: {d32:?}");
// actual: PrimitiveArray<Decimal32(9, 0)>[705032704]
// expected: PrimitiveArray<Decimal32(9, 0)>[null]
let d128 = cast_with_options(&a, &DataType::Decimal128(9, 0), &safe).unwrap();
println!("i64 5e9 -> Decimal128(9,0) safe: {d128:?}");
// Decimal128 is already correct: [null]
let u = UInt32Array::from(vec![4_000_000_000u32]);
let u32_unsafe =
cast_with_options(&u, &DataType::Decimal32(9, 0), &unsafe_opts);
println!("u32 4e9 -> Decimal32(9,0) unsafe: {u32_unsafe:?}");
// actual: Ok(PrimitiveArray<Decimal32(9, 0)>[-294967296])
// expected: Err(...)
let umax = UInt64Array::from(vec![u64::MAX]);
let u64_unsafe =
cast_with_options(&umax, &DataType::Decimal64(18, 0), &unsafe_opts);
println!("u64::MAX -> Decimal64(18,0) unsafe: {u64_unsafe:?}");
// actual: Ok(PrimitiveArray<Decimal64(18, 0)>[-1])
// expected: Err(...)
}
5_000_000_000i64 as i32 is 705032704. That 9-digit value is then accepted by Decimal32(9, 0) (max is 999_999_999).
### Expected behavior
Integer to decimal should use the original integer for the range / precision check, then convert.
• If the value does not fit the target native type or the requested precision:
• safe: true → null
• safe: false → Err, and the message should mention the original value
• Int64(5_000_000_000) -> Decimal32(9, 0) should match
Int64(5_000_000_000) -> Decimal128(9, 0)
• UInt32(4_000_000_000) -> Decimal32(9, 0) must not become a negative
• UInt64::MAX -> Decimal64(18, 0) must not become -1
### Additional context
The conversion is in cast_integer_to_decimal (arrow-cast/src/cast/mod.rs). All four arms do:
v.as_()
.mul_checked(scale_factor) // or div_checked when scale < 0
.and_then(|v| D::is_valid_decimal_precision(v, precision).then_some(v))
AsPrimitive is a wrapping cast. The later precision check therefore never sees 5000000000, only 705032704.
Existing overflow tests cover Int64 -> Decimal128/256 via a large scale factor, not this native-width wrap into Decimal32 / Decimal64.
I ran the reproduction locally and reviewed the result.
---
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] cast from integer to Decimal32/64 silently truncates values that do not fit [arrow-rs]
Posted by "Jefffrey (via GitHub)" <gi...@apache.org>.
Jefffrey closed issue #10706: cast from integer to Decimal32/64 silently truncates values that do not fit
URL: https://github.com/apache/arrow-rs/issues/10706
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org