You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2023/11/28 10:12:38 UTC
(arrow-rs) branch master updated: Fix negative decimal string (#5128)
This is an automated email from the ASF dual-hosted git repository.
tustvold 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 8a0b5cb252 Fix negative decimal string (#5128)
8a0b5cb252 is described below
commit 8a0b5cb25205a357c5f17a8af40e45019121c483
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Tue Nov 28 02:12:32 2023 -0800
Fix negative decimal string (#5128)
* Fix negative cases
* Fix
* Fix
* Fix clippy
* Update arrow-cast/src/cast.rs
Co-authored-by: Raphael Taylor-Davies <17...@users.noreply.github.com>
* Update arrow-cast/src/cast.rs
Co-authored-by: Raphael Taylor-Davies <17...@users.noreply.github.com>
---------
Co-authored-by: Raphael Taylor-Davies <17...@users.noreply.github.com>
---
arrow-cast/src/cast.rs | 90 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 88 insertions(+), 2 deletions(-)
diff --git a/arrow-cast/src/cast.rs b/arrow-cast/src/cast.rs
index 38b9fb4c34..8facb4f161 100644
--- a/arrow-cast/src/cast.rs
+++ b/arrow-cast/src/cast.rs
@@ -2596,11 +2596,33 @@ where
)));
}
- let integers = parts[0].trim_start_matches('0');
+ let (negative, first_part) = if parts[0].is_empty() {
+ (false, parts[0])
+ } else {
+ match parts[0].as_bytes()[0] {
+ b'-' => (true, &parts[0][1..]),
+ b'+' => (false, &parts[0][1..]),
+ _ => (false, parts[0]),
+ }
+ };
+
+ let integers = first_part.trim_start_matches('0');
let decimals = if parts.len() == 2 { parts[1] } else { "" };
+ if !integers.is_empty() && !integers.as_bytes()[0].is_ascii_digit() {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "Invalid decimal format: {value_str:?}"
+ )));
+ }
+
+ if !decimals.is_empty() && !decimals.as_bytes()[0].is_ascii_digit() {
+ return Err(ArrowError::InvalidArgumentError(format!(
+ "Invalid decimal format: {value_str:?}"
+ )));
+ }
+
// Adjust decimal based on scale
- let number_decimals = if decimals.len() > scale {
+ let mut number_decimals = if decimals.len() > scale {
let decimal_number = i256::from_string(decimals).ok_or_else(|| {
ArrowError::InvalidArgumentError(format!("Cannot parse decimal format: {value_str}"))
})?;
@@ -2640,6 +2662,10 @@ where
format!("{integers}{decimals}")
};
+ if negative {
+ number_decimals.insert(0, '-');
+ }
+
let value = i256::from_string(number_decimals.as_str()).ok_or_else(|| {
ArrowError::InvalidArgumentError(format!(
"Cannot convert {} to {}: Overflow",
@@ -8256,6 +8282,21 @@ mod tests {
assert_eq!("0.00", decimal_arr.value_as_string(10));
assert_eq!("0.00", decimal_arr.value_as_string(11));
assert!(decimal_arr.is_null(12));
+ assert_eq!("-1.23", decimal_arr.value_as_string(13));
+ assert_eq!("-1.24", decimal_arr.value_as_string(14));
+ assert_eq!("0.00", decimal_arr.value_as_string(15));
+ assert_eq!("-123.00", decimal_arr.value_as_string(16));
+ assert_eq!("-123.23", decimal_arr.value_as_string(17));
+ assert_eq!("-0.12", decimal_arr.value_as_string(18));
+ assert_eq!("1.23", decimal_arr.value_as_string(19));
+ assert_eq!("1.24", decimal_arr.value_as_string(20));
+ assert_eq!("0.00", decimal_arr.value_as_string(21));
+ assert_eq!("123.00", decimal_arr.value_as_string(22));
+ assert_eq!("123.23", decimal_arr.value_as_string(23));
+ assert_eq!("0.12", decimal_arr.value_as_string(24));
+ assert!(decimal_arr.is_null(25));
+ assert!(decimal_arr.is_null(26));
+ assert!(decimal_arr.is_null(27));
// Decimal256
let output_type = DataType::Decimal256(76, 3);
@@ -8277,6 +8318,21 @@ mod tests {
assert_eq!("0.000", decimal_arr.value_as_string(10));
assert_eq!("0.000", decimal_arr.value_as_string(11));
assert!(decimal_arr.is_null(12));
+ assert_eq!("-1.235", decimal_arr.value_as_string(13));
+ assert_eq!("-1.236", decimal_arr.value_as_string(14));
+ assert_eq!("0.000", decimal_arr.value_as_string(15));
+ assert_eq!("-123.000", decimal_arr.value_as_string(16));
+ assert_eq!("-123.234", decimal_arr.value_as_string(17));
+ assert_eq!("-0.123", decimal_arr.value_as_string(18));
+ assert_eq!("1.235", decimal_arr.value_as_string(19));
+ assert_eq!("1.236", decimal_arr.value_as_string(20));
+ assert_eq!("0.000", decimal_arr.value_as_string(21));
+ assert_eq!("123.000", decimal_arr.value_as_string(22));
+ assert_eq!("123.234", decimal_arr.value_as_string(23));
+ assert_eq!("0.123", decimal_arr.value_as_string(24));
+ assert!(decimal_arr.is_null(25));
+ assert!(decimal_arr.is_null(26));
+ assert!(decimal_arr.is_null(27));
}
#[test]
@@ -8295,6 +8351,21 @@ mod tests {
Some(""),
Some(" "),
None,
+ Some("-1.23499999"),
+ Some("-1.23599999"),
+ Some("-0.00001"),
+ Some("-123"),
+ Some("-123.234000"),
+ Some("-000.123"),
+ Some("+1.23499999"),
+ Some("+1.23599999"),
+ Some("+0.00001"),
+ Some("+123"),
+ Some("+123.234000"),
+ Some("+000.123"),
+ Some("1.-23499999"),
+ Some("-1.-23499999"),
+ Some("--1.23499999"),
]);
let array = Arc::new(str_array) as ArrayRef;
@@ -8317,6 +8388,21 @@ mod tests {
Some(""),
Some(" "),
None,
+ Some("-1.23499999"),
+ Some("-1.23599999"),
+ Some("-0.00001"),
+ Some("-123"),
+ Some("-123.234000"),
+ Some("-000.123"),
+ Some("+1.23499999"),
+ Some("+1.23599999"),
+ Some("+0.00001"),
+ Some("+123"),
+ Some("+123.234000"),
+ Some("+000.123"),
+ Some("1.-23499999"),
+ Some("-1.-23499999"),
+ Some("--1.23499999"),
]);
let array = Arc::new(str_array) as ArrayRef;