You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by vi...@apache.org on 2022/07/31 17:38:48 UTC
[arrow-rs] branch master updated: Fix max and min value for decimal256 (#2245)
This is an automated email from the ASF dual-hosted git repository.
viirya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push:
new 281cd7937 Fix max and min value for decimal256 (#2245)
281cd7937 is described below
commit 281cd793750182d434e9add99770a1e7c14fc811
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Sun Jul 31 10:38:42 2022 -0700
Fix max and min value for decimal256 (#2245)
---
arrow/src/array/array_decimal.rs | 6 +++---
arrow/src/array/builder/decimal_builder.rs | 16 +++++++---------
arrow/src/array/data.rs | 2 +-
arrow/src/compute/kernels/cast.rs | 4 ++--
arrow/src/datatypes/datatype.rs | 16 +++++++++-------
5 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/arrow/src/array/array_decimal.rs b/arrow/src/array/array_decimal.rs
index 6a453fc92..cb9f799fd 100644
--- a/arrow/src/array/array_decimal.rs
+++ b/arrow/src/array/array_decimal.rs
@@ -541,7 +541,7 @@ mod tests {
let mut result = decimal_builder.append_value(123456);
let mut error = result.unwrap_err();
assert_eq!(
- "Invalid argument error: 123456 is too large to store in a Decimal of precision 5. Max is 99999",
+ "Invalid argument error: 123456 is too large to store in a Decimal128 of precision 5. Max is 99999",
error.to_string()
);
@@ -558,7 +558,7 @@ mod tests {
result = decimal_builder.append_value(100);
error = result.unwrap_err();
assert_eq!(
- "Invalid argument error: 100 is too large to store in a Decimal of precision 2. Max is 99",
+ "Invalid argument error: 100 is too large to store in a Decimal128 of precision 2. Max is 99",
error.to_string()
);
@@ -677,7 +677,7 @@ mod tests {
#[test]
#[should_panic(
- expected = "-123223423432432 is too small to store in a Decimal of precision 5. Min is -99999"
+ expected = "-123223423432432 is too small to store in a Decimal128 of precision 5. Min is -99999"
)]
fn test_decimal_array_with_precision_and_scale_out_of_range() {
Decimal128Array::from_iter_values([12345, 456, 7890, -123223423432432])
diff --git a/arrow/src/array/builder/decimal_builder.rs b/arrow/src/array/builder/decimal_builder.rs
index 09127e76f..22c1490e8 100644
--- a/arrow/src/array/builder/decimal_builder.rs
+++ b/arrow/src/array/builder/decimal_builder.rs
@@ -261,7 +261,7 @@ mod tests {
use crate::array::array_decimal::{BasicDecimalArray, Decimal128Array};
use crate::array::{array_decimal, Array};
use crate::datatypes::DataType;
- use crate::util::decimal::Decimal128;
+ use crate::util::decimal::{Decimal128, Decimal256};
#[test]
fn test_decimal_builder() {
@@ -357,31 +357,29 @@ mod tests {
#[test]
#[should_panic(
- expected = "9999999999999999999999999999999999999999999999999999999999999999999999999999 is too large to store in a Decimal256 of precision 76. Max is 999999999999999999999999999999999999999999999999999999999999999999999999999"
+ expected = "9999999999999999999999999999999999999999999999999999999999999999999999999999 is too large to store in a Decimal256 of precision 75. Max is 999999999999999999999999999999999999999999999999999999999999999999999999999"
)]
fn test_decimal256_builder_out_of_range_precision_scale() {
- let mut builder = Decimal256Builder::new(30, 76, 6);
+ let mut builder = Decimal256Builder::new(30, 75, 6);
let big_value = BigInt::from_str_radix("9999999999999999999999999999999999999999999999999999999999999999999999999999", 10).unwrap();
- let bytes = big_value.to_signed_bytes_le();
- let value = Decimal256::try_new_from_bytes(76, 6, &bytes).unwrap();
+ let value = Decimal256::from_big_int(&big_value, 75, 6).unwrap();
builder.append_value(&value).unwrap();
}
#[test]
#[should_panic(
- expected = "9999999999999999999999999999999999999999999999999999999999999999999999999999 is too large to store in a Decimal256 of precision 76. Max is 999999999999999999999999999999999999999999999999999999999999999999999999999"
+ expected = "9999999999999999999999999999999999999999999999999999999999999999999999999999 is too large to store in a Decimal256 of precision 75. Max is 999999999999999999999999999999999999999999999999999999999999999999999999999"
)]
fn test_decimal256_data_validation() {
- let mut builder = Decimal256Builder::new(30, 76, 6);
+ let mut builder = Decimal256Builder::new(30, 75, 6);
// Disable validation at builder
unsafe {
builder.disable_value_validation();
}
let big_value = BigInt::from_str_radix("9999999999999999999999999999999999999999999999999999999999999999999999999999", 10).unwrap();
- let bytes = big_value.to_signed_bytes_le();
- let value = Decimal256::try_new_from_bytes(76, 6, &bytes).unwrap();
+ let value = Decimal256::from_big_int(&big_value, 75, 6).unwrap();
builder
.append_value(&value)
.expect("should not validate invalid value at builder");
diff --git a/arrow/src/array/data.rs b/arrow/src/array/data.rs
index 51de65f09..43c43b04a 100644
--- a/arrow/src/array/data.rs
+++ b/arrow/src/array/data.rs
@@ -2841,7 +2841,7 @@ mod tests {
let validation_result = array_data.validate_full();
let error = validation_result.unwrap_err();
assert_eq!(
- "Invalid argument error: 123456 is too large to store in a Decimal of precision 5. Max is 99999",
+ "Invalid argument error: 123456 is too large to store in a Decimal128 of precision 5. Max is 99999",
error.to_string()
);
}
diff --git a/arrow/src/compute/kernels/cast.rs b/arrow/src/compute/kernels/cast.rs
index 7e803766b..ea166f921 100644
--- a/arrow/src/compute/kernels/cast.rs
+++ b/arrow/src/compute/kernels/cast.rs
@@ -2230,7 +2230,7 @@ mod tests {
let array = Arc::new(input_decimal_array) as ArrayRef;
let result = cast(&array, &DataType::Decimal128(2, 2));
assert!(result.is_err());
- assert_eq!("Invalid argument error: 12345600 is too large to store in a Decimal of precision 2. Max is 99",
+ assert_eq!("Invalid argument error: 12345600 is too large to store in a Decimal128 of precision 2. Max is 99",
result.unwrap_err().to_string());
}
@@ -2412,7 +2412,7 @@ mod tests {
let array = Arc::new(array) as ArrayRef;
let casted_array = cast(&array, &DataType::Decimal128(3, 1));
assert!(casted_array.is_err());
- assert_eq!("Invalid argument error: 1000 is too large to store in a Decimal of precision 3. Max is 999", casted_array.unwrap_err().to_string());
+ assert_eq!("Invalid argument error: 1000 is too large to store in a Decimal128 of precision 3. Max is 999", casted_array.unwrap_err().to_string());
// test f32 to decimal type
let array = Float32Array::from(vec![
diff --git a/arrow/src/datatypes/datatype.rs b/arrow/src/datatypes/datatype.rs
index 9f23e6f79..034920d37 100644
--- a/arrow/src/datatypes/datatype.rs
+++ b/arrow/src/datatypes/datatype.rs
@@ -309,7 +309,6 @@ pub const MAX_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [
/// `MAX_DECIMAL_FOR_LARGER_PRECISION[p]` holds the maximum integer value
/// that can be stored in [DataType::Decimal256] value of precision `p` > 38
pub const MAX_DECIMAL_FOR_LARGER_PRECISION: [&str; 38] = [
- "99999999999999999999999999999999999999",
"999999999999999999999999999999999999999",
"9999999999999999999999999999999999999999",
"99999999999999999999999999999999999999999",
@@ -347,6 +346,7 @@ pub const MAX_DECIMAL_FOR_LARGER_PRECISION: [&str; 38] = [
"9999999999999999999999999999999999999999999999999999999999999999999999999",
"99999999999999999999999999999999999999999999999999999999999999999999999999",
"999999999999999999999999999999999999999999999999999999999999999999999999999",
+ "9999999999999999999999999999999999999999999999999999999999999999999999999999",
];
/// `MIN_DECIMAL_FOR_EACH_PRECISION[p]` holds the minimum `i128` value
@@ -395,7 +395,6 @@ pub const MIN_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [
/// `MIN_DECIMAL_FOR_LARGER_PRECISION[p]` holds the minimum integer value
/// that can be stored in a [DataType::Decimal256] value of precision `p` > 38
pub const MIN_DECIMAL_FOR_LARGER_PRECISION: [&str; 38] = [
- "-99999999999999999999999999999999999999",
"-999999999999999999999999999999999999999",
"-9999999999999999999999999999999999999999",
"-99999999999999999999999999999999999999999",
@@ -433,6 +432,7 @@ pub const MIN_DECIMAL_FOR_LARGER_PRECISION: [&str; 38] = [
"-9999999999999999999999999999999999999999999999999999999999999999999999999",
"-99999999999999999999999999999999999999999999999999999999999999999999999999",
"-999999999999999999999999999999999999999999999999999999999999999999999999999",
+ "-9999999999999999999999999999999999999999999999999999999999999999999999999999",
];
/// The maximum precision for [DataType::Decimal128] values
@@ -454,9 +454,11 @@ pub const DECIMAL_DEFAULT_SCALE: usize = 10;
/// interpreted as a Decimal number with precision `precision`
#[inline]
pub(crate) fn validate_decimal_precision(value: i128, precision: usize) -> Result<i128> {
- // TODO: add validation logic for precision > 38
- if precision > 38 {
- return Ok(value);
+ if precision > DECIMAL128_MAX_PRECISION {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "Max precision of a Decimal128 is {}, but got {}",
+ DECIMAL128_MAX_PRECISION, precision,
+ )));
}
let max = MAX_DECIMAL_FOR_EACH_PRECISION[precision - 1];
@@ -464,12 +466,12 @@ pub(crate) fn validate_decimal_precision(value: i128, precision: usize) -> Resul
if value > max {
Err(ArrowError::InvalidArgumentError(format!(
- "{} is too large to store in a Decimal of precision {}. Max is {}",
+ "{} is too large to store in a Decimal128 of precision {}. Max is {}",
value, precision, max
)))
} else if value < min {
Err(ArrowError::InvalidArgumentError(format!(
- "{} is too small to store in a Decimal of precision {}. Min is {}",
+ "{} is too small to store in a Decimal128 of precision {}. Min is {}",
value, precision, min
)))
} else {