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//!
20
21use crate::database::Database;
22
23#[cfg(feature = "bstr")]
24#[cfg_attr(docsrs, doc(cfg(feature = "bstr")))]
25pub mod bstr;
26
27#[cfg(feature = "git2")]
28#[cfg_attr(docsrs, doc(cfg(feature = "git2")))]
29pub mod git2;
30
31#[cfg(feature = "json")]
32#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
33mod json;
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
66#[cfg(feature = "decimal")]
67#[cfg_attr(docsrs, doc(cfg(feature = "decimal")))]
68#[doc(no_inline)]
69pub use rust_decimal::Decimal;
70
71#[cfg(feature = "ipnetwork")]
72#[cfg_attr(docsrs, doc(cfg(feature = "ipnetwork")))]
73pub mod ipnetwork {
74    #[doc(no_inline)]
75    pub use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
76}
77
78#[cfg(feature = "mac_address")]
79#[cfg_attr(docsrs, doc(cfg(feature = "mac_address")))]
80pub mod mac_address {
81    #[doc(no_inline)]
82    pub use mac_address::MacAddress;
83}
84
85#[cfg(feature = "json")]
86pub use json::{Json, JsonRawValue, JsonValue};
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 or 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/// ##### Attributes
121///
122/// * `#[sqlx(type_name = "<SQL type name>")]` on struct definition: instead of inferring the SQL
123///   type name from the inner field (in the above case, `BIGINT`), explicitly set it to
124///   `<SQL type name>` instead. May trigger errors or unexpected behavior if the encoding of the
125///   given type is different than that of the inferred type (e.g. if you rename the above to
126///   `VARCHAR`). Affects Postgres only.
127/// * `#[sqlx(rename_all = "<strategy>")]` on struct definition: See [`derive docs in FromRow`](crate::from_row::FromRow#rename_all)
128///
129/// ### Enumeration
130///
131/// Enumerations may be defined in Rust and can match SQL by
132/// integer discriminant or variant name.
133///
134/// With `#[repr(_)]` the integer representation is used when converting from/to SQL and expects
135/// that SQL type (e.g., `INT`). Without, the names of the variants are used instead and
136/// expects a textual SQL type (e.g., `VARCHAR`, `TEXT`).
137///
138/// ```rust,ignore
139/// #[derive(sqlx::Type)]
140/// #[repr(i32)]
141/// enum Color { Red = 1, Green = 2, Blue = 3 }
142/// ```
143///
144/// ```rust,ignore
145/// #[derive(sqlx::Type)]
146/// #[sqlx(type_name = "color")] // only for PostgreSQL to match a type definition
147/// #[sqlx(rename_all = "lowercase")]
148/// enum Color { Red, Green, Blue }
149/// ```
150///
151/// ### Records
152///
153/// User-defined composite types are supported through deriving a `struct`.
154///
155/// This is only supported for PostgreSQL.
156///
157/// ```rust,ignore
158/// #[derive(sqlx::Type)]
159/// #[sqlx(type_name = "interface_type")]
160/// struct InterfaceType {
161///     name: String,
162///     supplier_id: i32,
163///     price: f64
164/// }
165/// ```
166///
167pub trait Type<DB: Database> {
168    /// Returns the canonical SQL type for this Rust type.
169    ///
170    /// When binding arguments, this is used to tell the database what is about to be sent; which,
171    /// the database then uses to guide query plans. This can be overridden by `Encode::produces`.
172    ///
173    /// A map of SQL types to Rust types is populated with this and used
174    /// to determine the type that is returned from the anonymous struct type from `query!`.
175    fn type_info() -> DB::TypeInfo;
176
177    /// Determines if this Rust type is compatible with the given SQL type.
178    ///
179    /// When decoding values from a row, this method is checked to determine if we should continue
180    /// or raise a runtime type mismatch error.
181    ///
182    /// When binding arguments with `query!` or `query_as!`, this method is consulted to determine
183    /// if the Rust type is acceptable.
184    fn compatible(ty: &DB::TypeInfo) -> bool {
185        *ty == Self::type_info()
186    }
187}
188
189// for references, the underlying SQL type is identical
190impl<T: ?Sized + Type<DB>, DB: Database> Type<DB> for &'_ T {
191    fn type_info() -> DB::TypeInfo {
192        <T as Type<DB>>::type_info()
193    }
194
195    fn compatible(ty: &DB::TypeInfo) -> bool {
196        <T as Type<DB>>::compatible(ty)
197    }
198}
199
200// for optionals, the underlying SQL type is identical
201impl<T: Type<DB>, DB: Database> Type<DB> for Option<T> {
202    fn type_info() -> DB::TypeInfo {
203        <T as Type<DB>>::type_info()
204    }
205
206    fn compatible(ty: &DB::TypeInfo) -> bool {
207        <T as Type<DB>>::compatible(ty)
208    }
209}