sea_orm/driver/
sqlx_postgres.rs

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