sqlx_build_trust_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 = "json")]
28#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
29mod json;
30
31mod text;
32
33#[cfg(feature = "uuid")]
34#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))]
35#[doc(no_inline)]
36pub use uuid::{self, Uuid};
37
38#[cfg(feature = "chrono")]
39#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
40pub mod chrono {
41 #[doc(no_inline)]
42 pub use chrono::{
43 DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc,
44 };
45}
46
47#[cfg(feature = "bit-vec")]
48#[cfg_attr(docsrs, doc(cfg(feature = "bit-vec")))]
49#[doc(no_inline)]
50pub use bit_vec::BitVec;
51
52#[cfg(feature = "time")]
53#[cfg_attr(docsrs, doc(cfg(feature = "time")))]
54pub mod time {
55 #[doc(no_inline)]
56 pub use time::{Date, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset};
57}
58
59#[cfg(feature = "bigdecimal")]
60#[cfg_attr(docsrs, doc(cfg(feature = "bigdecimal")))]
61#[doc(no_inline)]
62pub use bigdecimal::BigDecimal;
63
64#[cfg(feature = "rust_decimal")]
65#[cfg_attr(docsrs, doc(cfg(feature = "rust_decimal")))]
66#[doc(no_inline)]
67pub use rust_decimal::Decimal;
68
69#[cfg(feature = "ipnetwork")]
70#[cfg_attr(docsrs, doc(cfg(feature = "ipnetwork")))]
71pub mod ipnetwork {
72 #[doc(no_inline)]
73 pub use ipnetwork::{IpNetwork, Ipv4Network, Ipv6Network};
74}
75
76#[cfg(feature = "mac_address")]
77#[cfg_attr(docsrs, doc(cfg(feature = "mac_address")))]
78pub mod mac_address {
79 #[doc(no_inline)]
80 pub use mac_address::MacAddress;
81}
82
83#[cfg(feature = "json")]
84pub use json::{Json, JsonRawValue, JsonValue};
85
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/// ```
196///
197pub trait Type<DB: Database> {
198 /// Returns the canonical SQL type for this Rust type.
199 ///
200 /// When binding arguments, this is used to tell the database what is about to be sent; which,
201 /// the database then uses to guide query plans. This can be overridden by `Encode::produces`.
202 ///
203 /// A map of SQL types to Rust types is populated with this and used
204 /// to determine the type that is returned from the anonymous struct type from `query!`.
205 fn type_info() -> DB::TypeInfo;
206
207 /// Determines if this Rust type is compatible with the given SQL type.
208 ///
209 /// When decoding values from a row, this method is checked to determine if we should continue
210 /// or raise a runtime type mismatch error.
211 ///
212 /// When binding arguments with `query!` or `query_as!`, this method is consulted to determine
213 /// if the Rust type is acceptable.
214 fn compatible(ty: &DB::TypeInfo) -> bool {
215 *ty == Self::type_info()
216 }
217}
218
219// for references, the underlying SQL type is identical
220impl<T: ?Sized + Type<DB>, DB: Database> Type<DB> for &'_ T {
221 fn type_info() -> DB::TypeInfo {
222 <T as Type<DB>>::type_info()
223 }
224
225 fn compatible(ty: &DB::TypeInfo) -> bool {
226 <T as Type<DB>>::compatible(ty)
227 }
228}
229
230// for optionals, the underlying SQL type is identical
231impl<T: Type<DB>, DB: Database> Type<DB> for Option<T> {
232 fn type_info() -> DB::TypeInfo {
233 <T as Type<DB>>::type_info()
234 }
235
236 fn compatible(ty: &DB::TypeInfo) -> bool {
237 <T as Type<DB>>::compatible(ty)
238 }
239}