sea_query_rusqlite/
lib.rs

1use rusqlite::{
2    types::{Null, ToSqlOutput},
3    Result, ToSql,
4};
5use sea_query::Value;
6use sea_query::{query::*, QueryBuilder};
7
8#[derive(Clone, Debug, PartialEq)]
9pub struct RusqliteValue(pub sea_query::Value);
10#[derive(Clone, Debug, PartialEq)]
11pub struct RusqliteValues(pub Vec<RusqliteValue>);
12
13impl RusqliteValues {
14    pub fn as_params(&self) -> Vec<&dyn ToSql> {
15        self.0
16            .iter()
17            .map(|x| {
18                let y: &dyn ToSql = x;
19                y
20            })
21            .collect()
22    }
23}
24
25pub trait RusqliteBinder {
26    fn build_rusqlite<T: QueryBuilder>(&self, query_builder: T) -> (String, RusqliteValues);
27}
28
29macro_rules! impl_rusqlite_binder {
30    ($l:ident) => {
31        impl RusqliteBinder for $l {
32            fn build_rusqlite<T: QueryBuilder>(
33                &self,
34                query_builder: T,
35            ) -> (String, RusqliteValues) {
36                let (query, values) = self.build(query_builder);
37                (
38                    query,
39                    RusqliteValues(values.into_iter().map(RusqliteValue).collect()),
40                )
41            }
42        }
43    };
44}
45
46impl_rusqlite_binder!(SelectStatement);
47impl_rusqlite_binder!(UpdateStatement);
48impl_rusqlite_binder!(InsertStatement);
49impl_rusqlite_binder!(DeleteStatement);
50impl_rusqlite_binder!(WithQuery);
51
52impl ToSql for RusqliteValue {
53    fn to_sql(&self) -> Result<ToSqlOutput<'_>> {
54        macro_rules! box_to_sql {
55            ( $v: expr ) => {
56                match $v {
57                    Some(v) => v.as_ref().to_sql(),
58                    None => Null.to_sql(),
59                }
60            };
61        }
62
63        macro_rules! opt_string_to_sql {
64            ( $v: expr ) => {
65                match $v {
66                    Some(v) => Ok(ToSqlOutput::from(v)),
67                    None => Null.to_sql(),
68                }
69            };
70        }
71
72        match &self.0 {
73            Value::Bool(v) => v.to_sql(),
74            Value::TinyInt(v) => v.to_sql(),
75            Value::SmallInt(v) => v.to_sql(),
76            Value::Int(v) => v.to_sql(),
77            Value::BigInt(v) => v.to_sql(),
78            Value::TinyUnsigned(v) => v.to_sql(),
79            Value::SmallUnsigned(v) => v.to_sql(),
80            Value::Unsigned(v) => v.to_sql(),
81            Value::BigUnsigned(v) => v.to_sql(),
82            Value::Float(v) => v.to_sql(),
83            Value::Double(v) => v.to_sql(),
84            Value::String(v) => box_to_sql!(v),
85            Value::Char(v) => opt_string_to_sql!(v.map(|v| v.to_string())),
86            Value::Bytes(v) => box_to_sql!(v),
87            #[cfg(feature = "with-chrono")]
88            Value::ChronoDate(v) => box_to_sql!(v),
89            #[cfg(feature = "with-chrono")]
90            Value::ChronoTime(v) => box_to_sql!(v),
91            #[cfg(feature = "with-chrono")]
92            Value::ChronoDateTime(v) => box_to_sql!(v),
93            #[cfg(feature = "with-chrono")]
94            Value::ChronoDateTimeUtc(v) => box_to_sql!(v),
95            #[cfg(feature = "with-chrono")]
96            Value::ChronoDateTimeLocal(v) => box_to_sql!(v),
97            #[cfg(feature = "with-chrono")]
98            Value::ChronoDateTimeWithTimeZone(v) => box_to_sql!(v),
99            #[cfg(feature = "with-time")]
100            v @ Value::TimeDate(_) => opt_string_to_sql!(v.time_as_naive_utc_in_string()),
101            #[cfg(feature = "with-time")]
102            v @ Value::TimeTime(_) => opt_string_to_sql!(v.time_as_naive_utc_in_string()),
103            #[cfg(feature = "with-time")]
104            v @ Value::TimeDateTime(_) => opt_string_to_sql!(v.time_as_naive_utc_in_string()),
105            #[cfg(feature = "with-time")]
106            v @ Value::TimeDateTimeWithTimeZone(_) => {
107                opt_string_to_sql!(v.time_as_naive_utc_in_string())
108            }
109            #[cfg(feature = "with-uuid")]
110            Value::Uuid(v) => box_to_sql!(v),
111            #[cfg(feature = "with-json")]
112            Value::Json(j) => box_to_sql!(j),
113            #[cfg(feature = "with-rust_decimal")]
114            Value::Decimal(_) => {
115                panic!("Rusqlite doesn't support rust_decimal arguments");
116            }
117            #[cfg(feature = "with-bigdecimal")]
118            Value::BigDecimal(_) => {
119                panic!("Rusqlite doesn't support bigdecimal arguments");
120            }
121            #[cfg(feature = "with-ipnetwork")]
122            Value::IpNetwork(_) => {
123                panic!("Rusqlite doesn't support IpNetwork arguments");
124            }
125            #[cfg(feature = "with-mac_address")]
126            Value::MacAddress(_) => {
127                panic!("Rusqlite doesn't support MacAddress arguments");
128            }
129            #[cfg(feature = "postgres-array")]
130            Value::Array(_, _) => {
131                panic!("Rusqlite doesn't support Array arguments");
132            }
133            #[cfg(feature = "postgres-vector")]
134            Value::Vector(_) => {
135                panic!("Rusqlite doesn't support Vector arguments");
136            }
137        }
138    }
139}