sqlx_postgres/types/mod.rs
1//! Conversions between Rust and **Postgres** types.
2//!
3//! # Types
4//!
5//! | Rust type | Postgres type(s) |
6//! |---------------------------------------|------------------------------------------------------|
7//! | `bool` | BOOL |
8//! | `i8` | "CHAR" |
9//! | `i16` | SMALLINT, SMALLSERIAL, INT2 |
10//! | `i32` | INT, SERIAL, INT4 |
11//! | `i64` | BIGINT, BIGSERIAL, INT8 |
12//! | `f32` | REAL, FLOAT4 |
13//! | `f64` | DOUBLE PRECISION, FLOAT8 |
14//! | `&str`, [`String`] | VARCHAR, CHAR(N), TEXT, NAME, CITEXT |
15//! | `&[u8]`, `Vec<u8>` | BYTEA |
16//! | `()` | VOID |
17//! | [`PgInterval`] | INTERVAL |
18//! | [`PgRange<T>`](PgRange) | INT8RANGE, INT4RANGE, TSRANGE, TSTZRANGE, DATERANGE, NUMRANGE |
19//! | [`PgMoney`] | MONEY |
20//! | [`PgLTree`] | LTREE |
21//! | [`PgLQuery`] | LQUERY |
22//! | [`PgCiText`] | CITEXT<sup>1</sup> |
23//!
24//! <sup>1</sup> SQLx generally considers `CITEXT` to be compatible with `String`, `&str`, etc.,
25//! but this wrapper type is available for edge cases, such as `CITEXT[]` which Postgres
26//! does not consider to be compatible with `TEXT[]`.
27//!
28//! ### [`bigdecimal`](https://crates.io/crates/bigdecimal)
29//! Requires the `bigdecimal` Cargo feature flag.
30//!
31//! | Rust type | Postgres type(s) |
32//! |---------------------------------------|------------------------------------------------------|
33//! | `bigdecimal::BigDecimal` | NUMERIC |
34//!
35#![doc=include_str!("bigdecimal-range.md")]
36//!
37//! ### [`rust_decimal`](https://crates.io/crates/rust_decimal)
38//! Requires the `rust_decimal` Cargo feature flag.
39//!
40//! | Rust type | Postgres type(s) |
41//! |---------------------------------------|------------------------------------------------------|
42//! | `rust_decimal::Decimal` | NUMERIC |
43//!
44#![doc=include_str!("rust_decimal-range.md")]
45//!
46//! ### [`chrono`](https://crates.io/crates/chrono)
47//!
48//! Requires the `chrono` Cargo feature flag.
49//!
50//! | Rust type | Postgres type(s) |
51//! |---------------------------------------|------------------------------------------------------|
52//! | `chrono::DateTime<Utc>` | TIMESTAMPTZ |
53//! | `chrono::DateTime<Local>` | TIMESTAMPTZ |
54//! | `chrono::NaiveDateTime` | TIMESTAMP |
55//! | `chrono::NaiveDate` | DATE |
56//! | `chrono::NaiveTime` | TIME |
57//! | [`PgTimeTz`] | TIMETZ |
58//!
59//! ### [`time`](https://crates.io/crates/time)
60//!
61//! Requires the `time` Cargo feature flag.
62//!
63//! | Rust type | Postgres type(s) |
64//! |---------------------------------------|------------------------------------------------------|
65//! | `time::PrimitiveDateTime` | TIMESTAMP |
66//! | `time::OffsetDateTime` | TIMESTAMPTZ |
67//! | `time::Date` | DATE |
68//! | `time::Time` | TIME |
69//! | [`PgTimeTz`] | TIMETZ |
70//!
71//! ### [`uuid`](https://crates.io/crates/uuid)
72//!
73//! Requires the `uuid` Cargo feature flag.
74//!
75//! | Rust type | Postgres type(s) |
76//! |---------------------------------------|------------------------------------------------------|
77//! | `uuid::Uuid` | UUID |
78//!
79//! ### [`ipnetwork`](https://crates.io/crates/ipnetwork)
80//!
81//! Requires the `ipnetwork` Cargo feature flag.
82//!
83//! | Rust type | Postgres type(s) |
84//! |---------------------------------------|------------------------------------------------------|
85//! | `ipnetwork::IpNetwork` | INET, CIDR |
86//! | `std::net::IpAddr` | INET, CIDR |
87//!
88//! Note that because `IpAddr` does not support network prefixes, it is an error to attempt to decode
89//! an `IpAddr` from a `INET` or `CIDR` value with a network prefix smaller than the address' full width:
90//! `/32` for IPv4 addresses and `/128` for IPv6 addresses.
91//!
92//! `IpNetwork` does not have this limitation.
93//!
94//! ### [`mac_address`](https://crates.io/crates/mac_address)
95//!
96//! Requires the `mac_address` Cargo feature flag.
97//!
98//! | Rust type | Postgres type(s) |
99//! |---------------------------------------|------------------------------------------------------|
100//! | `mac_address::MacAddress` | MACADDR |
101//!
102//! ### [`bit-vec`](https://crates.io/crates/bit-vec)
103//!
104//! Requires the `bit-vec` Cargo feature flag.
105//!
106//! | Rust type | Postgres type(s) |
107//! |---------------------------------------|------------------------------------------------------|
108//! | `bit_vec::BitVec` | BIT, VARBIT |
109//!
110//! ### [`json`](https://crates.io/crates/serde_json)
111//!
112//! Requires the `json` Cargo feature flag.
113//!
114//! | Rust type | Postgres type(s) |
115//! |---------------------------------------|------------------------------------------------------|
116//! | [`Json<T>`] | JSON, JSONB |
117//! | `serde_json::Value` | JSON, JSONB |
118//! | `&serde_json::value::RawValue` | JSON, JSONB |
119//!
120//! `Value` and `RawValue` from `serde_json` can be used for unstructured JSON data with
121//! Postgres.
122//!
123//! [`Json<T>`](crate::types::Json) can be used for structured JSON data with Postgres.
124//!
125//! # [Composite types](https://www.postgresql.org/docs/current/rowtypes.html)
126//!
127//! User-defined composite types are supported through a derive for `Type`.
128//!
129//! ```text
130//! CREATE TYPE inventory_item AS (
131//! name text,
132//! supplier_id integer,
133//! price numeric
134//! );
135//! ```
136//!
137//! ```rust,ignore
138//! #[derive(sqlx::Type)]
139//! #[sqlx(type_name = "inventory_item")]
140//! struct InventoryItem {
141//! name: String,
142//! supplier_id: i32,
143//! price: BigDecimal,
144//! }
145//! ```
146//!
147//! Anonymous composite types are represented as tuples. Note that anonymous composites may only
148//! be returned and not sent to Postgres (this is a limitation of postgres).
149//!
150//! # Arrays
151//!
152//! One-dimensional arrays are supported as `Vec<T>` or `&[T]` where `T` implements `Type`.
153//!
154//! # [Enumerations](https://www.postgresql.org/docs/current/datatype-enum.html)
155//!
156//! User-defined enumerations are supported through a derive for `Type`.
157//!
158//! ```text
159//! CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
160//! ```
161//!
162//! ```rust,ignore
163//! #[derive(sqlx::Type)]
164//! #[sqlx(type_name = "mood", rename_all = "lowercase")]
165//! enum Mood { Sad, Ok, Happy }
166//! ```
167//!
168//! Rust enumerations may also be defined to be represented as an integer using `repr`.
169//! The following type expects a SQL type of `INTEGER` or `INT4` and will convert to/from the
170//! Rust enumeration.
171//!
172//! ```rust,ignore
173//! #[derive(sqlx::Type)]
174//! #[repr(i32)]
175//! enum Mood { Sad = 0, Ok = 1, Happy = 2 }
176//! ```
177//!
178
179use crate::type_info::PgTypeKind;
180use crate::{PgTypeInfo, Postgres};
181
182pub(crate) use sqlx_core::types::{Json, Type};
183
184mod array;
185mod bool;
186mod bytes;
187mod citext;
188mod float;
189mod int;
190mod interval;
191mod lquery;
192mod ltree;
193// Not behind a Cargo feature because we require JSON in the driver implementation.
194mod json;
195mod money;
196mod oid;
197mod range;
198mod record;
199mod str;
200mod text;
201mod tuple;
202mod void;
203
204#[cfg(any(feature = "chrono", feature = "time"))]
205mod time_tz;
206
207#[cfg(feature = "bigdecimal")]
208mod bigdecimal;
209
210#[cfg(any(feature = "bigdecimal", feature = "rust_decimal"))]
211mod numeric;
212
213#[cfg(feature = "rust_decimal")]
214mod rust_decimal;
215
216#[cfg(feature = "chrono")]
217mod chrono;
218
219#[cfg(feature = "time")]
220mod time;
221
222#[cfg(feature = "uuid")]
223mod uuid;
224
225#[cfg(feature = "ipnetwork")]
226mod ipnetwork;
227
228#[cfg(feature = "ipnetwork")]
229mod ipaddr;
230
231#[cfg(feature = "mac_address")]
232mod mac_address;
233
234#[cfg(feature = "bit-vec")]
235mod bit_vec;
236
237pub use array::PgHasArrayType;
238pub use citext::PgCiText;
239pub use interval::PgInterval;
240pub use lquery::PgLQuery;
241pub use lquery::PgLQueryLevel;
242pub use lquery::PgLQueryVariant;
243pub use lquery::PgLQueryVariantFlag;
244pub use ltree::PgLTree;
245pub use ltree::PgLTreeLabel;
246pub use ltree::PgLTreeParseError;
247pub use money::PgMoney;
248pub use oid::Oid;
249pub use range::PgRange;
250
251#[cfg(any(feature = "chrono", feature = "time"))]
252pub use time_tz::PgTimeTz;
253
254// used in derive(Type) for `struct`
255// but the interface is not considered part of the public API
256#[doc(hidden)]
257pub use record::{PgRecordDecoder, PgRecordEncoder};
258
259// Type::compatible impl appropriate for arrays
260fn array_compatible<E: Type<Postgres> + ?Sized>(ty: &PgTypeInfo) -> bool {
261 // we require the declared type to be an _array_ with an
262 // element type that is acceptable
263 if let PgTypeKind::Array(element) = &ty.kind() {
264 return E::compatible(&element);
265 }
266
267 false
268}