Skip to content

Commit 080cd75

Browse files
committed
fix decoding of the sql DECIMAL type: integers and floats are now handled separately
we used to decode all decimals as floats
1 parent f85b792 commit 080cd75

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

Cargo.lock

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ sqlx = { package = "sqlx-oldapi", git = "https://github.com/sqlpage/sqlx-oldapi"
2828
"mssql",
2929
"odbc",
3030
"chrono",
31+
"bigdecimal",
3132
"json",
3233
"uuid",
3334
] }
@@ -52,6 +53,7 @@ sqlparser = { version = "0.59.0", default-features = false, features = [
5253
async-stream = "0.3"
5354
async-trait = "0.1.61"
5455
async-recursion = "1.0.0"
56+
bigdecimal = "0.4.8"
5557
include_dir = "0.7.2"
5658
config = { version = "0.15.4", features = ["json"] }
5759
markdown = { version = "1.0.0-alpha.23", features = ["log"] }

src/webserver/database/sql_to_json.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::utils::add_value_to_map;
22
use crate::webserver::database::blob_to_data_url;
3+
use bigdecimal::{BigDecimal, ToPrimitive};
34
use chrono::{DateTime, FixedOffset, NaiveDateTime};
45
use serde_json::{self, Map, Value};
56
use sqlx::any::{AnyRow, AnyTypeInfo, AnyTypeInfoKind};
@@ -61,8 +62,18 @@ pub fn sql_nonnull_to_json<'r>(mut get_ref: impl FnMut() -> sqlx::any::AnyValueR
6162
log::trace!("Decoding a value of type {type_name:?} (type info: {type_info:?})");
6263
let AnyTypeInfo(ref db_type) = *type_info;
6364
match type_name {
64-
"REAL" | "FLOAT" | "FLOAT4" | "FLOAT8" | "DOUBLE" | "NUMERIC" | "DECIMAL" => {
65-
decode_raw::<f64>(raw_value).into()
65+
"REAL" | "FLOAT" | "FLOAT4" | "FLOAT8" | "DOUBLE" => decode_raw::<f64>(raw_value).into(),
66+
"NUMERIC" | "DECIMAL" => {
67+
let decimal = decode_raw::<BigDecimal>(raw_value);
68+
if decimal.is_integer() {
69+
if let Some(int) = decimal.to_i64() {
70+
return int.into();
71+
}
72+
}
73+
if let Some(float) = decimal.to_f64() {
74+
return float.into();
75+
}
76+
decimal.to_string().into()
6677
}
6778
"INT8" | "BIGINT" | "SERIAL8" | "BIGSERIAL" | "IDENTITY" | "INT64" | "INTEGER8"
6879
| "BIGINT SIGNED" => decode_raw::<i64>(raw_value).into(),

0 commit comments

Comments
 (0)