Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Type System

QAIL provides type conversion between Rust and PostgreSQL.

Supported Types

Rust TypePostgreSQL TypeNotes
StringTEXT, VARCHARUTF-8
i32INT432-bit integer
i64INT8, BIGINT64-bit integer
f64FLOAT8Double precision
boolBOOLEAN
UuidUUID128-bit
TimestampTIMESTAMPMicrosecond precision
DateDATE
TimeTIME
JsonJSON, JSONB
DecimalNUMERICArbitrary precision

Compile-Time Type Safety

QAIL uses the ColumnType enum for compile-time validation in schema definitions:

#![allow(unused)]
fn main() {
use qail_core::migrate::{Column, ColumnType};

// ✅ Compile-time enforced - no typos possible
Column::new("id", ColumnType::Uuid).primary_key()
Column::new("name", ColumnType::Text).not_null()
Column::new("email", ColumnType::Varchar(Some(255))).unique()

// Available types:
// Uuid, Text, Varchar, Int, BigInt, Serial, BigSerial,
// Bool, Float, Decimal, Jsonb, Timestamp, Timestamptz, Date, Time, Bytea
}

Validation at compile time:

  • primary_key() validates the type can be a PK (UUID, INT, SERIAL)
  • unique() validates the type supports indexing (not JSONB, BYTEA)

Usage

Reading Values

#![allow(unused)]
fn main() {
use qail_pg::types::{Timestamp, Uuid, Json};

for row in rows {
    let id: i32 = row.get("id")?;
    let uuid: Uuid = row.get("uuid")?;
    let created: Timestamp = row.get("created_at")?;
    let data: Json = row.get("metadata")?;
}
}

Temporal Types

#![allow(unused)]
fn main() {
use qail_pg::types::{Timestamp, Date, Time};

// Timestamp with microsecond precision
let ts = Timestamp::from_micros(1703520000000000);

// Date only
let date = Date::from_ymd(2024, 1, 15);

// Time only
let time = Time::from_hms(14, 30, 0);
}

JSON

#![allow(unused)]
fn main() {
use qail_pg::types::Json;

let json = Json("{"key": "value"}".to_string());
}

Custom Types

Implement FromPg and ToPg for custom types:

#![allow(unused)]
fn main() {
use qail_pg::types::{FromPg, ToPg, TypeError};

impl FromPg for MyType {
    fn from_pg(bytes: &[u8], oid: u32, format: i16) -> Result<Self, TypeError> {
        // Decode from wire format
    }
}

impl ToPg for MyType {
    fn to_pg(&self) -> (Vec<u8>, u32, i16) {
        // Encode to wire format
        (bytes, oid, format)
    }
}
}