Skip to content

Commit

Permalink
add checker for appending i128 to decimal builder (#928) (#943)
Browse files Browse the repository at this point in the history
* add check for appending i128 to decimal builder

* remove the ArrowError(DecimalError)

Co-authored-by: Kun Liu <liukun@apache.org>
  • Loading branch information
alamb and liukun4515 committed Nov 12, 2021
1 parent dff1411 commit 320de1c
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 1 deletion.
35 changes: 34 additions & 1 deletion arrow/src/array/array_binary.rs
Expand Up @@ -1286,9 +1286,42 @@ mod tests {
assert_eq!(16, decimal_array.value_length());
}

#[test]
fn test_decimal_append_error_value() {
let mut decimal_builder = DecimalBuilder::new(10, 5, 3);
let mut result = decimal_builder.append_value(123456);
let mut error = result.unwrap_err();
assert_eq!(
"Invalid argument error: The value of 123456 i128 is not compatible with Decimal(5,3)",
error.to_string()
);
decimal_builder.append_value(12345).unwrap();
let arr = decimal_builder.finish();
assert_eq!("12.345", arr.value_as_string(0));

decimal_builder = DecimalBuilder::new(10, 2, 1);
result = decimal_builder.append_value(100);
error = result.unwrap_err();
assert_eq!(
"Invalid argument error: The value of 100 i128 is not compatible with Decimal(2,1)",
error.to_string()
);
decimal_builder.append_value(99).unwrap();
result = decimal_builder.append_value(-100);
error = result.unwrap_err();
assert_eq!(
"Invalid argument error: The value of -100 i128 is not compatible with Decimal(2,1)",
error.to_string()
);
decimal_builder.append_value(-99).unwrap();
let arr = decimal_builder.finish();
assert_eq!("9.9", arr.value_as_string(0));
assert_eq!("-9.9", arr.value_as_string(1));
}

#[test]
fn test_decimal_array_value_as_string() {
let mut decimal_builder = DecimalBuilder::new(7, 5, 3);
let mut decimal_builder = DecimalBuilder::new(7, 6, 3);
for value in [123450, -123450, 100, -100, 10, -10, 0] {
decimal_builder.append_value(value).unwrap();
}
Expand Down
89 changes: 89 additions & 0 deletions arrow/src/array/builder.rs
Expand Up @@ -1118,6 +1118,87 @@ pub struct FixedSizeBinaryBuilder {
builder: FixedSizeListBuilder<UInt8Builder>,
}

const MAX_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [
9,
99,
999,
9999,
99999,
999999,
9999999,
99999999,
999999999,
9999999999,
99999999999,
999999999999,
9999999999999,
99999999999999,
999999999999999,
9999999999999999,
99999999999999999,
999999999999999999,
9999999999999999999,
99999999999999999999,
999999999999999999999,
9999999999999999999999,
99999999999999999999999,
999999999999999999999999,
9999999999999999999999999,
99999999999999999999999999,
999999999999999999999999999,
9999999999999999999999999999,
99999999999999999999999999999,
999999999999999999999999999999,
9999999999999999999999999999999,
99999999999999999999999999999999,
999999999999999999999999999999999,
9999999999999999999999999999999999,
99999999999999999999999999999999999,
999999999999999999999999999999999999,
9999999999999999999999999999999999999,
170141183460469231731687303715884105727,
];
const MIN_DECIMAL_FOR_EACH_PRECISION: [i128; 38] = [
-9,
-99,
-999,
-9999,
-99999,
-999999,
-9999999,
-99999999,
-999999999,
-9999999999,
-99999999999,
-999999999999,
-9999999999999,
-99999999999999,
-999999999999999,
-9999999999999999,
-99999999999999999,
-999999999999999999,
-9999999999999999999,
-99999999999999999999,
-999999999999999999999,
-9999999999999999999999,
-99999999999999999999999,
-999999999999999999999999,
-9999999999999999999999999,
-99999999999999999999999999,
-999999999999999999999999999,
-9999999999999999999999999999,
-99999999999999999999999999999,
-999999999999999999999999999999,
-9999999999999999999999999999999,
-99999999999999999999999999999999,
-999999999999999999999999999999999,
-9999999999999999999999999999999999,
-99999999999999999999999999999999999,
-999999999999999999999999999999999999,
-9999999999999999999999999999999999999,
-170141183460469231731687303715884105728,
];

///
/// Array Builder for [`DecimalArray`]
///
Expand Down Expand Up @@ -1431,6 +1512,14 @@ impl DecimalBuilder {
/// distinct array element.
#[inline]
pub fn append_value(&mut self, value: i128) -> Result<()> {
if value > MAX_DECIMAL_FOR_EACH_PRECISION[self.precision - 1]
|| value < MIN_DECIMAL_FOR_EACH_PRECISION[self.precision - 1]
{
return Err(ArrowError::InvalidArgumentError(format!(
"The value of {} i128 is not compatible with Decimal({},{})",
value, self.precision, self.scale
)));
}
let value_as_bytes = Self::from_i128_to_fixed_size_bytes(
value,
self.builder.value_length() as usize,
Expand Down

0 comments on commit 320de1c

Please sign in to comment.