Skip to content

Commit acc2c7d

Browse files
authored
chore(deps): update bigdecimal from 0.4.1 to 0.4.6 (#13569)
1 parent 61083f3 commit acc2c7d

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ arrow-ipc = { version = "53.3.0", default-features = false, features = [
9292
arrow-ord = { version = "53.3.0", default-features = false }
9393
arrow-schema = { version = "53.3.0", default-features = false }
9494
async-trait = "0.1.73"
95-
bigdecimal = "=0.4.1"
95+
bigdecimal = "0.4.6"
9696
bytes = "1.4"
9797
chrono = { version = "0.4.38", default-features = false }
9898
ctor = "0.2.0"

datafusion/sqllogictest/src/engines/conversion.rs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,70 @@ pub(crate) fn decimal_to_str(value: Decimal) -> String {
101101
}
102102

103103
pub(crate) fn big_decimal_to_str(value: BigDecimal) -> String {
104-
value.round(12).normalized().to_string()
104+
// Round the value to limit the number of decimal places
105+
let value = value.round(12).normalized();
106+
// Format the value to a string
107+
format_big_decimal(value)
108+
}
109+
110+
fn format_big_decimal(value: BigDecimal) -> String {
111+
let (integer, scale) = value.into_bigint_and_exponent();
112+
let mut str = integer.to_str_radix(10);
113+
if scale <= 0 {
114+
// Append zeros to the right of the integer part
115+
str.extend(std::iter::repeat('0').take(scale.unsigned_abs() as usize));
116+
str
117+
} else {
118+
let (sign, unsigned_len, unsigned_str) = if integer.is_negative() {
119+
("-", str.len() - 1, &str[1..])
120+
} else {
121+
("", str.len(), &str[..])
122+
};
123+
let scale = scale as usize;
124+
if unsigned_len <= scale {
125+
format!("{}0.{:0>scale$}", sign, unsigned_str)
126+
} else {
127+
str.insert(str.len() - scale, '.');
128+
str
129+
}
130+
}
131+
}
132+
133+
#[cfg(test)]
134+
mod tests {
135+
use super::big_decimal_to_str;
136+
use bigdecimal::{num_bigint::BigInt, BigDecimal};
137+
138+
macro_rules! assert_decimal_str_eq {
139+
($integer:expr, $scale:expr, $expected:expr) => {
140+
assert_eq!(
141+
big_decimal_to_str(BigDecimal::from_bigint(
142+
BigInt::from($integer),
143+
$scale
144+
)),
145+
$expected
146+
);
147+
};
148+
}
149+
150+
#[test]
151+
fn test_big_decimal_to_str() {
152+
assert_decimal_str_eq!(11, 3, "0.011");
153+
assert_decimal_str_eq!(11, 2, "0.11");
154+
assert_decimal_str_eq!(11, 1, "1.1");
155+
assert_decimal_str_eq!(11, 0, "11");
156+
assert_decimal_str_eq!(11, -1, "110");
157+
assert_decimal_str_eq!(0, 0, "0");
158+
159+
// Negative cases
160+
assert_decimal_str_eq!(-11, 3, "-0.011");
161+
assert_decimal_str_eq!(-11, 2, "-0.11");
162+
assert_decimal_str_eq!(-11, 1, "-1.1");
163+
assert_decimal_str_eq!(-11, 0, "-11");
164+
assert_decimal_str_eq!(-11, -1, "-110");
165+
166+
// Round to 12 decimal places
167+
// 1.0000000000011 -> 1.000000000001
168+
assert_decimal_str_eq!(10_i128.pow(13) + 11, 13, "1.000000000001");
169+
}
105170
}

0 commit comments

Comments
 (0)