diesel/sqlite/types/
numeric.rs1#[cfg(feature = "numeric")]
2mod bigdecimal {
3 use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
4
5 use crate::deserialize::{self, FromSql};
6 use crate::serialize::{self, IsNull, Output, ToSql};
7 use crate::sql_types::{Double, Numeric};
8 use crate::sqlite::connection::SqliteValue;
9 use crate::sqlite::Sqlite;
10
11 #[cfg(all(feature = "sqlite", feature = "numeric"))]
12 impl ToSql<Numeric, Sqlite> for BigDecimal {
13 fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Sqlite>) -> serialize::Result {
14 let x = self
15 .to_f64()
16 .ok_or_else(|| format!("{self} is not representable as an f64"))?;
17 out.set_value(x);
18 Ok(IsNull::No)
19 }
20 }
21
22 #[cfg(all(feature = "sqlite", feature = "numeric"))]
23 impl FromSql<Numeric, Sqlite> for BigDecimal {
24 fn from_sql(bytes: SqliteValue<'_, '_, '_>) -> deserialize::Result<Self> {
25 let x = <f64 as FromSql<Double, Sqlite>>::from_sql(bytes)?;
26 BigDecimal::from_f64(x)
27 .ok_or_else(|| format!("{x} is not valid decimal number ").into())
28 }
29 }
30
31 #[cfg(test)]
32 mod tests {
33 use crate::prelude::*;
34 use bigdecimal::{BigDecimal, ToPrimitive};
35
36 table! {
37 bigdecimal_test {
38 id -> Integer,
39 value -> BigInt,
40 }
41 }
42
43 #[test]
44 fn sum_bigdecimal_to_i64() {
45 use self::bigdecimal_test::dsl::*;
46
47 let connection = &mut SqliteConnection::establish(":memory:").unwrap();
48 crate::sql_query(
49 "CREATE TABLE bigdecimal_test (id integer primary key autoincrement, value integer)",
50 )
51 .execute(connection)
52 .unwrap();
53 crate::sql_query("INSERT INTO bigdecimal_test (value) VALUES (14), (14), (14)")
54 .execute(connection)
55 .unwrap();
56
57 let result: Option<BigDecimal> = bigdecimal_test
58 .select(crate::dsl::sum(value))
59 .first(connection)
60 .expect("Summed result");
61
62 let result = match result.map(|r| r.to_i64()) {
63 Some(Some(r)) => r,
64 Some(None) => i64::MAX,
65 None => 0,
66 };
67
68 assert_eq!(42i64, result);
69 }
70
71 #[test]
72 fn sum_bigdecimal_to_f64() {
73 use self::bigdecimal_test::dsl::*;
74
75 let connection = &mut SqliteConnection::establish(":memory:").unwrap();
76 crate::sql_query(
77 "CREATE TABLE bigdecimal_test (id integer primary key autoincrement, value numeric)",
78 )
79 .execute(connection)
80 .unwrap();
81 crate::sql_query(
82 "INSERT INTO bigdecimal_test (value) VALUES (14.14), (14.14), (14.14)",
83 )
84 .execute(connection)
85 .unwrap();
86
87 let result: Option<BigDecimal> = bigdecimal_test
88 .select(crate::dsl::sum(value))
89 .first(connection)
90 .expect("Summed result");
91
92 let result = match result.map(|r| r.to_f64()) {
93 Some(Some(r)) => r,
94 Some(None) => f64::MAX,
95 None => 0.0,
96 };
97
98 assert_eq!(42.42f64, result);
99 }
100 }
101}