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