This is an automated email from the ASF dual-hosted git repository.
Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 5d087d0d62 fix: Correctly decode zero-valued Decimal256s in
integration tests (#10873)
5d087d0d62 is described below
commit 5d087d0d627eef30eb89eec8866bdfb0267467b8
Author: Neil Conway <[email protected]>
AuthorDate: Wed Aug 26 22:14:34 2026 -0400
fix: Correctly decode zero-valued Decimal256s in integration tests (#10873)
# Which issue does this PR close?
- Closes #10872.
# Rationale for this change
The Decimal256 branch of `array_from_json` didn't handle zeros
correctly. It builds a little-endian two's-complement buffer as part of
converting string-valued decimals into native Decimal256 values, but for
`0` inputs exactly, it used the wrong fill bytes (it used `0xFF` instead
of `0`). This lead to `0` being decoded as `-256`.
# What changes are included in this PR?
* Fix decoding bug (use `0` fill bytes for `0` input values)
* Add unit test
# Are these changes tested?
Yes, new test added.
# Are there any user-facing changes?
No.
---
arrow-integration-test/src/lib.rs | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/arrow-integration-test/src/lib.rs
b/arrow-integration-test/src/lib.rs
index 64860a7ff4..4636aafd59 100644
--- a/arrow-integration-test/src/lib.rs
+++ b/arrow-integration-test/src/lib.rs
@@ -962,10 +962,13 @@ pub fn array_from_json(
let str = value.as_str().unwrap();
let integer = BigInt::parse_bytes(str.as_bytes(),
10).unwrap();
let integer_bytes = integer.to_signed_bytes_le();
- let mut bytes = if integer.is_positive() {
- [0_u8; 32]
- } else {
+ // Sign-extend the minimal-length two's-complement
+ // encoding to the full 32 bytes: 0x00 fill for
+ // non-negative values, 0xFF for negative ones.
+ let mut bytes = if integer.is_negative() {
[255_u8; 32]
+ } else {
+ [0_u8; 32]
};
bytes[0..integer_bytes.len()].copy_from_slice(integer_bytes.as_slice());
b.append_value(i256::from_le_bytes(bytes));
@@ -1269,6 +1272,34 @@ impl ArrowJsonBatch {
mod tests {
use super::*;
+ #[test]
+ fn test_decimal256_from_json() {
+ let field = Field::new("c", DataType::Decimal256(76, 0), false);
+ let col: ArrowJsonColumn = serde_json::from_str(
+ r#"{
+ "name": "c",
+ "count": 5,
+ "VALIDITY": [1, 1, 1, 1, 1],
+ "DATA": [
+ "0",
+ "1",
+ "-1",
+ "123456789012345678901234567890",
+ "-123456789012345678901234567890"
+ ]
+ }"#,
+ )
+ .unwrap();
+ let arr = array_from_json(&field, col, None).unwrap();
+ let arr = arr.as_any().downcast_ref::<Decimal256Array>().unwrap();
+ assert_eq!(arr.value(0), i256::ZERO);
+ assert_eq!(arr.value(1), i256::from_i128(1));
+ assert_eq!(arr.value(2), i256::from_i128(-1));
+ let big = i256::from_string("123456789012345678901234567890").unwrap();
+ assert_eq!(arr.value(3), big);
+ assert_eq!(arr.value(4), i256::ZERO - big);
+ }
+
#[test]
fn test_schema_equality() {
let json = r#"