sea_query_sqlite/
lib.rs

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