chain_builder/
sqlx_bind.rs1use crate::builder::QueryBuilder;
14use crate::dialect::Dialect;
15use crate::value::Value;
16
17#[cfg(feature = "sqlx_mysql")]
18use crate::dialect::MySql;
19#[cfg(feature = "sqlx_postgres")]
20use crate::dialect::Postgres;
21#[cfg(feature = "sqlx_sqlite")]
22use crate::dialect::Sqlite;
23
24pub trait SqlxDialect: Dialect + private::Sealed {
29 type Database: sqlx::Database<Arguments: sqlx::IntoArguments<Self::Database>>;
35
36 fn bind_arguments(binds: &[Value]) -> <Self::Database as sqlx::Database>::Arguments;
42}
43
44mod private {
45 pub trait Sealed {}
47
48 #[cfg(feature = "sqlx_postgres")]
49 impl Sealed for crate::dialect::Postgres {}
50 #[cfg(feature = "sqlx_mysql")]
51 impl Sealed for crate::dialect::MySql {}
52 #[cfg(feature = "sqlx_sqlite")]
53 impl Sealed for crate::dialect::Sqlite {}
54}
55
56#[cfg(feature = "sqlx_postgres")]
57impl SqlxDialect for Postgres {
58 type Database = sqlx::Postgres;
59
60 fn bind_arguments(binds: &[Value]) -> sqlx::postgres::PgArguments {
61 use sqlx::Arguments;
62 let mut arguments = sqlx::postgres::PgArguments::default();
63 for bind in binds {
64 match bind {
66 Value::Null => {
67 let _ = arguments.add(Option::<String>::None);
68 }
69 Value::Bool(b) => {
70 let _ = arguments.add(*b);
71 }
72 Value::I64(i) => {
73 let _ = arguments.add(*i);
74 }
75 Value::F64(f) => {
76 let _ = arguments.add(*f);
77 }
78 Value::Text(s) => {
79 let _ = arguments.add(s.clone());
80 }
81 Value::Bytes(b) => {
82 let _ = arguments.add(b.clone());
83 }
84 #[cfg(feature = "json")]
85 Value::Json(j) => {
86 let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
88 }
89 #[cfg(feature = "uuid")]
90 Value::Uuid(u) => {
91 let _ = arguments.add(*u);
92 }
93 #[cfg(feature = "chrono")]
94 Value::DateTimeUtc(dt) => {
95 let _ = arguments.add(*dt);
96 }
97 #[cfg(feature = "chrono")]
98 Value::NaiveDateTime(dt) => {
99 let _ = arguments.add(*dt);
100 }
101 #[cfg(feature = "chrono")]
102 Value::NaiveDate(d) => {
103 let _ = arguments.add(*d);
104 }
105 #[cfg(feature = "chrono")]
106 Value::NaiveTime(t) => {
107 let _ = arguments.add(*t);
108 }
109 #[cfg(feature = "decimal")]
110 Value::Decimal(d) => {
111 let _ = arguments.add(*d);
113 }
114 }
115 }
116 arguments
117 }
118}
119
120#[cfg(feature = "sqlx_mysql")]
121impl SqlxDialect for MySql {
122 type Database = sqlx::MySql;
123
124 fn bind_arguments(binds: &[Value]) -> sqlx::mysql::MySqlArguments {
125 use sqlx::Arguments;
126 let mut arguments = sqlx::mysql::MySqlArguments::default();
127 for bind in binds {
128 match bind {
130 Value::Null => {
131 let _ = arguments.add(Option::<String>::None);
132 }
133 Value::Bool(b) => {
134 let _ = arguments.add(*b);
135 }
136 Value::I64(i) => {
137 let _ = arguments.add(*i);
138 }
139 Value::F64(f) => {
140 let _ = arguments.add(*f);
141 }
142 Value::Text(s) => {
143 let _ = arguments.add(s.clone());
144 }
145 Value::Bytes(b) => {
146 let _ = arguments.add(b.clone());
147 }
148 #[cfg(feature = "json")]
149 Value::Json(j) => {
150 let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
152 }
153 #[cfg(feature = "uuid")]
154 Value::Uuid(u) => {
155 let _ = arguments.add(*u);
156 }
157 #[cfg(feature = "chrono")]
158 Value::DateTimeUtc(dt) => {
159 let _ = arguments.add(*dt);
160 }
161 #[cfg(feature = "chrono")]
162 Value::NaiveDateTime(dt) => {
163 let _ = arguments.add(*dt);
164 }
165 #[cfg(feature = "chrono")]
166 Value::NaiveDate(d) => {
167 let _ = arguments.add(*d);
168 }
169 #[cfg(feature = "chrono")]
170 Value::NaiveTime(t) => {
171 let _ = arguments.add(*t);
172 }
173 #[cfg(feature = "decimal")]
174 Value::Decimal(d) => {
175 let _ = arguments.add(*d);
177 }
178 }
179 }
180 arguments
181 }
182}
183
184#[cfg(feature = "sqlx_sqlite")]
185impl SqlxDialect for Sqlite {
186 type Database = sqlx::Sqlite;
187
188 fn bind_arguments(binds: &[Value]) -> sqlx::sqlite::SqliteArguments {
189 use sqlx::Arguments;
190 let mut arguments = sqlx::sqlite::SqliteArguments::default();
193 for bind in binds {
194 match bind {
196 Value::Null => {
197 let _ = arguments.add(Option::<String>::None);
198 }
199 Value::Bool(b) => {
200 let _ = arguments.add(*b);
201 }
202 Value::I64(i) => {
203 let _ = arguments.add(*i);
204 }
205 Value::F64(f) => {
206 let _ = arguments.add(*f);
207 }
208 Value::Text(s) => {
209 let _ = arguments.add(s.clone());
210 }
211 Value::Bytes(b) => {
212 let _ = arguments.add(b.clone());
213 }
214 #[cfg(feature = "json")]
215 Value::Json(j) => {
216 let _ = arguments.add(serde_json::to_string(j).unwrap_or_default());
218 }
219 #[cfg(feature = "uuid")]
220 Value::Uuid(u) => {
221 let _ = arguments.add(*u);
222 }
223 #[cfg(feature = "chrono")]
224 Value::DateTimeUtc(dt) => {
225 let _ = arguments.add(*dt);
226 }
227 #[cfg(feature = "chrono")]
228 Value::NaiveDateTime(dt) => {
229 let _ = arguments.add(*dt);
230 }
231 #[cfg(feature = "chrono")]
232 Value::NaiveDate(d) => {
233 let _ = arguments.add(*d);
234 }
235 #[cfg(feature = "chrono")]
236 Value::NaiveTime(t) => {
237 let _ = arguments.add(*t);
238 }
239 #[cfg(feature = "decimal")]
240 Value::Decimal(d) => {
241 let _ = arguments.add(d.to_string());
244 }
245 }
246 }
247 arguments
248 }
249}
250
251pub type SqlxQuery<'q, D> = sqlx::query::Query<
253 'q,
254 <D as SqlxDialect>::Database,
255 <<D as SqlxDialect>::Database as sqlx::Database>::Arguments,
256>;
257
258pub type SqlxQueryAs<'q, D, T> = sqlx::query::QueryAs<
261 'q,
262 <D as SqlxDialect>::Database,
263 T,
264 <<D as SqlxDialect>::Database as sqlx::Database>::Arguments,
265>;
266
267#[cfg(any(
268 feature = "sqlx_postgres",
269 feature = "sqlx_mysql",
270 feature = "sqlx_sqlite"
271))]
272impl<D: SqlxDialect> QueryBuilder<D> {
273 pub fn to_sqlx_query(
281 &self,
282 ) -> sqlx::query::Query<'_, D::Database, <D::Database as sqlx::Database>::Arguments> {
283 let (sql, binds) = self.to_sql();
284 sqlx::query_with(sqlx::AssertSqlSafe(sql), D::bind_arguments(&binds))
285 }
286
287 pub fn try_to_sqlx_query(&self) -> Result<SqlxQuery<'_, D>, crate::BuildError> {
291 let (sql, binds) = self.try_to_sql()?;
292 Ok(sqlx::query_with(
293 sqlx::AssertSqlSafe(sql),
294 D::bind_arguments(&binds),
295 ))
296 }
297
298 pub fn to_sqlx_query_as<T>(
302 &self,
303 ) -> sqlx::query::QueryAs<'_, D::Database, T, <D::Database as sqlx::Database>::Arguments>
304 where
305 T: for<'r> sqlx::FromRow<'r, <D::Database as sqlx::Database>::Row>,
306 {
307 let (sql, binds) = self.to_sql();
308 sqlx::query_as_with(sqlx::AssertSqlSafe(sql), D::bind_arguments(&binds))
309 }
310
311 pub fn try_to_sqlx_query_as<T>(&self) -> Result<SqlxQueryAs<'_, D, T>, crate::BuildError>
315 where
316 T: for<'r> sqlx::FromRow<'r, <D::Database as sqlx::Database>::Row>,
317 {
318 let (sql, binds) = self.try_to_sql()?;
319 Ok(sqlx::query_as_with(
320 sqlx::AssertSqlSafe(sql),
321 D::bind_arguments(&binds),
322 ))
323 }
324}