From 5af433392be3d48fe77d71fff95c74c8b167edba Mon Sep 17 00:00:00 2001 From: Piotr Findeisen Date: Fri, 13 Dec 2024 13:06:49 +0100 Subject: [PATCH] Update to bigdecimal 0.4.7 (#13747) * Add big decimal formatting test cases with potential trailing zeros * Rename and simplify decimal rendering functions - add `decimal` to function name - drop `precision` parameter as it is not supposed to affect the result * Update to bigdecimal 0.4.7 Utilize new `to_plain_string` function --- Cargo.toml | 2 +- .../sqllogictest/src/engines/conversion.rs | 57 ++++++++++--------- .../engines/datafusion_engine/normalize.rs | 8 +-- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0c76ff196a10..cc94b4292a50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,7 +93,7 @@ arrow-ipc = { version = "53.3.0", default-features = false, features = [ arrow-ord = { version = "53.3.0", default-features = false } arrow-schema = { version = "53.3.0", default-features = false } async-trait = "0.1.73" -bigdecimal = "0.4.6" +bigdecimal = "0.4.7" bytes = "1.4" chrono = { version = "0.4.38", default-features = false } ctor = "0.2.0" diff --git a/datafusion/sqllogictest/src/engines/conversion.rs b/datafusion/sqllogictest/src/engines/conversion.rs index 8d2fd1e6d0f2..516ec69e0b07 100644 --- a/datafusion/sqllogictest/src/engines/conversion.rs +++ b/datafusion/sqllogictest/src/engines/conversion.rs @@ -81,16 +81,18 @@ pub(crate) fn f64_to_str(value: f64) -> String { } } -pub(crate) fn i128_to_str(value: i128, precision: &u8, scale: &i8) -> String { +pub(crate) fn decimal_128_to_str(value: i128, scale: i8) -> String { + let precision = u8::MAX; // does not matter big_decimal_to_str( - BigDecimal::from_str(&Decimal128Type::format_decimal(value, *precision, *scale)) + BigDecimal::from_str(&Decimal128Type::format_decimal(value, precision, scale)) .unwrap(), ) } -pub(crate) fn i256_to_str(value: i256, precision: &u8, scale: &i8) -> String { +pub(crate) fn decimal_256_to_str(value: i256, scale: i8) -> String { + let precision = u8::MAX; // does not matter big_decimal_to_str( - BigDecimal::from_str(&Decimal256Type::format_decimal(value, *precision, *scale)) + BigDecimal::from_str(&Decimal256Type::format_decimal(value, precision, scale)) .unwrap(), ) } @@ -104,30 +106,7 @@ pub(crate) fn big_decimal_to_str(value: BigDecimal) -> String { // Round the value to limit the number of decimal places let value = value.round(12).normalized(); // Format the value to a string - format_big_decimal(value) -} - -fn format_big_decimal(value: BigDecimal) -> String { - let (integer, scale) = value.into_bigint_and_exponent(); - let mut str = integer.to_str_radix(10); - if scale <= 0 { - // Append zeros to the right of the integer part - str.extend(std::iter::repeat('0').take(scale.unsigned_abs() as usize)); - str - } else { - let (sign, unsigned_len, unsigned_str) = if integer.is_negative() { - ("-", str.len() - 1, &str[1..]) - } else { - ("", str.len(), &str[..]) - }; - let scale = scale as usize; - if unsigned_len <= scale { - format!("{}0.{:0>scale$}", sign, unsigned_str) - } else { - str.insert(str.len() - scale, '.'); - str - } - } + value.to_plain_string() } #[cfg(test)] @@ -149,19 +128,41 @@ mod tests { #[test] fn test_big_decimal_to_str() { + assert_decimal_str_eq!(110, 3, "0.11"); assert_decimal_str_eq!(11, 3, "0.011"); assert_decimal_str_eq!(11, 2, "0.11"); assert_decimal_str_eq!(11, 1, "1.1"); assert_decimal_str_eq!(11, 0, "11"); assert_decimal_str_eq!(11, -1, "110"); assert_decimal_str_eq!(0, 0, "0"); + assert_decimal_str_eq!( + 12345678901234567890123456789012345678_i128, + 0, + "12345678901234567890123456789012345678" + ); + assert_decimal_str_eq!( + 12345678901234567890123456789012345678_i128, + 38, + "0.123456789012" + ); // Negative cases + assert_decimal_str_eq!(-110, 3, "-0.11"); assert_decimal_str_eq!(-11, 3, "-0.011"); assert_decimal_str_eq!(-11, 2, "-0.11"); assert_decimal_str_eq!(-11, 1, "-1.1"); assert_decimal_str_eq!(-11, 0, "-11"); assert_decimal_str_eq!(-11, -1, "-110"); + assert_decimal_str_eq!( + -12345678901234567890123456789012345678_i128, + 0, + "-12345678901234567890123456789012345678" + ); + assert_decimal_str_eq!( + -12345678901234567890123456789012345678_i128, + 38, + "-0.123456789012" + ); // Round to 12 decimal places // 1.0000000000011 -> 1.000000000001 diff --git a/datafusion/sqllogictest/src/engines/datafusion_engine/normalize.rs b/datafusion/sqllogictest/src/engines/datafusion_engine/normalize.rs index 4146c7cf8010..b80f0ef075ff 100644 --- a/datafusion/sqllogictest/src/engines/datafusion_engine/normalize.rs +++ b/datafusion/sqllogictest/src/engines/datafusion_engine/normalize.rs @@ -213,13 +213,13 @@ pub fn cell_to_string(col: &ArrayRef, row: usize) -> Result { DataType::Float64 => { Ok(f64_to_str(get_row_value!(array::Float64Array, col, row))) } - DataType::Decimal128(precision, scale) => { + DataType::Decimal128(_, scale) => { let value = get_row_value!(array::Decimal128Array, col, row); - Ok(i128_to_str(value, precision, scale)) + Ok(decimal_128_to_str(value, *scale)) } - DataType::Decimal256(precision, scale) => { + DataType::Decimal256(_, scale) => { let value = get_row_value!(array::Decimal256Array, col, row); - Ok(i256_to_str(value, precision, scale)) + Ok(decimal_256_to_str(value, *scale)) } DataType::LargeUtf8 => Ok(varchar_to_str(get_row_value!( array::LargeStringArray,