Skip to main content

drizzle_postgres/
lib.rs

1//! `PostgreSQL` support for drizzle-rs: values, query builders,
2//! `PostgreSQL`-only operators and the traits the `#[PostgresTable]` family of
3//! macros implement.
4//!
5//! Most code uses this crate through the `drizzle` crate, which re-exports it
6//! as `drizzle::postgres` and adds the database drivers. On its own, this
7//! crate builds SQL without running it.
8
9#![allow(unexpected_cfgs)]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12#[cfg(not(feature = "std"))]
13extern crate alloc;
14
15pub(crate) mod prelude {
16    #[cfg(feature = "std")]
17    pub use std::{
18        borrow::Cow,
19        boxed::Box,
20        format,
21        rc::Rc,
22        string::{String, ToString},
23        sync::Arc,
24        vec::Vec,
25    };
26
27    #[cfg(not(feature = "std"))]
28    pub use alloc::{
29        borrow::Cow,
30        boxed::Box,
31        format,
32        rc::Rc,
33        string::{String, ToString},
34        sync::Arc,
35        vec::Vec,
36    };
37}
38
39pub mod attrs;
40#[cfg(feature = "aws-data-api")]
41pub mod aws_data_api;
42pub mod builder;
43pub mod common;
44pub mod expr;
45pub mod helpers;
46pub mod traits;
47pub mod transaction;
48/// SQL type markers for `PostgreSQL` (`Int4`, `Text`, `Jsonb`, ...), from
49/// `drizzle_types`.
50pub mod types {
51    pub use drizzle_types::postgres::types::*;
52}
53pub mod values;
54
55#[cfg(all(test, feature = "query"))]
56mod relational_sql_tests;
57
58#[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
59pub use postgres::Row;
60#[cfg(feature = "tokio-postgres")]
61pub use tokio_postgres::Row;
62
63#[doc(hidden)]
64pub mod driver_types {
65    #[cfg(all(
66        any(feature = "serde", feature = "query"),
67        feature = "postgres-sync",
68        not(feature = "tokio-postgres")
69    ))]
70    pub use postgres::types::Json;
71    #[cfg(all(any(feature = "serde", feature = "query"), feature = "tokio-postgres"))]
72    pub use tokio_postgres::types::Json;
73
74    // Wire-codec items for macro-generated `FromSql`/`ToSql` impls, so the
75    // expansion never names a driver crate the user may not depend on directly.
76    #[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
77    pub use bytes::BytesMut;
78    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
79    pub use postgres::types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
80    #[cfg(feature = "tokio-postgres")]
81    pub use tokio_postgres::types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
82
83    #[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
84    pub use field_decode::{FieldDecode, ViaColumn, ViaFromSql};
85
86    /// Decodes a `#[derive(PostgresFromRow)]` field whose type the derive
87    /// cannot inspect. Generated code calls
88    /// `(&&FieldDecode::<T>::new()).decode_field(row, idx)`: method resolution
89    /// tries `ViaColumn` (custom `DrizzlePostgresColumn` types and
90    /// `#[PostgresEnum]`s, decoded through their own codec) before
91    /// `ViaFromSql` (anything the driver decodes). Both return a decode error
92    /// instead of panicking.
93    #[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
94    mod field_decode {
95        use crate::traits::DrizzlePostgresColumn;
96        use core::marker::PhantomData;
97        use drizzle_core::error::DrizzleError;
98
99        pub struct FieldDecode<T>(PhantomData<T>);
100
101        impl<T> FieldDecode<T> {
102            #[must_use]
103            pub const fn new() -> Self {
104                Self(PhantomData)
105            }
106        }
107
108        impl<T> Default for FieldDecode<T> {
109            fn default() -> Self {
110                Self::new()
111            }
112        }
113
114        pub trait ViaColumn<T> {
115            /// Decodes the cell at `idx` through `T`'s column codec.
116            ///
117            /// # Errors
118            ///
119            /// Returns the codec's error when the cell does not decode.
120            fn decode_field(&self, row: &crate::Row, idx: usize) -> Result<T, DrizzleError>;
121        }
122
123        impl<T: DrizzlePostgresColumn> ViaColumn<T> for &FieldDecode<T> {
124            fn decode_field(&self, row: &crate::Row, idx: usize) -> Result<T, DrizzleError> {
125                T::decode(row, idx)
126            }
127        }
128
129        pub trait ViaFromSql<T> {
130            /// Decodes the cell at `idx` through the driver's `FromSql`.
131            ///
132            /// # Errors
133            ///
134            /// Returns [`DrizzleError::ConversionError`] when the cell's wire
135            /// type does not match `T` or its value does not decode.
136            fn decode_field(&self, row: &crate::Row, idx: usize) -> Result<T, DrizzleError>;
137        }
138
139        impl<T: for<'a> super::FromSql<'a>> ViaFromSql<T> for FieldDecode<T> {
140            fn decode_field(&self, row: &crate::Row, idx: usize) -> Result<T, DrizzleError> {
141                row.try_get::<_, T>(idx)
142                    .map_err(|e| DrizzleError::ConversionError(e.to_string().into()))
143            }
144        }
145    }
146}
147
148pub use drizzle_core::ParamBind;
149pub use transaction::{AccessMode, IsolationLevel, SnapshotId, TransactionConfig};