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