JingsongLi commented on code in PR #907:
URL: https://github.com/apache/paimon-rust/pull/907#discussion_r4067959566
##########
crates/paimon/src/arrow/nested_evolution.rs:
##########
@@ -64,6 +66,62 @@ pub(crate) fn evolve_column(
return Ok(source.clone());
}
+ if let (
+ ArrowDataType::Decimal128(_, source_scale),
+ ArrowDataType::Decimal128(target_precision, target_scale),
+ ) = (source.data_type(), &target_arrow)
+ {
+ if source_scale > target_scale {
+ // Arrow rounds Decimal128 scale reductions. Paimon schema casts,
+ // like Python's unsafe Arrow cast, truncate toward zero instead.
+ let shift = u32::try_from(i16::from(*source_scale) -
i16::from(*target_scale))
+ .map_err(|_| crate::Error::DataInvalid {
+ message: "invalid decimal scale reduction".to_string(),
+ source: None,
+ })?;
+ let divisor = 10_i128
+ .checked_pow(shift)
+ .ok_or_else(|| crate::Error::DataInvalid {
+ message: "decimal scale reduction exceeds Decimal128
range".to_string(),
+ source: None,
+ })?;
+ let decimals = source
+ .as_any()
+ .downcast_ref::<Decimal128Array>()
+ .ok_or_else(|| crate::Error::DataInvalid {
+ message: format!("expected Decimal128 array, got {:?}",
source.data_type()),
+ source: None,
+ })?;
+ let reduced = Decimal128Array::from(
+ (0..decimals.len())
+ .map(|index| {
+ decimals
+ .is_valid(index)
+ .then(|| decimals.value(index) / divisor)
Review Comment:
Fixed in aeba0cdf. Removed the truncating Decimal128 special case so scale
reductions use Arrow safe cast, matching Java HALF_UP. Added positive/negative
and exact-half regression cases; both failed before the fix and pass now.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]