sea_query_rusqlite/
lib.rs

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