Tipos Postgres-Rust
| Rust type | Postgres type(s) |
|---|---|
bool | BOOL |
i8 | “CHAR” |
i16 | SMALLINT, SMALLSERIAL, INT2 |
i32 | INT, SERIAL, INT4 |
i64 | BIGINT, BIGSERIAL, INT8 |
f32 | REAL, FLOAT4 |
f64 | DOUBLE PRECISION, FLOAT8 |
&str, String | VARCHAR, CHAR(N), TEXT, NAME, CITEXT |
&[u8], Vec<u8> | BYTEA |
() | VOID |
PgMoney | MONEY |
NUMERIC
- Requiere la feature bigdecimal o rust_decimal y también el crate para el tipo elegido
- NUMERIC no devuelve
f32of64sino que devuelvedecimal - BigDecimal puede representar valores con un rango mucho mayor que el tipo NUMERIC en Postgres.
- RustDecimal tiene un rango más pequeño que NUMERIC
- NUMERIC puede representar todos los valores posibles de
rust_decimal::Decimal, pero no al revés. Esto significa que la codificación nunca debería fallar, pero la decodificación sí
| Rust type | Postgres type(s) |
|---|---|
bigdecimal::BigDecimal | NUMERIC |
rust_decimal::Decimal | NUMERIC |
Tiempo
Siempre que el dato represente un momento real en el tiempo (como created_at, updated_at, etc.) usar:
TIMESTAMPTZen Postgreschrono::DateTime<Utc>otime::OffsetDateTimeen Rust- Cuando no se guarda con UTC o zona horaria, si se lee en otras regiones puede cambiar el significado
Usar tipos sin zona horaria (TIMESTAMP, PrimitiveDateTime, etc.) solo si:
- La zona no importa (ej: horarios fijos)
- No se está representando un instante real en el tiempo global
Time
- Requiere la feature
timey el cratetime
| Rust type | Postgres type(s) | Descripción | Example |
|---|---|---|---|
time::PrimitiveDateTime | TIMESTAMP | Fecha y hora sin zona horaria | 2025-04-15 18:30:00 |
time::OffsetDateTime | TIMESTAMPTZ | Fecha y hora con zona horaria (offset) | 2025-04-15 18:30:00+00 |
time::Date | DATE | Solo la fecha | 2025-04-15 |
time::Time | TIME | Solo la hora | 18:30:00 |
PgTimeTz | TIMETZ | Hora con zona horaria | 18:30:00-05 |
Chrono
- Requiere la feature
chronoy el cratechrono
| Rust type | Postgres type(s) | Descripción | Example |
|---|---|---|---|
chrono::DateTime<Utc> | TIMESTAMPTZ | Fecha y hora en UTC | 2025-04-15 18:30:00+00 |
chrono::DateTime<Local> | TIMESTAMPTZ | Fecha y hora en zona local | 2025-04-15 13:30:00-05 |
chrono::NaiveDateTime | TIMESTAMP | Fecha y hora sin zona horaria | 2025-04-15 18:30:00 |
chrono::NaiveDate | DATE | Solo la fecha | 2025-04-15 |
chrono::NaiveTime | TIME | Solo la hora | 18:30:00 |
PgTimeTz | TIMETZ | Hora con zona horaria | 18:30:00-05 |
Uuid
- Requiere la feature
uuidy el crateuuid
| Rust type | Postgres type(s) |
|---|---|
uuid::Uuid | UUID |
Json
- Requiere la feature
json ValueyRawValuedeserde_jsonse pueden utilizar para datos JSON no estructurados con Postgres.sqlx::types::Json<T>se puede utilizar para datos JSON estructurados con Postgres.
| Rust type | Postgres type(s) |
|---|---|
sqlx::types::Json<T> | JSON, JSONB |
serde_json::Value | JSON, JSONB |
&serde_json::value::RawValue | JSON, JSONB |
Vectores
| Rust type | Postgres type(s) |
|---|---|
Vec<T> o &[T] | ARRAY |
Enums
Enum nativo de PostgreSQL
Aquí el enum se mapea al tipo mood que se crea en PostgreSQL con CREATE TYPE mood AS ENUM (...). Los valores se almacenan como un enum real de PostgreSQL.
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
#[derive(sqlx::Type)]
#[sqlx(type_name = "mood", rename_all = "lowercase")]
enum Mood { Sad, Ok, Happy }
Como entero
Las enumeraciones de Rust también pueden definirse para representarse como un entero mediante repr. El siguiente tipo espera un tipo SQL INTEGERo INT4 y se convertirá a/desde la enumeración de Rust.
#[derive(sqlx::Type)]
#[repr(i32)]
enum Mood {
Sad = 0,
Ok = 1,
Happy = 2
}
Como texto Los valores se almacenan como strings ("Sad", "Ok", "Happy") en una columna TEXT regular de PostgreSQL.
La ventaja de usar type_name = "text" es que no se necesita crear un tipo enum personalizado en PostgreSQL - se utiliza cualquier columna de tipo TEXT existente. SQLx automáticamente convierte entre los valores del enum de Rust y las strings en la base de datos.
Es útil cuando se trabaja con bases de datos existentes que ya tienen columnas de texto para representar estados o categorías, o cuando se requiere más flexibilidad sin definir tipos personalizados en PostgreSQL.
#[derive(sqlx::Type)]
#[sqlx(type_name = "text")]
enum Mood { Sad, Ok, Happy }
Ejemplo
# Base de datos (PostgreSQL)
sqlx = { version = "0.8.1", features = [
"runtime-tokio",
"tls-rustls-ring",
"postgres",
"uuid",
"time",
"rust_decimal",
] }
# Para algunos tipos de la base de datos
uuid = { version = "1.10.0", features = ["v4", "serde"] }
time = { version = "=0.3.36" }
rust_decimal = "1.36"