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