SQLx bridges Rust and SQL through three core traits:Documentation Index
Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt
Use this file to discover all available pages before exploring further.
Type, Encode, and Decode. Every value you bind as a query parameter or read back from a row passes through this system. Understanding how the traits compose helps you extend SQLx with custom types and choose the right feature flags for your project.
The three core traits
Type
Declares which SQL type corresponds to a Rust type and whether a given SQL type is compatible at runtime.
Encode
Serialises a Rust value into the database’s wire format when binding query parameters.
Decode
Deserialises a raw database value into a Rust type when reading a row column.
The Type trait
Type<DB> tells SQLx what SQL type a Rust type corresponds to and how to check compatibility:
type_info() is called when binding arguments so the database can plan the query correctly. compatible() is checked when decoding a column value to prevent silent type mismatches at runtime.
Option<T> automatically implements Type<DB> for any T: Type<DB>. The SQL type is the same as the inner type; NULL is handled at the Encode/Decode level.
The Encode trait
Encode<'q, DB> converts a Rust value into bytes in the buffer that SQLx sends to the database:
encode is preferred because it can move the value and reuse existing allocations. encode_by_ref is the required method; encode has a default implementation that delegates to it.
The return type, IsNull, signals whether the encoded value should be treated as SQL NULL:
Arc<T>, Box<T>, Rc<T>, Cow<'_, T>) all forward to the inner Encode implementation automatically, so you can bind owned or borrowed values interchangeably.
The Decode trait
Decode<'r, DB> reads a raw value from the database wire format into a Rust type:
'r lifetime ties the decoded value to the lifetime of the row being read. Option<T> is implemented automatically: if the column value is NULL, None is returned without calling T::decode.
A common pattern is to delegate decoding to a type you already support, then parse from there:
Built-in type mappings
SQLx ships with implementations for common Rust primitives. The exact SQL type names vary by database; the table below lists the Rust types and their general SQL counterparts.| Rust type | SQL type |
|---|---|
bool | BOOLEAN |
i8 | TINYINT / SMALLINT |
i16 | SMALLINT |
i32 | INT / INTEGER |
i64 | BIGINT |
u8 | TINYINT UNSIGNED |
u16 | SMALLINT UNSIGNED |
u32 | INT UNSIGNED |
u64 | BIGINT UNSIGNED |
f32 | FLOAT / REAL |
f64 | DOUBLE / DOUBLE PRECISION |
String / &str | VARCHAR / TEXT / CHAR |
Vec<u8> / &[u8] | BLOB / BYTEA / VARBINARY |
Option<T> | Nullable version of T’s SQL type |
Not all integer widths are supported by every database. PostgreSQL does not have unsigned integer types; MySQL has all widths listed. Check your database’s type documentation for details.
Optional type integrations
Additional Rust types are enabled through Cargo feature flags. Add the relevant features to yourCargo.toml [dependencies] entry for sqlx.
| Feature flag | Rust type(s) | SQL type |
|---|---|---|
uuid | uuid::Uuid | UUID |
chrono | chrono::NaiveDate, NaiveTime, NaiveDateTime, DateTime<Tz> | DATE, TIME, TIMESTAMP, TIMESTAMPTZ |
time | time::Date, Time, PrimitiveDateTime, OffsetDateTime | DATE, TIME, TIMESTAMP, TIMESTAMPTZ |
json | serde_json::Value, sqlx::types::Json<T>, sqlx::types::JsonRawValue | JSON, JSONB |
bigdecimal | bigdecimal::BigDecimal | NUMERIC / DECIMAL |
rust_decimal | rust_decimal::Decimal | NUMERIC / DECIMAL |
ipnet | ipnet::IpNet, Ipv4Net, Ipv6Net | INET, CIDR (PostgreSQL only) |
ipnetwork | ipnetwork::IpNetwork, Ipv4Network, Ipv6Network | INET, CIDR (PostgreSQL only) |
mac_address | mac_address::MacAddress | MACADDR (PostgreSQL only) |
bit-vec | bit_vec::BitVec | BIT, VARBIT (PostgreSQL only) |
bstr | bstr::BString | BLOB / BYTEA |
Cargo.toml:
Resolving chrono / time ambiguity with sqlx.toml
When bothchrono and time are enabled, add an sqlx.toml at your workspace root to tell the macro which crate to map date/time columns to:
query! and query_as! macro output. Runtime encoding and decoding work for both crates regardless.
Smart pointer pass-through
Type, Encode, and Decode are all implemented for Arc<T>, Box<T>, Rc<T>, and Cow<'_, T> when the inner type supports them. You can bind a Box<str> or Arc<String> directly without any conversion.