Skip to content

Commit

Permalink
fix(relationJoins): decimal values should not suffer precision loss (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Weakky committed Mar 22, 2024
1 parent 8aaab74 commit ff01c8c
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 20 deletions.
5 changes: 3 additions & 2 deletions quaint/src/connector/sqlite/native/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,10 @@ impl<'a> GetRow for SqliteRow<'a> {
}
}
ValueRef::Real(f) if column.is_real() => {
use bigdecimal::{BigDecimal, FromPrimitive};
use bigdecimal::BigDecimal;
use std::str::FromStr;

Value::numeric(BigDecimal::from_f64(f).unwrap())
Value::numeric(BigDecimal::from_str(&f.to_string()).unwrap())
}
ValueRef::Real(f) => Value::double(f),
ValueRef::Text(bytes) if column.is_datetime() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,20 +186,21 @@ mod scalar_relations {
create_child(&runner, r#"{ childId: 1, dec: "1" }"#).await?;
create_child(&runner, r#"{ childId: 2, dec: "-1" }"#).await?;
create_child(&runner, r#"{ childId: 3, dec: "123.45678910" }"#).await?;
create_child(&runner, r#"{ childId: 4, dec: "95993.57" }"#).await?;
create_parent(
&runner,
r#"{ id: 1, children: { connect: [{ childId: 1 }, { childId: 2 }, { childId: 3 }] } }"#,
r#"{ id: 1, children: { connect: [{ childId: 1 }, { childId: 2 }, { childId: 3 }, { childId: 4 }] } }"#,
)
.await?;

insta::assert_snapshot!(
run_query!(&runner, r#"{ findManyParent(orderBy: { id: asc }) { id children { childId dec } } }"#),
@r###"{"data":{"findManyParent":[{"id":1,"children":[{"childId":1,"dec":"1"},{"childId":2,"dec":"-1"},{"childId":3,"dec":"123.4567891"}]}]}}"###
@r###"{"data":{"findManyParent":[{"id":1,"children":[{"childId":1,"dec":"1"},{"childId":2,"dec":"-1"},{"childId":3,"dec":"123.4567891"},{"childId":4,"dec":"95993.57"}]}]}}"###
);

insta::assert_snapshot!(
run_query!(&runner, r#"{ findUniqueParent(where: { id: 1 }) { id children { childId dec } } }"#),
@r###"{"data":{"findUniqueParent":{"id":1,"children":[{"childId":1,"dec":"1"},{"childId":2,"dec":"-1"},{"childId":3,"dec":"123.4567891"}]}}}"###
@r###"{"data":{"findUniqueParent":{"id":1,"children":[{"childId":1,"dec":"1"},{"childId":2,"dec":"-1"},{"childId":3,"dec":"123.4567891"},{"childId":4,"dec":"95993.57"}]}}}"###
);

Ok(())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use bigdecimal::{BigDecimal, FromPrimitive, ParseBigDecimalError};
use bigdecimal::{BigDecimal, ParseBigDecimalError};
use itertools::Itertools;
use query_structure::*;
use std::{borrow::Cow, io, str::FromStr};
Expand Down Expand Up @@ -137,13 +137,9 @@ pub(crate) fn coerce_json_scalar_to_pv(value: serde_json::Value, sf: &ScalarFiel
build_conversion_error(sf, &format!("Number({n})"), &format!("{:?}", sf.type_identifier()))
})?)),
TypeIdentifier::Float | TypeIdentifier::Decimal => {
let bd = n
.as_f64()
.and_then(BigDecimal::from_f64)
.map(|bd| bd.normalized())
.ok_or_else(|| {
build_conversion_error(sf, &format!("Number({n})"), &format!("{:?}", sf.type_identifier()))
})?;
let bd = parse_decimal(&n.to_string()).map_err(|_| {
build_conversion_error(sf, &format!("Number({n})"), &format!("{:?}", sf.type_identifier()))
})?;

Ok(PrismaValue::Float(bd))
}
Expand Down
10 changes: 3 additions & 7 deletions query-engine/driver-adapters/src/conversion/js_to_quaint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::str::FromStr;

pub use crate::types::{ColumnType, JSResultSet};
use quaint::bigdecimal::{BigDecimal, FromPrimitive};
use quaint::bigdecimal::BigDecimal;
use quaint::chrono::{DateTime, NaiveDate, NaiveTime, Utc};
use quaint::{
connector::ResultSet as QuaintResultSet,
Expand Down Expand Up @@ -137,12 +137,8 @@ pub fn js_value_to_quaint(
serde_json::Value::String(s) => BigDecimal::from_str(&s).map(QuaintValue::numeric).map_err(|e| {
conversion_error!("invalid numeric value when parsing {s} in column '{column_name}': {e}")
}),
serde_json::Value::Number(n) => n
.as_f64()
.and_then(BigDecimal::from_f64)
.ok_or(conversion_error!(
"number must be an f64 in column '{column_name}', got {n}"
))
serde_json::Value::Number(n) => BigDecimal::from_str(&n.to_string())
.map_err(|_| conversion_error!("number must be an f64 in column '{column_name}', got {n}"))
.map(QuaintValue::numeric),
serde_json::Value::Null => Ok(QuaintValue::null_numeric()),
mismatch => Err(conversion_error!(
Expand Down

0 comments on commit ff01c8c

Please sign in to comment.