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}