1use futures_util::lock::Mutex;
2use log::LevelFilter;
3use sea_query::Values;
4use std::{fmt::Write, future::Future, pin::Pin, sync::Arc};
5
6use sqlx::{
7 pool::PoolConnection,
8 postgres::{PgConnectOptions, PgQueryResult, PgRow},
9 Connection, Executor, PgPool, Postgres,
10};
11
12use sea_query_binder::SqlxValues;
13use tracing::instrument;
14
15use crate::{
16 debug_print, error::*, executor::*, AccessMode, ConnectOptions, DatabaseConnection,
17 DatabaseTransaction, DbBackend, IsolationLevel, QueryStream, Statement, TransactionError,
18};
19
20use super::sqlx_common::*;
21
22#[derive(Debug)]
24pub struct SqlxPostgresConnector;
25
26#[derive(Clone)]
28pub struct SqlxPostgresPoolConnection {
29 pub(crate) pool: PgPool,
30 metric_callback: Option<crate::metric::Callback>,
31}
32
33impl std::fmt::Debug for SqlxPostgresPoolConnection {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 write!(f, "SqlxPostgresPoolConnection {{ pool: {:?} }}", self.pool)
36 }
37}
38
39impl From<PgPool> for SqlxPostgresPoolConnection {
40 fn from(pool: PgPool) -> Self {
41 SqlxPostgresPoolConnection {
42 pool,
43 metric_callback: None,
44 }
45 }
46}
47
48impl From<PgPool> for DatabaseConnection {
49 fn from(pool: PgPool) -> Self {
50 DatabaseConnection::SqlxPostgresPoolConnection(pool.into())
51 }
52}
53
54impl SqlxPostgresConnector {
55 pub fn accepts(string: &str) -> bool {
57 string.starts_with("postgres://") && string.parse::<PgConnectOptions>().is_ok()
58 }
59
60 #[instrument(level = "trace")]
62 pub async fn connect(options: ConnectOptions) -> Result<DatabaseConnection, DbErr> {
63 let mut sqlx_opts = options
64 .url
65 .parse::<PgConnectOptions>()
66 .map_err(sqlx_error_to_conn_err)?;
67 use sqlx::ConnectOptions;
68 if !options.sqlx_logging {
69 sqlx_opts = sqlx_opts.disable_statement_logging();
70 } else {
71 sqlx_opts = sqlx_opts.log_statements(options.sqlx_logging_level);
72 if options.sqlx_slow_statements_logging_level != LevelFilter::Off {
73 sqlx_opts = sqlx_opts.log_slow_statements(
74 options.sqlx_slow_statements_logging_level,
75 options.sqlx_slow_statements_logging_threshold,
76 );
77 }
78 }
79
80 if let Some(f) = &options.pg_opts_fn {
81 sqlx_opts = f(sqlx_opts);
82 }
83
84 let set_search_path_sql = options.schema_search_path.as_ref().map(|schema| {
85 let mut string = "SET search_path = ".to_owned();
86 if schema.starts_with('"') {
87 write!(&mut string, "{schema}").unwrap();
88 } else {
89 for (i, schema) in schema.split(',').enumerate() {
90 if i > 0 {
91 write!(&mut string, ",").unwrap();
92 }
93 if schema.starts_with('"') {
94 write!(&mut string, "{schema}").unwrap();
95 } else {
96 write!(&mut string, "\"{schema}\"").unwrap();
97 }
98 }
99 }
100 string
101 });
102 let lazy = options.connect_lazy;
103 let mut pool_options = options.sqlx_pool_options();
104 if let Some(sql) = set_search_path_sql {
105 pool_options = pool_options.after_connect(move |conn, _| {
106 let sql = sql.clone();
107 Box::pin(async move {
108 sqlx::Executor::execute(conn, sql.as_str())
109 .await
110 .map(|_| ())
111 })
112 });
113 }
114 let pool = if lazy {
115 pool_options.connect_lazy_with(sqlx_opts)
116 } else {
117 pool_options
118 .connect_with(sqlx_opts)
119 .await
120 .map_err(sqlx_error_to_conn_err)?
121 };
122 Ok(DatabaseConnection::SqlxPostgresPoolConnection(
123 SqlxPostgresPoolConnection {
124 pool,
125 metric_callback: None,
126 },
127 ))
128 }
129}
130
131impl SqlxPostgresConnector {
132 pub fn from_sqlx_postgres_pool(pool: PgPool) -> DatabaseConnection {
134 DatabaseConnection::SqlxPostgresPoolConnection(SqlxPostgresPoolConnection {
135 pool,
136 metric_callback: None,
137 })
138 }
139}
140
141impl SqlxPostgresPoolConnection {
142 #[instrument(level = "trace")]
144 pub async fn execute(&self, stmt: Statement) -> Result<ExecResult, DbErr> {
145 debug_print!("{}", stmt);
146
147 let query = sqlx_query(&stmt);
148 let mut conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
149 crate::metric::metric!(self.metric_callback, &stmt, {
150 match query.execute(&mut *conn).await {
151 Ok(res) => Ok(res.into()),
152 Err(err) => Err(sqlx_error_to_exec_err(err)),
153 }
154 })
155 }
156
157 #[instrument(level = "trace")]
159 pub async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
160 debug_print!("{}", sql);
161
162 let conn = &mut self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
163 match conn.execute(sql).await {
164 Ok(res) => Ok(res.into()),
165 Err(err) => Err(sqlx_error_to_exec_err(err)),
166 }
167 }
168
169 #[instrument(level = "trace")]
171 pub async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
172 debug_print!("{}", stmt);
173
174 let query = sqlx_query(&stmt);
175 let mut conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
176 crate::metric::metric!(self.metric_callback, &stmt, {
177 match query.fetch_one(&mut *conn).await {
178 Ok(row) => Ok(Some(row.into())),
179 Err(err) => match err {
180 sqlx::Error::RowNotFound => Ok(None),
181 _ => Err(sqlx_error_to_query_err(err)),
182 },
183 }
184 })
185 }
186
187 #[instrument(level = "trace")]
189 pub async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr> {
190 debug_print!("{}", stmt);
191
192 let query = sqlx_query(&stmt);
193 let mut conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
194 crate::metric::metric!(self.metric_callback, &stmt, {
195 match query.fetch_all(&mut *conn).await {
196 Ok(rows) => Ok(rows.into_iter().map(|r| r.into()).collect()),
197 Err(err) => Err(sqlx_error_to_query_err(err)),
198 }
199 })
200 }
201
202 #[instrument(level = "trace")]
204 pub async fn stream(&self, stmt: Statement) -> Result<QueryStream, DbErr> {
205 debug_print!("{}", stmt);
206
207 let conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
208 Ok(QueryStream::from((
209 conn,
210 stmt,
211 self.metric_callback.clone(),
212 )))
213 }
214
215 #[instrument(level = "trace")]
217 pub async fn begin(
218 &self,
219 isolation_level: Option<IsolationLevel>,
220 access_mode: Option<AccessMode>,
221 ) -> Result<DatabaseTransaction, DbErr> {
222 let conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
223 DatabaseTransaction::new_postgres(
224 conn,
225 self.metric_callback.clone(),
226 isolation_level,
227 access_mode,
228 )
229 .await
230 }
231
232 #[instrument(level = "trace", skip(callback))]
234 pub async fn transaction<F, T, E>(
235 &self,
236 callback: F,
237 isolation_level: Option<IsolationLevel>,
238 access_mode: Option<AccessMode>,
239 ) -> Result<T, TransactionError<E>>
240 where
241 F: for<'b> FnOnce(
242 &'b DatabaseTransaction,
243 ) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'b>>
244 + Send,
245 T: Send,
246 E: std::fmt::Display + std::fmt::Debug + Send,
247 {
248 let conn = self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
249 let transaction = DatabaseTransaction::new_postgres(
250 conn,
251 self.metric_callback.clone(),
252 isolation_level,
253 access_mode,
254 )
255 .await
256 .map_err(|e| TransactionError::Connection(e))?;
257 transaction.run(callback).await
258 }
259
260 pub(crate) fn set_metric_callback<F>(&mut self, callback: F)
261 where
262 F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static,
263 {
264 self.metric_callback = Some(Arc::new(callback));
265 }
266
267 pub async fn ping(&self) -> Result<(), DbErr> {
269 let conn = &mut self.pool.acquire().await.map_err(sqlx_conn_acquire_err)?;
270 match conn.ping().await {
271 Ok(_) => Ok(()),
272 Err(err) => Err(sqlx_error_to_conn_err(err)),
273 }
274 }
275
276 pub async fn close(self) -> Result<(), DbErr> {
279 self.close_by_ref().await
280 }
281
282 pub async fn close_by_ref(&self) -> Result<(), DbErr> {
284 self.pool.close().await;
285 Ok(())
286 }
287}
288
289impl From<PgRow> for QueryResult {
290 fn from(row: PgRow) -> QueryResult {
291 QueryResult {
292 row: QueryResultRow::SqlxPostgres(row),
293 }
294 }
295}
296
297impl From<PgQueryResult> for ExecResult {
298 fn from(result: PgQueryResult) -> ExecResult {
299 ExecResult {
300 result: ExecResultHolder::SqlxPostgres(result),
301 }
302 }
303}
304
305pub(crate) fn sqlx_query(stmt: &Statement) -> sqlx::query::Query<'_, Postgres, SqlxValues> {
306 let values = stmt
307 .values
308 .as_ref()
309 .map_or(Values(Vec::new()), |values| values.clone());
310 sqlx::query_with(&stmt.sql, SqlxValues(values))
311}
312
313pub(crate) async fn set_transaction_config(
314 conn: &mut PoolConnection<Postgres>,
315 isolation_level: Option<IsolationLevel>,
316 access_mode: Option<AccessMode>,
317) -> Result<(), DbErr> {
318 if let Some(isolation_level) = isolation_level {
319 let stmt = Statement {
320 sql: format!("SET TRANSACTION ISOLATION LEVEL {isolation_level}"),
321 values: None,
322 db_backend: DbBackend::Postgres,
323 };
324 let query = sqlx_query(&stmt);
325 conn.execute(query).await.map_err(sqlx_error_to_exec_err)?;
326 }
327 if let Some(access_mode) = access_mode {
328 let stmt = Statement {
329 sql: format!("SET TRANSACTION {access_mode}"),
330 values: None,
331 db_backend: DbBackend::Postgres,
332 };
333 let query = sqlx_query(&stmt);
334 conn.execute(query).await.map_err(sqlx_error_to_exec_err)?;
335 }
336 Ok(())
337}
338
339impl
340 From<(
341 PoolConnection<sqlx::Postgres>,
342 Statement,
343 Option<crate::metric::Callback>,
344 )> for crate::QueryStream
345{
346 fn from(
347 (conn, stmt, metric_callback): (
348 PoolConnection<sqlx::Postgres>,
349 Statement,
350 Option<crate::metric::Callback>,
351 ),
352 ) -> Self {
353 crate::QueryStream::build(
354 stmt,
355 crate::InnerConnection::Postgres(conn),
356 metric_callback,
357 )
358 }
359}
360
361impl crate::DatabaseTransaction {
362 pub(crate) async fn new_postgres(
363 inner: PoolConnection<sqlx::Postgres>,
364 metric_callback: Option<crate::metric::Callback>,
365 isolation_level: Option<IsolationLevel>,
366 access_mode: Option<AccessMode>,
367 ) -> Result<crate::DatabaseTransaction, DbErr> {
368 Self::begin(
369 Arc::new(Mutex::new(crate::InnerConnection::Postgres(inner))),
370 crate::DbBackend::Postgres,
371 metric_callback,
372 isolation_level,
373 access_mode,
374 )
375 .await
376 }
377}
378
379#[cfg(feature = "proxy")]
380pub(crate) fn from_sqlx_postgres_row_to_proxy_row(row: &sqlx::postgres::PgRow) -> crate::ProxyRow {
381 use sea_query::Value;
384 use sqlx::{Column, Row, TypeInfo};
385 crate::ProxyRow {
386 values: row
387 .columns()
388 .iter()
389 .map(|c| {
390 (
391 c.name().to_string(),
392 match c.type_info().name() {
393 "BOOL" => Value::Bool(Some(
394 row.try_get(c.ordinal()).expect("Failed to get boolean"),
395 )),
396 #[cfg(feature = "postgres-array")]
397 "BOOL[]" => Value::Array(
398 sea_query::ArrayType::Bool,
399 Some(Box::new(
400 row.try_get::<Vec<bool>, _>(c.ordinal())
401 .expect("Failed to get boolean array")
402 .iter()
403 .map(|val| Value::Bool(Some(*val)))
404 .collect(),
405 )),
406 ),
407
408 "\"CHAR\"" => Value::TinyInt(Some(
409 row.try_get(c.ordinal())
410 .expect("Failed to get small integer"),
411 )),
412 #[cfg(feature = "postgres-array")]
413 "\"CHAR\"[]" => Value::Array(
414 sea_query::ArrayType::TinyInt,
415 Some(Box::new(
416 row.try_get::<Vec<i8>, _>(c.ordinal())
417 .expect("Failed to get small integer array")
418 .iter()
419 .map(|val| Value::TinyInt(Some(*val)))
420 .collect(),
421 )),
422 ),
423
424 "SMALLINT" | "SMALLSERIAL" | "INT2" => Value::SmallInt(Some(
425 row.try_get(c.ordinal())
426 .expect("Failed to get small integer"),
427 )),
428 #[cfg(feature = "postgres-array")]
429 "SMALLINT[]" | "SMALLSERIAL[]" | "INT2[]" => Value::Array(
430 sea_query::ArrayType::SmallInt,
431 Some(Box::new(
432 row.try_get::<Vec<i16>, _>(c.ordinal())
433 .expect("Failed to get small integer array")
434 .iter()
435 .map(|val| Value::SmallInt(Some(*val)))
436 .collect(),
437 )),
438 ),
439
440 "INT" | "SERIAL" | "INT4" => Value::Int(Some(
441 row.try_get(c.ordinal()).expect("Failed to get integer"),
442 )),
443 #[cfg(feature = "postgres-array")]
444 "INT[]" | "SERIAL[]" | "INT4[]" => Value::Array(
445 sea_query::ArrayType::Int,
446 Some(Box::new(
447 row.try_get::<Vec<i32>, _>(c.ordinal())
448 .expect("Failed to get integer array")
449 .iter()
450 .map(|val| Value::Int(Some(*val)))
451 .collect(),
452 )),
453 ),
454
455 "BIGINT" | "BIGSERIAL" | "INT8" => Value::BigInt(Some(
456 row.try_get(c.ordinal()).expect("Failed to get big integer"),
457 )),
458 #[cfg(feature = "postgres-array")]
459 "BIGINT[]" | "BIGSERIAL[]" | "INT8[]" => Value::Array(
460 sea_query::ArrayType::BigInt,
461 Some(Box::new(
462 row.try_get::<Vec<i64>, _>(c.ordinal())
463 .expect("Failed to get big integer array")
464 .iter()
465 .map(|val| Value::BigInt(Some(*val)))
466 .collect(),
467 )),
468 ),
469
470 "FLOAT4" | "REAL" => Value::Float(Some(
471 row.try_get(c.ordinal()).expect("Failed to get float"),
472 )),
473 #[cfg(feature = "postgres-array")]
474 "FLOAT4[]" | "REAL[]" => Value::Array(
475 sea_query::ArrayType::Float,
476 Some(Box::new(
477 row.try_get::<Vec<f32>, _>(c.ordinal())
478 .expect("Failed to get float array")
479 .iter()
480 .map(|val| Value::Float(Some(*val)))
481 .collect(),
482 )),
483 ),
484
485 "FLOAT8" | "DOUBLE PRECISION" => Value::Double(Some(
486 row.try_get(c.ordinal()).expect("Failed to get double"),
487 )),
488 #[cfg(feature = "postgres-array")]
489 "FLOAT8[]" | "DOUBLE PRECISION[]" => Value::Array(
490 sea_query::ArrayType::Double,
491 Some(Box::new(
492 row.try_get::<Vec<f64>, _>(c.ordinal())
493 .expect("Failed to get double array")
494 .iter()
495 .map(|val| Value::Double(Some(*val)))
496 .collect(),
497 )),
498 ),
499
500 "VARCHAR" | "CHAR" | "TEXT" | "NAME" => Value::String(Some(Box::new(
501 row.try_get(c.ordinal()).expect("Failed to get string"),
502 ))),
503 #[cfg(feature = "postgres-array")]
504 "VARCHAR[]" | "CHAR[]" | "TEXT[]" | "NAME[]" => Value::Array(
505 sea_query::ArrayType::String,
506 Some(Box::new(
507 row.try_get::<Vec<String>, _>(c.ordinal())
508 .expect("Failed to get string array")
509 .iter()
510 .map(|val| Value::String(Some(Box::new(val.clone()))))
511 .collect(),
512 )),
513 ),
514
515 "BYTEA" => Value::Bytes(Some(Box::new(
516 row.try_get(c.ordinal()).expect("Failed to get bytes"),
517 ))),
518 #[cfg(feature = "postgres-array")]
519 "BYTEA[]" => Value::Array(
520 sea_query::ArrayType::Bytes,
521 Some(Box::new(
522 row.try_get::<Vec<Vec<u8>>, _>(c.ordinal())
523 .expect("Failed to get bytes array")
524 .iter()
525 .map(|val| Value::Bytes(Some(Box::new(val.clone()))))
526 .collect(),
527 )),
528 ),
529
530 #[cfg(feature = "with-bigdecimal")]
531 "NUMERIC" => Value::BigDecimal(Some(Box::new(
532 row.try_get(c.ordinal()).expect("Failed to get numeric"),
533 ))),
534 #[cfg(all(
535 feature = "with-rust_decimal",
536 not(feature = "with-bigdecimal")
537 ))]
538 "NUMERIC" => Value::Decimal(Some(Box::new(
539 row.try_get(c.ordinal()).expect("Failed to get numeric"),
540 ))),
541
542 #[cfg(all(feature = "with-bigdecimal", feature = "postgres-array"))]
543 "NUMERIC[]" => Value::Array(
544 sea_query::ArrayType::BigDecimal,
545 Some(Box::new(
546 row.try_get::<Vec<bigdecimal::BigDecimal>, _>(c.ordinal())
547 .expect("Failed to get numeric array")
548 .iter()
549 .map(|val| Value::BigDecimal(Some(Box::new(val.clone()))))
550 .collect(),
551 )),
552 ),
553 #[cfg(all(
554 feature = "with-rust_decimal",
555 not(feature = "with-bigdecimal"),
556 feature = "postgres-array"
557 ))]
558 "NUMERIC[]" => Value::Array(
559 sea_query::ArrayType::Decimal,
560 Some(Box::new(
561 row.try_get::<Vec<rust_decimal::Decimal>, _>(c.ordinal())
562 .expect("Failed to get numeric array")
563 .iter()
564 .map(|val| Value::Decimal(Some(Box::new(val.clone()))))
565 .collect(),
566 )),
567 ),
568
569 "OID" => Value::BigInt(Some(
570 row.try_get(c.ordinal()).expect("Failed to get oid"),
571 )),
572 #[cfg(feature = "postgres-array")]
573 "OID[]" => Value::Array(
574 sea_query::ArrayType::BigInt,
575 Some(Box::new(
576 row.try_get::<Vec<i64>, _>(c.ordinal())
577 .expect("Failed to get oid array")
578 .iter()
579 .map(|val| Value::BigInt(Some(*val)))
580 .collect(),
581 )),
582 ),
583
584 "JSON" | "JSONB" => Value::Json(Some(Box::new(
585 row.try_get(c.ordinal()).expect("Failed to get json"),
586 ))),
587 #[cfg(any(feature = "json-array", feature = "postgres-array"))]
588 "JSON[]" | "JSONB[]" => Value::Array(
589 sea_query::ArrayType::Json,
590 Some(Box::new(
591 row.try_get::<Vec<serde_json::Value>, _>(c.ordinal())
592 .expect("Failed to get json array")
593 .iter()
594 .map(|val| Value::Json(Some(Box::new(val.clone()))))
595 .collect(),
596 )),
597 ),
598
599 #[cfg(feature = "with-ipnetwork")]
600 "INET" | "CIDR" => Value::IpNetwork(Some(Box::new(
601 row.try_get(c.ordinal()).expect("Failed to get ip address"),
602 ))),
603 #[cfg(feature = "with-ipnetwork")]
604 "INET[]" | "CIDR[]" => Value::Array(
605 sea_query::ArrayType::IpNetwork,
606 Some(Box::new(
607 row.try_get::<Vec<ipnetwork::IpNetwork>, _>(c.ordinal())
608 .expect("Failed to get ip address array")
609 .iter()
610 .map(|val| Value::IpNetwork(Some(Box::new(*val))))
611 .collect(),
612 )),
613 ),
614
615 #[cfg(feature = "with-mac_address")]
616 "MACADDR" | "MACADDR8" => Value::MacAddress(Some(Box::new(
617 row.try_get(c.ordinal()).expect("Failed to get mac address"),
618 ))),
619 #[cfg(all(feature = "with-mac_address", feature = "postgres-array"))]
620 "MACADDR[]" | "MACADDR8[]" => Value::Array(
621 sea_query::ArrayType::MacAddress,
622 Some(Box::new(
623 row.try_get::<Vec<mac_address::MacAddress>, _>(c.ordinal())
624 .expect("Failed to get mac address array")
625 .iter()
626 .map(|val| Value::MacAddress(Some(Box::new(val.clone()))))
627 .collect(),
628 )),
629 ),
630
631 #[cfg(feature = "with-chrono")]
632 "TIMESTAMP" => Value::ChronoDateTime(Some(Box::new(
633 row.try_get(c.ordinal()).expect("Failed to get timestamp"),
634 ))),
635 #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
636 "TIMESTAMP" => Value::TimeDateTime(Some(Box::new(
637 row.try_get(c.ordinal()).expect("Failed to get timestamp"),
638 ))),
639
640 #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
641 "TIMESTAMP[]" => Value::Array(
642 sea_query::ArrayType::ChronoDateTime,
643 Some(Box::new(
644 row.try_get::<Vec<chrono::NaiveDateTime>, _>(c.ordinal())
645 .expect("Failed to get timestamp array")
646 .iter()
647 .map(|val| Value::ChronoDateTime(Some(Box::new(*val))))
648 .collect(),
649 )),
650 ),
651 #[cfg(all(
652 feature = "with-time",
653 not(feature = "with-chrono"),
654 feature = "postgres-array"
655 ))]
656 "TIMESTAMP[]" => Value::Array(
657 sea_query::ArrayType::TimeDateTime,
658 Some(Box::new(
659 row.try_get::<Vec<time::OffsetDateTime>, _>(c.ordinal())
660 .expect("Failed to get timestamp array")
661 .iter()
662 .map(|val| Value::TimeDateTime(Some(Box::new(val.clone()))))
663 .collect(),
664 )),
665 ),
666
667 #[cfg(feature = "with-chrono")]
668 "DATE" => Value::ChronoDate(Some(Box::new(
669 row.try_get(c.ordinal()).expect("Failed to get date"),
670 ))),
671 #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
672 "DATE" => Value::TimeDate(Some(Box::new(
673 row.try_get(c.ordinal()).expect("Failed to get date"),
674 ))),
675
676 #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
677 "DATE[]" => Value::Array(
678 sea_query::ArrayType::ChronoDate,
679 Some(Box::new(
680 row.try_get::<Vec<chrono::NaiveDate>, _>(c.ordinal())
681 .expect("Failed to get date array")
682 .iter()
683 .map(|val| Value::ChronoDate(Some(Box::new(*val))))
684 .collect(),
685 )),
686 ),
687 #[cfg(all(
688 feature = "with-time",
689 not(feature = "with-chrono"),
690 feature = "postgres-array"
691 ))]
692 "DATE[]" => Value::Array(
693 sea_query::ArrayType::TimeDate,
694 Some(Box::new(
695 row.try_get::<Vec<time::Date>, _>(c.ordinal())
696 .expect("Failed to get date array")
697 .iter()
698 .map(|val| Value::TimeDate(Some(Box::new(val.clone()))))
699 .collect(),
700 )),
701 ),
702
703 #[cfg(feature = "with-chrono")]
704 "TIME" => Value::ChronoTime(Some(Box::new(
705 row.try_get(c.ordinal()).expect("Failed to get time"),
706 ))),
707 #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
708 "TIME" => Value::TimeTime(Some(Box::new(
709 row.try_get(c.ordinal()).expect("Failed to get time"),
710 ))),
711
712 #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
713 "TIME[]" => Value::Array(
714 sea_query::ArrayType::ChronoTime,
715 Some(Box::new(
716 row.try_get::<Vec<chrono::NaiveTime>, _>(c.ordinal())
717 .expect("Failed to get time array")
718 .iter()
719 .map(|val| Value::ChronoTime(Some(Box::new(*val))))
720 .collect(),
721 )),
722 ),
723 #[cfg(all(
724 feature = "with-time",
725 not(feature = "with-chrono"),
726 feature = "postgres-array"
727 ))]
728 "TIME[]" => Value::Array(
729 sea_query::ArrayType::TimeTime,
730 Some(Box::new(
731 row.try_get::<Vec<time::Time>, _>(c.ordinal())
732 .expect("Failed to get time array")
733 .iter()
734 .map(|val| Value::TimeTime(Some(Box::new(val.clone()))))
735 .collect(),
736 )),
737 ),
738
739 #[cfg(feature = "with-chrono")]
740 "TIMESTAMPTZ" => Value::ChronoDateTimeUtc(Some(Box::new(
741 row.try_get(c.ordinal()).expect("Failed to get timestamptz"),
742 ))),
743 #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
744 "TIMESTAMPTZ" => Value::TimeDateTime(Some(Box::new(
745 row.try_get(c.ordinal()).expect("Failed to get timestamptz"),
746 ))),
747
748 #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
749 "TIMESTAMPTZ[]" => Value::Array(
750 sea_query::ArrayType::ChronoDateTimeUtc,
751 Some(Box::new(
752 row.try_get::<Vec<chrono::DateTime<chrono::Utc>>, _>(c.ordinal())
753 .expect("Failed to get timestamptz array")
754 .iter()
755 .map(|val| Value::ChronoDateTimeUtc(Some(Box::new(*val))))
756 .collect(),
757 )),
758 ),
759 #[cfg(all(
760 feature = "with-time",
761 not(feature = "with-chrono"),
762 feature = "postgres-array"
763 ))]
764 "TIMESTAMPTZ[]" => Value::Array(
765 sea_query::ArrayType::TimeDateTime,
766 Some(Box::new(
767 row.try_get::<Vec<time::OffsetDateTime>, _>(c.ordinal())
768 .expect("Failed to get timestamptz array")
769 .iter()
770 .map(|val| Value::TimeDateTime(Some(Box::new(val.clone()))))
771 .collect(),
772 )),
773 ),
774
775 #[cfg(feature = "with-chrono")]
776 "TIMETZ" => Value::ChronoTime(Some(Box::new(
777 row.try_get(c.ordinal()).expect("Failed to get timetz"),
778 ))),
779 #[cfg(all(feature = "with-time", not(feature = "with-chrono")))]
780 "TIMETZ" => Value::TimeTime(Some(Box::new(
781 row.try_get(c.ordinal()).expect("Failed to get timetz"),
782 ))),
783
784 #[cfg(all(feature = "with-chrono", feature = "postgres-array"))]
785 "TIMETZ[]" => Value::Array(
786 sea_query::ArrayType::ChronoTime,
787 Some(Box::new(
788 row.try_get::<Vec<chrono::NaiveTime>, _>(c.ordinal())
789 .expect("Failed to get timetz array")
790 .iter()
791 .map(|val| Value::ChronoTime(Some(Box::new(*val))))
792 .collect(),
793 )),
794 ),
795 #[cfg(all(
796 feature = "with-time",
797 not(feature = "with-chrono"),
798 feature = "postgres-array"
799 ))]
800 "TIMETZ[]" => Value::Array(
801 sea_query::ArrayType::TimeTime,
802 Some(Box::new(
803 row.try_get::<Vec<time::Time>, _>(c.ordinal())
804 .expect("Failed to get timetz array")
805 .iter()
806 .map(|val| Value::TimeTime(Some(Box::new(val.clone()))))
807 .collect(),
808 )),
809 ),
810
811 #[cfg(feature = "with-uuid")]
812 "UUID" => Value::Uuid(Some(Box::new(
813 row.try_get(c.ordinal()).expect("Failed to get uuid"),
814 ))),
815
816 #[cfg(all(feature = "with-uuid", feature = "postgres-array"))]
817 "UUID[]" => Value::Array(
818 sea_query::ArrayType::Uuid,
819 Some(Box::new(
820 row.try_get::<Vec<uuid::Uuid>, _>(c.ordinal())
821 .expect("Failed to get uuid array")
822 .iter()
823 .map(|val| Value::Uuid(Some(Box::new(*val))))
824 .collect(),
825 )),
826 ),
827
828 _ => unreachable!("Unknown column type: {}", c.type_info().name()),
829 },
830 )
831 })
832 .collect(),
833 }
834}