Skip to content

Commit 8b382e9

Browse files
committed
[FIX] try removing f64 to convert decimal to string
1 parent a5bfbb9 commit 8b382e9

File tree

1 file changed

+54
-21
lines changed

1 file changed

+54
-21
lines changed

parquet-variant/src/to_json.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,55 @@ pub fn variant_to_json(json_buffer: &mut impl Write, variant: &Variant) -> Resul
8181
write!(json_buffer, "{}", f)?;
8282
}
8383
Variant::Decimal4 { integer, scale } => {
84-
// Convert decimal to string representation
85-
let divisor = 10_i32.pow(*scale as u32);
86-
let decimal_value = *integer as f64 / divisor as f64;
87-
write!(json_buffer, "{}", decimal_value)?;
84+
// Convert decimal to string representation using integer arithmetic
85+
if *scale == 0 {
86+
write!(json_buffer, "{}", integer)?;
87+
} else {
88+
let divisor = 10_i32.pow(*scale as u32);
89+
let quotient = integer / divisor;
90+
let remainder = (integer % divisor).abs();
91+
let formatted_remainder = format!("{:0width$}", remainder, width = *scale as usize);
92+
let trimmed_remainder = formatted_remainder.trim_end_matches('0');
93+
if trimmed_remainder.is_empty() {
94+
write!(json_buffer, "{}", quotient)?;
95+
} else {
96+
write!(json_buffer, "{}.{}", quotient, trimmed_remainder)?;
97+
}
98+
}
8899
}
89100
Variant::Decimal8 { integer, scale } => {
90-
// Convert decimal to string representation
91-
let divisor = 10_i64.pow(*scale as u32);
92-
let decimal_value = *integer as f64 / divisor as f64;
93-
write!(json_buffer, "{}", decimal_value)?;
101+
// Convert decimal to string representation using integer arithmetic
102+
if *scale == 0 {
103+
write!(json_buffer, "{}", integer)?;
104+
} else {
105+
let divisor = 10_i64.pow(*scale as u32);
106+
let quotient = integer / divisor;
107+
let remainder = (integer % divisor).abs();
108+
let formatted_remainder = format!("{:0width$}", remainder, width = *scale as usize);
109+
let trimmed_remainder = formatted_remainder.trim_end_matches('0');
110+
if trimmed_remainder.is_empty() {
111+
write!(json_buffer, "{}", quotient)?;
112+
} else {
113+
write!(json_buffer, "{}.{}", quotient, trimmed_remainder)?;
114+
}
115+
}
94116
}
95117
Variant::Decimal16 { integer, scale } => {
96-
// Convert decimal to string representation
97-
let divisor = 10_i128.pow(*scale as u32);
98-
let decimal_value = *integer as f64 / divisor as f64;
99-
write!(json_buffer, "{}", decimal_value)?;
118+
// Convert decimal to string representation using integer arithmetic
119+
if *scale == 0 {
120+
write!(json_buffer, "{}", integer)?;
121+
} else {
122+
let divisor = 10_i128.pow(*scale as u32);
123+
let quotient = integer / divisor;
124+
let remainder = (integer % divisor).abs();
125+
let formatted_remainder = format!("{:0width$}", remainder, width = *scale as usize);
126+
let trimmed_remainder = formatted_remainder.trim_end_matches('0');
127+
if trimmed_remainder.is_empty() {
128+
write!(json_buffer, "{}", quotient)?;
129+
} else {
130+
write!(json_buffer, "{}.{}", quotient, trimmed_remainder)?;
131+
}
132+
}
100133
}
101134
Variant::Date(date) => {
102135
write!(json_buffer, "\"{}\"", date.format("%Y-%m-%d"))?;
@@ -252,30 +285,30 @@ pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
252285
.map(Value::Number)
253286
.ok_or_else(|| ArrowError::InvalidArgumentError("Invalid double value".to_string())),
254287
Variant::Decimal4 { integer, scale } => {
255-
let divisor = 10_i32.pow(*scale as u32);
256-
let decimal_value = *integer as f64 / divisor as f64;
288+
let divisor = 10_i32.pow(*scale as u32);
289+
let decimal_value = *integer as f64 / divisor as f64;
257290
serde_json::Number::from_f64(decimal_value)
258291
.map(Value::Number)
259292
.ok_or_else(|| {
260-
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
293+
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
261294
})
262295
}
263296
Variant::Decimal8 { integer, scale } => {
264-
let divisor = 10_i64.pow(*scale as u32);
265-
let decimal_value = *integer as f64 / divisor as f64;
297+
let divisor = 10_i64.pow(*scale as u32);
298+
let decimal_value = *integer as f64 / divisor as f64;
266299
serde_json::Number::from_f64(decimal_value)
267300
.map(Value::Number)
268301
.ok_or_else(|| {
269-
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
302+
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
270303
})
271304
}
272305
Variant::Decimal16 { integer, scale } => {
273-
let divisor = 10_i128.pow(*scale as u32);
274-
let decimal_value = *integer as f64 / divisor as f64;
306+
let divisor = 10_i128.pow(*scale as u32);
307+
let decimal_value = *integer as f64 / divisor as f64;
275308
serde_json::Number::from_f64(decimal_value)
276309
.map(Value::Number)
277310
.ok_or_else(|| {
278-
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
311+
ArrowError::InvalidArgumentError("Invalid decimal value".to_string())
279312
})
280313
}
281314
Variant::Date(date) => Ok(Value::String(date.format("%Y-%m-%d").to_string())),

0 commit comments

Comments
 (0)