sqlx_core/types/
mod.rs

1//! Conversions between Rust and SQL types.
2//!
3//! To see how each SQL type maps to a Rust type, see the corresponding `types` module for each
4//! database:
5//!
6//!  * [PostgreSQL](crate::postgres::types)
7//!  * [MySQL](crate::mysql::types)
8//!  * [SQLite](crate::sqlite::types)
9//!  * [MSSQL](crate::mssql::types)
10//!
11//! Any external types that have had [`Type`] implemented for, are re-exported in this module
12//! for convenience as downstream users need to use a compatible version of the external crate
13//! to take advantage of the implementation.
14//!
15//! # Nullable
16//!
17//! To represent nullable SQL types, `Option<T>` is supported where `T` implements `Type`.
18//! An `Option<T>` represents a potentially `NULL` value from SQL.
19
20use crate::database::Database;
21use crate::type_info::TypeInfo;
22
23mod non_zero;
24
25#[cfg(feature = "bstr")]
26#[cfg_attr(docsrs, doc(cfg(feature = "bstr")))]
27pub mod bstr;
28
29#[cfg(feature = "json")]
30#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
31mod json;
32
33mod text;
34
35#[cfg(feature = "uuid")]
36#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
37#[doc(no_inline)]
38pub use uuid::{self, Uuid};
39
40#[cfg(feature = "chrono")]
41#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
42pub mod chrono {
43    #[doc(no_inline)]
44    pub use chrono::{
45        DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc,
46    };
47}
48
49#[cfg(feature = "bit-vec")]
50#[cfg_attr(docsrs, doc(cfg(feature = "bit-vec")))]
51#[doc(no_inline)]
52pub use bit_vec::BitVec;
53
54#[cfg(feature = "time")]
55#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
56pub mod time {
57    #[doc(no_inline)]
58    pub use time::{Date, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset};
59}
60
61#[cfg(feature = "bigdecimal")]
62#[cfg_attr(docsrs, doc(cfg(feature = "bigdecimal")))]
63#[doc(no_inline)]
64pub use bigdecimal::BigDecimal;
65#[cfg(feature = "rust_decimal")]
66#[cfg_attr(docsrs, doc(cfg(feature = "rust_decimal")))]
67#[doc(no_inline)]
68pub use rust_decimal::Decimal;
69
70#[cfg(feature = "ipnetwork")]
71#[cfg_attr(docsrs, doc(cfg(feature = "ipnetwork")))]
72pub mod ipnetwork {
73    #[doc(no_inline)]
74    pub use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
75}
76
77#[cfg(feature = "mac_address")]
78#[cfg_attr(docsrs, doc(cfg(feature = "mac_address")))]
79pub mod mac_address {
80    #[doc(no_inline)]
81    pub use mac_address::MacAddress;
82}
83
84#[cfg(feature = "json")]
85pub use json::{Json, JsonRawValue, JsonValue};
86pub use text::Text;
87
88/// Indicates that a SQL type is supported for a database.
89///
90/// ## Compile-time verification
91///
92/// With compile-time verification, the use of type overrides is currently required to make
93/// use of any user-defined types.
94///
95/// ```rust,ignore
96/// struct MyUser { id: UserId, name: String }
97///
98/// // fetch all properties from user and override the type in Rust for `id`
99/// let user = query_as!(MyUser, r#"SELECT users.*, id as "id: UserId" FROM users"#)
100///     .fetch_one(&pool).await?;
101/// ```
102///
103/// ## Derivable
104///
105/// This trait can be derived by SQLx to support Rust-only wrapper types, enumerations, and (for
106/// postgres) structured records. Additionally, an implementation of [`Encode`](crate::encode::Encode) and [`Decode`](crate::decode::Decode) is
107/// generated.
108///
109/// ### Transparent
110///
111/// Rust-only domain wrappers around SQL types. The generated implementations directly delegate
112/// to the implementation of the inner type.
113///
114/// ```rust,ignore
115/// #[derive(sqlx::Type)]
116/// #[sqlx(transparent)]
117/// struct UserId(i64);
118/// ```
119///
120/// ##### Note: `PgHasArrayType`
121/// If you have the `postgres` feature enabled, this derive also generates a `PgHasArrayType` impl
122/// so that you may use it with `Vec` and other types that decode from an array in Postgres:
123///
124/// ```rust,ignore
125/// let user_ids: Vec<UserId> = sqlx::query_scalar("select '{ 123, 456 }'::int8[]")
126///    .fetch(&mut pg_connection)
127///    .await?;
128/// ```
129///
130/// However, if you are wrapping a type that does not implement `PgHasArrayType`
131/// (e.g. `Vec` itself, because we don't currently support multidimensional arrays),
132/// you may receive an error:
133///
134/// ```rust,ignore
135/// #[derive(sqlx::Type)] // ERROR: `Vec<i64>` does not implement `PgHasArrayType`
136/// #[sqlx(transparent)]
137/// struct UserIds(Vec<i64>);
138/// ```
139///
140/// To remedy this, add `#[sqlx(no_pg_array)]`, which disables the generation
141/// of the `PgHasArrayType` impl:
142///
143/// ```rust,ignore
144/// #[derive(sqlx::Type)]
145/// #[sqlx(transparent, no_pg_array)]
146/// struct UserIds(Vec<i64>);
147/// ```
148///
149/// ##### Attributes
150///
151/// * `#[sqlx(type_name = "<SQL type name>")]` on struct definition: instead of inferring the SQL
152///   type name from the inner field (in the above case, `BIGINT`), explicitly set it to
153///   `<SQL type name>` instead. May trigger errors or unexpected behavior if the encoding of the
154///   given type is different than that of the inferred type (e.g. if you rename the above to
155///   `VARCHAR`). Affects Postgres only.
156/// * `#[sqlx(rename_all = "<strategy>")]` on struct definition: See [`derive docs in FromRow`](crate::from_row::FromRow#rename_all)
157/// * `#[sqlx(no_pg_array)]`: do not emit a `PgHasArrayType` impl (see above).
158///
159/// ### Enumeration
160///
161/// Enumerations may be defined in Rust and can match SQL by
162/// integer discriminant or variant name.
163///
164/// With `#[repr(_)]` the integer representation is used when converting from/to SQL and expects
165/// that SQL type (e.g., `INT`). Without, the names of the variants are used instead and
166/// expects a textual SQL type (e.g., `VARCHAR`, `TEXT`).
167///
168/// ```rust,ignore
169/// #[derive(sqlx::Type)]
170/// #[repr(i32)]
171/// enum Color { Red = 1, Green = 2, Blue = 3 }
172/// ```
173///
174/// ```rust,ignore
175/// #[derive(sqlx::Type)]
176/// #[sqlx(type_name = "color")] // only for PostgreSQL to match a type definition
177/// #[sqlx(rename_all = "lowercase")]
178/// enum Color { Red, Green, Blue }
179/// ```
180///
181/// ### Records
182///
183/// User-defined composite types are supported through deriving a `struct`.
184///
185/// This is only supported for PostgreSQL.
186///
187/// ```rust,ignore
188/// #[derive(sqlx::Type)]
189/// #[sqlx(type_name = "interface_type")]
190/// struct InterfaceType {
191///     name: String,
192///     supplier_id: i32,
193///     price: f64
194/// }
195/// ```
196pub trait Type<DB: Database> {
197    /// Returns the canonical SQL type for this Rust type.
198    ///
199    /// When binding arguments, this is used to tell the database what is about to be sent; which,
200    /// the database then uses to guide query plans. This can be overridden by `Encode::produces`.
201    ///
202    /// A map of SQL types to Rust types is populated with this and used
203    /// to determine the type that is returned from the anonymous struct type from `query!`.
204    fn type_info() -> DB::TypeInfo;
205
206    /// Determines if this Rust type is compatible with the given SQL type.
207    ///
208    /// When decoding values from a row, this method is checked to determine if we should continue
209    /// or raise a runtime type mismatch error.
210    ///
211    /// When binding arguments with `query!` or `query_as!`, this method is consulted to determine
212    /// if the Rust type is acceptable.
213    ///
214    /// Defaults to checking [`TypeInfo::type_compatible()`].
215    fn compatible(ty: &DB::TypeInfo) -> bool {
216        Self::type_info().type_compatible(ty)
217    }
218}
219
220// for references, the underlying SQL type is identical
221impl<T: ?Sized + Type<DB>, DB: Database> Type<DB> for &'_ T {
222    fn type_info() -> DB::TypeInfo {
223        <T as Type<DB>>::type_info()
224    }
225
226    fn compatible(ty: &DB::TypeInfo) -> bool {
227        <T as Type<DB>>::compatible(ty)
228    }
229}
230
231// for optionals, the underlying SQL type is identical
232impl<T: Type<DB>, DB: Database> Type<DB> for Option<T> {
233    fn type_info() -> DB::TypeInfo {
234        <T as Type<DB>>::type_info()
235    }
236
237    fn compatible(ty: &DB::TypeInfo) -> bool {
238        ty.is_null() || <T as Type<DB>>::compatible(ty)
239    }
240}