sea_query_sqlx/
sqlx_postgres.rs1use sqlx::Arguments;
2
3use sea_query::Value;
4#[cfg(all(feature = "with-json", feature = "postgres-array"))]
5use sea_query::prelude::Json;
6#[cfg(feature = "postgres-array")]
7use sea_query::{Array, ArrayType};
8
9use crate::SqlxValues;
10
11impl sqlx::IntoArguments<'_, sqlx::postgres::Postgres> for SqlxValues {
12 fn into_arguments(self) -> sqlx::postgres::PgArguments {
13 let mut args = sqlx::postgres::PgArguments::default();
14 for arg in self.0.into_iter() {
15 match arg {
16 Value::Bool(b) => {
17 let _ = args.add(b);
18 }
19 Value::TinyInt(i) => {
20 let _ = args.add(i);
21 }
22 Value::SmallInt(i) => {
23 let _ = args.add(i);
24 }
25 Value::Int(i) => {
26 let _ = args.add(i);
27 }
28 Value::BigInt(i) => {
29 let _ = args.add(i);
30 }
31 Value::TinyUnsigned(i) => {
32 let _ = args.add(i.map(|i| i as i16));
33 }
34 Value::SmallUnsigned(i) => {
35 let _ = args.add(i.map(|i| i as i32));
36 }
37 Value::Unsigned(i) => {
38 let _ = args.add(i.map(|i| i as i64));
39 }
40 Value::BigUnsigned(i) => {
41 let _ = args.add(i.map(|i| <i64 as TryFrom<u64>>::try_from(i).unwrap()));
42 }
43 Value::Float(f) => {
44 let _ = args.add(f);
45 }
46 Value::Double(d) => {
47 let _ = args.add(d);
48 }
49 Value::String(s) => {
50 let _ = args.add(s.as_deref());
51 }
52 Value::Char(c) => {
53 let _ = args.add(c.map(|c| c.to_string()));
54 }
55 Value::Bytes(b) => {
56 let _ = args.add(b.as_deref());
57 }
58 #[cfg(feature = "with-chrono")]
59 Value::ChronoDate(d) => {
60 let _ = args.add(d);
61 }
62 #[cfg(feature = "with-chrono")]
63 Value::ChronoTime(t) => {
64 let _ = args.add(t);
65 }
66 #[cfg(feature = "with-chrono")]
67 Value::ChronoDateTime(t) => {
68 let _ = args.add(t);
69 }
70 #[cfg(feature = "with-chrono")]
71 Value::ChronoDateTimeUtc(t) => {
72 let _ = args.add(t);
73 }
74 #[cfg(feature = "with-chrono")]
75 Value::ChronoDateTimeLocal(t) => {
76 let _ = args.add(t);
77 }
78 #[cfg(feature = "with-chrono")]
79 Value::ChronoDateTimeWithTimeZone(t) => {
80 let _ = args.add(t);
81 }
82 #[cfg(feature = "with-time")]
83 Value::TimeDate(t) => {
84 let _ = args.add(t);
85 }
86 #[cfg(feature = "with-time")]
87 Value::TimeTime(t) => {
88 let _ = args.add(t);
89 }
90 #[cfg(feature = "with-time")]
91 Value::TimeDateTime(t) => {
92 let _ = args.add(t);
93 }
94 #[cfg(feature = "with-time")]
95 Value::TimeDateTimeWithTimeZone(t) => {
96 let _ = args.add(t);
97 }
98 #[cfg(feature = "with-uuid")]
99 Value::Uuid(uuid) => {
100 let _ = args.add(uuid);
101 }
102 #[cfg(feature = "with-rust_decimal")]
103 Value::Decimal(d) => {
104 let _ = args.add(d);
105 }
106 #[cfg(feature = "with-bigdecimal")]
107 Value::BigDecimal(d) => {
108 let _ = args.add(d.as_ref());
109 }
110 #[cfg(feature = "with-json")]
111 Value::Json(j) => {
112 let _ = args.add(j);
113 }
114 #[cfg(feature = "with-ipnetwork")]
115 Value::IpNetwork(ip) => {
116 let _ = args.add(ip);
117 }
118 #[cfg(feature = "with-mac_address")]
119 Value::MacAddress(mac) => {
120 let _ = args.add(mac);
121 }
122 #[cfg(feature = "with-jiff")]
123 Value::JiffDate(d) => {
124 let _ = args.add(d.map(jiff_sqlx::Date::from));
125 }
126 #[cfg(feature = "with-jiff")]
127 Value::JiffTime(t) => {
128 let _ = args.add(t.map(jiff_sqlx::Time::from));
129 }
130 #[cfg(feature = "with-jiff")]
131 Value::JiffDateTime(dt) => {
132 let _ = args.add(dt.map(jiff_sqlx::DateTime::from));
133 }
134 #[cfg(feature = "with-jiff")]
135 Value::JiffTimestamp(ts) => {
136 let _ = args.add(ts.map(jiff_sqlx::Timestamp::from));
137 }
138 #[cfg(feature = "with-jiff")]
139 Value::JiffZoned(z) => {
140 let _ = args.add(z.map(|z| jiff_sqlx::Timestamp::from(z.timestamp())));
141 }
142 Value::Enum(e) => {
143 let _ = args.add(e.map(|e| e.as_str().to_owned()));
145 }
146 #[cfg(feature = "postgres-array")]
147 Value::Array(arr) => {
148 match_array(arr, &mut args);
149 }
150 #[cfg(feature = "postgres-vector")]
151 Value::Vector(v) => {
152 let _ = args.add(v);
153 }
154 #[cfg(feature = "postgres-range")]
155 Value::Range(r) => {
156 let _ = args.add(r);
157 }
158 }
159 }
160 args
161 }
162}
163
164#[cfg(feature = "postgres-array")]
165fn match_array(arr: Array, args: &mut sqlx::postgres::PgArguments) {
166 match arr {
167 Array::Null(ty) => match_null_array(ty, args),
168 Array::Bool(inner) => {
169 let _ = args.add(inner.into_vec());
170 }
171 Array::TinyInt(inner) => {
172 let _ = args.add(inner.into_vec());
173 }
174 Array::SmallInt(inner) => {
175 let _ = args.add(inner.into_vec());
176 }
177 Array::Int(inner) => {
178 let _ = args.add(inner.into_vec());
179 }
180 Array::BigInt(inner) => {
181 let _ = args.add(inner.into_vec());
182 }
183 Array::TinyUnsigned(inner) => {
184 let v: Vec<Option<i16>> = inner
185 .into_vec()
186 .into_iter()
187 .map(|x| x.map(|y| y as i16))
188 .collect();
189 let _ = args.add(v);
190 }
191 Array::SmallUnsigned(inner) => {
192 let v: Vec<Option<i32>> = inner
193 .into_vec()
194 .into_iter()
195 .map(|x| x.map(|y| y as i32))
196 .collect();
197 let _ = args.add(v);
198 }
199 Array::Unsigned(inner) => {
200 let v: Vec<Option<i64>> = inner
201 .into_vec()
202 .into_iter()
203 .map(|x| x.map(|y| y as i64))
204 .collect();
205 let _ = args.add(v);
206 }
207 Array::BigUnsigned(inner) => {
208 let v: Vec<Option<i64>> = inner
209 .into_vec()
210 .into_iter()
211 .map(|x| x.map(|y| <i64 as TryFrom<u64>>::try_from(y).unwrap()))
212 .collect();
213 let _ = args.add(v);
214 }
215 Array::Float(inner) => {
216 let _ = args.add(inner.into_vec());
217 }
218 Array::Double(inner) => {
219 let _ = args.add(inner.into_vec());
220 }
221 Array::String(inner) => {
222 let _ = args.add(inner.into_vec());
223 }
224 Array::Char(inner) => {
225 let v: Vec<Option<String>> = inner
226 .into_vec()
227 .into_iter()
228 .map(|c| c.map(|x| x.to_string()))
229 .collect();
230 let _ = args.add(v);
231 }
232 Array::Bytes(inner) => {
233 let _ = args.add(inner.into_vec());
234 }
235 #[cfg(feature = "with-json")]
236 Array::Json(inner) => {
237 let _ = args.add(inner.into_vec());
238 }
239 #[cfg(feature = "with-chrono")]
240 Array::ChronoDate(inner) => {
241 let _ = args.add(inner.into_vec());
242 }
243 #[cfg(feature = "with-chrono")]
244 Array::ChronoTime(inner) => {
245 let _ = args.add(inner.into_vec());
246 }
247 #[cfg(feature = "with-chrono")]
248 Array::ChronoDateTime(inner) => {
249 let _ = args.add(inner.into_vec());
250 }
251 #[cfg(feature = "with-chrono")]
252 Array::ChronoDateTimeUtc(inner) => {
253 let _ = args.add(inner.into_vec());
254 }
255 #[cfg(feature = "with-chrono")]
256 Array::ChronoDateTimeLocal(inner) => {
257 let _ = args.add(inner.into_vec());
258 }
259 #[cfg(feature = "with-chrono")]
260 Array::ChronoDateTimeWithTimeZone(inner) => {
261 let _ = args.add(inner.into_vec());
262 }
263 #[cfg(feature = "with-time")]
264 Array::TimeDate(inner) => {
265 let _ = args.add(inner.into_vec());
266 }
267 #[cfg(feature = "with-time")]
268 Array::TimeTime(inner) => {
269 let _ = args.add(inner.into_vec());
270 }
271 #[cfg(feature = "with-time")]
272 Array::TimeDateTime(inner) => {
273 let _ = args.add(inner.into_vec());
274 }
275 #[cfg(feature = "with-time")]
276 Array::TimeDateTimeWithTimeZone(inner) => {
277 let _ = args.add(inner.into_vec());
278 }
279 #[cfg(feature = "with-uuid")]
280 Array::Uuid(inner) => {
281 let _ = args.add(inner.into_vec());
282 }
283 #[cfg(feature = "with-rust_decimal")]
284 Array::Decimal(inner) => {
285 let _ = args.add(inner.into_vec());
286 }
287 #[cfg(feature = "with-bigdecimal")]
288 Array::BigDecimal(inner) => {
289 let _ = args.add(inner.into_vec());
290 }
291 #[cfg(feature = "with-ipnetwork")]
292 Array::IpNetwork(inner) => {
293 let _ = args.add(inner.into_vec());
294 }
295 #[cfg(feature = "with-mac_address")]
296 Array::MacAddress(inner) => {
297 let _ = args.add(inner.into_vec());
298 }
299 #[cfg(feature = "with-jiff")]
300 Array::JiffDate(inner) => {
301 let v: Vec<Option<jiff_sqlx::Date>> = inner
302 .into_vec()
303 .into_iter()
304 .map(|x| x.map(Into::into))
305 .collect();
306 let _ = args.add(v);
307 }
308 #[cfg(feature = "with-jiff")]
309 Array::JiffTime(inner) => {
310 let v: Vec<Option<jiff_sqlx::Time>> = inner
311 .into_vec()
312 .into_iter()
313 .map(|x| x.map(Into::into))
314 .collect();
315 let _ = args.add(v);
316 }
317 #[cfg(feature = "with-jiff")]
318 Array::JiffDateTime(inner) => {
319 let v: Vec<Option<jiff_sqlx::DateTime>> = inner
320 .into_vec()
321 .into_iter()
322 .map(|x| x.map(Into::into))
323 .collect();
324 let _ = args.add(v);
325 }
326 #[cfg(feature = "with-jiff")]
327 Array::JiffTimestamp(inner) => {
328 let v: Vec<Option<jiff_sqlx::Timestamp>> = inner
329 .into_vec()
330 .into_iter()
331 .map(|x| x.map(Into::into))
332 .collect();
333 let _ = args.add(v);
334 }
335 #[cfg(feature = "with-jiff")]
336 Array::JiffZoned(inner) => {
337 let v: Vec<Option<jiff_sqlx::Timestamp>> = inner
338 .into_vec()
339 .into_iter()
340 .map(|x| x.map(|z| z.timestamp().into()))
341 .collect();
342 let _ = args.add(v);
343 }
344 Array::Enum(inner) => {
345 let (_, arr) = inner.as_ref();
347 let v: Vec<Option<String>> = arr
348 .iter()
349 .map(|e| e.as_ref().map(|e| e.as_str().to_owned()))
350 .collect();
351 let _ = args.add(v);
352 }
353 _ => {
354 panic!("Unsupported array variant for sea-query-sqlx");
355 }
356 }
357}
358
359#[cfg(feature = "postgres-array")]
360fn match_null_array(ty: ArrayType, args: &mut sqlx::postgres::PgArguments) {
361 match ty {
362 ArrayType::Bool => {
363 let _ = args.add(Option::<Vec<Option<bool>>>::None);
364 }
365 ArrayType::TinyInt => {
366 let _ = args.add(Option::<Vec<Option<i8>>>::None);
367 }
368 ArrayType::SmallInt => {
369 let _ = args.add(Option::<Vec<Option<i16>>>::None);
370 }
371 ArrayType::Int => {
372 let _ = args.add(Option::<Vec<Option<i32>>>::None);
373 }
374 ArrayType::BigInt => {
375 let _ = args.add(Option::<Vec<Option<i64>>>::None);
376 }
377 ArrayType::TinyUnsigned => {
378 let _ = args.add(Option::<Vec<Option<i16>>>::None);
379 }
380 ArrayType::SmallUnsigned => {
381 let _ = args.add(Option::<Vec<Option<i32>>>::None);
382 }
383 ArrayType::Unsigned => {
384 let _ = args.add(Option::<Vec<Option<i64>>>::None);
385 }
386 ArrayType::BigUnsigned => {
387 let _ = args.add(Option::<Vec<Option<i64>>>::None);
388 }
389 ArrayType::Float => {
390 let _ = args.add(Option::<Vec<Option<f32>>>::None);
391 }
392 ArrayType::Double => {
393 let _ = args.add(Option::<Vec<Option<f64>>>::None);
394 }
395 ArrayType::String => {
396 let _ = args.add(Option::<Vec<Option<String>>>::None);
397 }
398 ArrayType::Char => {
399 let _ = args.add(Option::<Vec<Option<String>>>::None);
400 }
401 ArrayType::Bytes => {
402 let _ = args.add(Option::<Vec<Option<Vec<u8>>>>::None);
403 }
404 ArrayType::Enum(_) => {
405 let _ = args.add(Option::<Vec<Option<String>>>::None);
406 }
407 #[cfg(feature = "with-json")]
408 ArrayType::Json => {
409 let _ = args.add(Option::<Vec<Option<Json>>>::None);
410 }
411 #[cfg(feature = "with-chrono")]
412 ArrayType::ChronoDate => {
413 let _ = args.add(Option::<Vec<Option<chrono::NaiveDate>>>::None);
414 }
415 #[cfg(feature = "with-chrono")]
416 ArrayType::ChronoTime => {
417 let _ = args.add(Option::<Vec<Option<chrono::NaiveTime>>>::None);
418 }
419 #[cfg(feature = "with-chrono")]
420 ArrayType::ChronoDateTime => {
421 let _ = args.add(Option::<Vec<Option<chrono::NaiveDateTime>>>::None);
422 }
423 #[cfg(feature = "with-chrono")]
424 ArrayType::ChronoDateTimeUtc => {
425 let _ = args.add(Option::<Vec<Option<chrono::DateTime<chrono::Utc>>>>::None);
426 }
427 #[cfg(feature = "with-chrono")]
428 ArrayType::ChronoDateTimeLocal => {
429 let _ = args.add(Option::<Vec<Option<chrono::DateTime<chrono::Local>>>>::None);
430 }
431 #[cfg(feature = "with-chrono")]
432 ArrayType::ChronoDateTimeWithTimeZone => {
433 let _ = args.add(Option::<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>::None);
434 }
435 #[cfg(feature = "with-time")]
436 ArrayType::TimeDate => {
437 let _ = args.add(Option::<Vec<Option<time::Date>>>::None);
438 }
439 #[cfg(feature = "with-time")]
440 ArrayType::TimeTime => {
441 let _ = args.add(Option::<Vec<Option<time::Time>>>::None);
442 }
443 #[cfg(feature = "with-time")]
444 ArrayType::TimeDateTime => {
445 let _ = args.add(Option::<Vec<Option<time::PrimitiveDateTime>>>::None);
446 }
447 #[cfg(feature = "with-time")]
448 ArrayType::TimeDateTimeWithTimeZone => {
449 let _ = args.add(Option::<Vec<Option<time::OffsetDateTime>>>::None);
450 }
451 #[cfg(feature = "with-jiff")]
452 ArrayType::JiffDate => {
453 let _ = args.add(Option::<Vec<Option<jiff_sqlx::Date>>>::None);
454 }
455 #[cfg(feature = "with-jiff")]
456 ArrayType::JiffTime => {
457 let _ = args.add(Option::<Vec<Option<jiff_sqlx::Time>>>::None);
458 }
459 #[cfg(feature = "with-jiff")]
460 ArrayType::JiffDateTime => {
461 let _ = args.add(Option::<Vec<Option<jiff_sqlx::DateTime>>>::None);
462 }
463 #[cfg(feature = "with-jiff")]
464 ArrayType::JiffTimestamp => {
465 let _ = args.add(Option::<Vec<Option<jiff_sqlx::Timestamp>>>::None);
466 }
467 #[cfg(feature = "with-jiff")]
468 ArrayType::JiffZoned => {
469 let _ = args.add(Option::<Vec<Option<jiff_sqlx::Timestamp>>>::None);
470 }
471 #[cfg(feature = "with-uuid")]
472 ArrayType::Uuid => {
473 let _ = args.add(Option::<Vec<Option<uuid::Uuid>>>::None);
474 }
475 #[cfg(feature = "with-rust_decimal")]
476 ArrayType::Decimal => {
477 let _ = args.add(Option::<Vec<Option<rust_decimal::Decimal>>>::None);
478 }
479 #[cfg(feature = "with-bigdecimal")]
480 ArrayType::BigDecimal => {
481 let _ = args.add(Option::<Vec<Option<bigdecimal::BigDecimal>>>::None);
482 }
483 #[cfg(feature = "with-ipnetwork")]
484 ArrayType::IpNetwork => {
485 let _ = args.add(Option::<Vec<Option<ipnetwork::IpNetwork>>>::None);
486 }
487 #[cfg(feature = "with-mac_address")]
488 ArrayType::MacAddress => {
489 let _ = args.add(Option::<Vec<Option<mac_address::MacAddress>>>::None);
490 }
491 }
492}
493
494#[cfg(all(test, feature = "postgres-array", feature = "with-json"))]
495mod tests {
496 use super::*;
497 use sqlx::Arguments;
498
499 #[test]
500 fn bind_null_json_array_adds_argument() {
501 let mut args = sqlx::postgres::PgArguments::default();
502 match_array(Array::Null(ArrayType::Json), &mut args);
503 assert_eq!(args.len(), 1);
504 }
505}