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

QAIL Zig Documentation

Zig-first PostgreSQL wire-protocol driver with AST-native query building, PostgreSQL-path parity tracking against qail.rs, and optional Linux Kerberos/GSSENC integration via the platform GSSAPI stack.

QAIL Zig is the active Zig implementation of the QAIL PostgreSQL stack. It shares the same AST direction as qail.rs, but keeps the runtime, protocol path, and tooling in Zig. The core driver path is Zig-native; Linux Kerberos/GSSENC support is an optional runtime integration with system libc/GSSAPI rather than a self-contained Zig Kerberos stack. Full qail.rs ecosystem parity is still incomplete outside the PostgreSQL-focused track.

Latest Updates (May 2026)

  • qail-zig remains on the v0.8.3 release line; the current main branch carries additional post-v0.8.3 API hardening.
  • The current public API is AST-native: QailCmd, typed Expr values, PgDriver, PgPool, Pipeline, COPY helpers, RLS helpers, and explicit URL/options connection APIs.
  • Public raw SQL inputs and nested raw escape hatches are not part of the current driver API; public runtime and transpiler paths fail closed.
  • Cursor SQL helpers, trusted/raw compatibility helpers, and data-safety raw helper modules are internal implementation details.
  • CLI parity work now includes branch management, codegen tools, migration receipt hardening, and live PostgreSQL validation for exec, seed, pull, and migrate status|plan|up|down.
  • Current repository snapshot: 56,749 tracked text lines total, including 53,426 lines of Zig across 172 tracked .zig files.
  • The current qail.rs reference size for parity tracking is 210,593 total tracked lines.

Repository Snapshot

  • Total LOC: 56,749 tracked text lines in qail-zig.
  • Zig LOC: 53,426 lines across 172 tracked .zig files.
  • qail.rs total LOC: 210,593 tracked lines.
.
├── src/                # Driver, AST, parser, protocol, runtime, CLI, tests, benches
├── scripts/            # Codegen, parity, and policy guards
├── docs/               # mdBook pages and theme overrides
├── .github/workflows/  # CI workflows
├── build.zig           # Build graph and targets
└── PARITY_AST_PG_DRIVER.md

What QAIL Zig Covers

AreaStatus
PostgreSQL driver✅ Active
Connection pooling✅ Active
Prepared pipelines✅ Active
COPY in/out helpers✅ Active
TLS✅ Active
Logical replication core✅ Active
CLI✅ Active
Editor LSP (via qail.rs extension)✅ External
Security hardening suites✅ Active
qail.rs parity tracking✅ Active

Implementation Positioning

  • qail.rs is still the production reference and widest implementation.
  • qail-zig is the serious Zig track, with active parity work and dedicated benchmarks.
  • Security boundary: on the AST flow, the goal remains no application SQL string interpolation surface.

Docs Map

Installation

Requirements

  • Zig 0.16+
  • PostgreSQL 14+
  • macOS, Linux, or another platform supported by the Zig toolchain

Clone and Build

git clone https://github.com/qail-io/qail-zig.git
cd qail-zig
zig build -Doptimize=ReleaseFast

Optional Wrapper

./scripts/zigw is a thin convenience wrapper for common repo tasks.

Examples:

./scripts/zigw doctor
./scripts/zigw test
./scripts/zigw pgzig-bench qail single --workload point

./scripts/zigw delegates to normal zig build commands.

Docs Build

The Zig docs book is configured to publish into the existing dev.qail.io tree at public/zig/docs.

cd docs
mdbook build

Quick Start

const std = @import("std");
const qail = @import("qail");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var driver = try qail.driver.driver.PgDriver.connect(allocator, "127.0.0.1", 5432, "postgres", "mydb");
    defer driver.deinit();

    const cmd = qail.ast.QailCmd.get("users")
        .select(&.{ qail.ast.Expr.col("id"), qail.ast.Expr.col("email") })
        .where(&.{.{ .condition = .{ .column = "active", .op = .eq, .value = .{ .bool = true } } }})
        .limit(10);

    const rows = try driver.fetchAll(&cmd);
    defer {
        for (rows) |*row| row.deinit();
        allocator.free(rows);
    }
}

High-Level Entry Points

  • qail.driver.driver.PgDriver.connect(...)
  • qail.driver.driver.PgDriver.connectUrl(...)
  • qail.driver.pool.PgPool.init(...)
  • qail.driver.pipeline.Pipeline.init(...)
  • qail.validateAst(...)

Practical Direction

  • Use PgDriver for direct command execution and AST-native reads/writes.
  • Use Pipeline for high-throughput prepared batches.
  • Use PgPool for concurrent prepared singles and scoped workloads.
  • Validate untrusted AST input with qail.validateAst before execution.

PostgreSQL Driver

QAIL Zig implements PostgreSQL directly over the wire protocol. The active surface includes:

  • plain TCP connections
  • connection timeouts
  • TLS transport
  • startup/auth handling for cleartext, MD5, SCRAM, and enterprise auth hooks
  • prepared statement execution
  • pipeline execution
  • connection pooling
  • COPY helpers
  • LISTEN / NOTIFY
  • logical replication core
  • RLS helper APIs

Primary Types

  • qail.driver.driver.PgDriver
  • qail.driver.connection.Connection
  • qail.driver.pipeline.Pipeline
  • qail.driver.pool.PgPool

Driver Direction

The focus of qail-zig is not a SQL-string convenience wrapper. The serious path is:

  1. build AST or validated command input
  2. encode PostgreSQL protocol frames directly
  3. execute over a pure-Zig transport path
  4. fail closed on protocol and state-machine violations

Current Emphasis

Recent work concentrated on hardening the PG driver instead of broadening surface area first. That includes startup/auth state validation, protocol framing checks, COPY sequencing checks, replication stream fail-closed handling, and AST sanitization.

The current public driver surface keeps raw SQL and trusted compatibility helpers internal. Application code should enter through QailCmd, PgDriver, PgPool, Pipeline, COPY helpers, and documented connection options.

Pool, Pipeline, and COPY

Pool

PgPool provides fixed-size connection pooling with scoped helpers and reset-on-release behavior.

Use it when:

  • you want concurrent prepared single-query workloads
  • you need pooled RLS or tenant-scoped acquisition
  • you want explicit min_connections / max_connections

Pipeline

Pipeline batches Bind + Execute messages and sends one Sync per batch. This is the highest-throughput path for prepared count-only or row-collecting workloads on a single connection.

Use it when:

  • you already have a prepared statement
  • batch throughput matters more than per-query latency
  • you want one connection and many completions per round trip

COPY

The COPY helpers are active and hardened.

Supported areas:

  • COPY FROM STDIN helpers
  • COPY TO STDOUT raw export helpers
  • stricter protocol sequencing checks
  • fail-closed handling on malformed COPY states and oversized data

COPY is now treated as a protocol feature that must reject unexpected backend frames rather than attempting to continue.

Security Hardening

The recent qail-zig work focused on PG-driver hardening parity against qail.rs.

Added or Tightened

  • AST sanitization for untrusted command input
  • raw SQL escape-hatch rejection on the sanitization, runtime, and public transpiler paths
  • strict runtime SQL-string allowlist checks for core/driver files
  • public API guards that keep raw, trusted-compatibility, cursor SQL helper, and data-safety raw helper modules internal
  • stricter startup/auth ordering checks
  • authentication method-switch rejection
  • SASL final / AuthenticationOk sequencing checks
  • Bind / Parse parameter-count guards
  • COPY fail-closed state validation
  • replication stream fail-closed handling on malformed CopyData
  • startup, protocol, and replication hardening suites

Why This Matters

Protocol bugs are often state-machine bugs, not just parsing bugs. The hardening work in qail-zig now rejects malformed or unexpected backend sequences earlier instead of silently progressing through them.

Current Safety Model

  • AST-native execution is the preferred path.
  • validateAst exists for untrusted or deserialized command ingress.
  • Public driver execution rejects raw SQL command payloads; remaining SQL strings are confined to audited internal renderers/helpers.
  • Public transpilation fails closed for raw command payloads.
  • Protocol handlers use explicit state validation and drain-to-ready behavior after errors where recovery is possible.

Remaining Direction

The active parity target is not “support every surface first”. It is “close driver and hardening gaps without weakening the transport guarantees.”

QAIL Zig Benchmarks

The current public benchmark page is published at /zig/benchmarks on dev.qail.io.

The current public Zig driver comparison is:

  • qail-zig
  • pg.zig

Harness

The active harness is src/benchmarks/qail_pgzig_bench.zig and reports the shared prepared-statement surface:

  • single — prepared single-query path on one connection
  • pool10 — prepared singles over ten connections

It covers five workloads:

  • point — tiny point lookup path
  • wide_rows — medium result sets with wide mixed rows
  • large_rows — larger result-set receive/decode path
  • many_params — parameter-heavy bind/encode path
  • aggregate — more server-heavy aggregate slice

The methodology is intentionally strict:

  • qail-zig workloads are authored as native QailCmd ASTs
  • qail-zig compiles them once to SQL for statement preparation
  • qail-zig then runs them through its prepared protocol path
  • pg.zig executes the same prepared SQL templates through its cached prepared-query path
  • pipeline is excluded so the published page stays on the clearest shared modes between the two drivers

Runner Examples

# Canonical benchmark runner
zig build pgzig-bench -- qail single --workload point
zig build pgzig-bench -- pgzig single --workload point

# Optional wrapper (equivalent commands)
./scripts/zigw pgzig-bench qail single --workload point
./scripts/zigw pgzig-bench pgzig single --workload point

# Full published matrix surface
zig build pgzig-bench -- qail pool10 --workload wide_rows
zig build pgzig-bench -- pgzig pool10 --workload wide_rows
zig build pgzig-bench -- qail single --workload many_params
zig build pgzig-bench -- pgzig pool10 --workload aggregate

Latest Published 3-Round Medians

WorkloadSingle (pg.zig / qail-zig)Pool10 (pg.zig / qail-zig)
Point19,535 / 44,862 q/s72,251 / 158,675 q/s
Wide rows4,544 / 5,474 q/s16,246 / 19,062 q/s
Large rows88.306 / 90.000 q/s279.950 / 306.865 q/s
Many params19,118 / 41,570 q/s71,257 / 153,386 q/s
Aggregate228.241 / 236.793 q/s1,438.975 / 1,474.389 q/s

Reading the Results

  • qail-zig leads all 10 / 10 shared throughput cells in the published matrix.
  • The biggest gains are on point and many_params, which points at lower execution-path and bind-handling cost.
  • wide_rows also stays positive, which means the win is not restricted to tiny dispatch-heavy lookups.
  • The smallest gaps are large_rows and aggregate, where PostgreSQL itself dominates more of the total work.
  • The page is intentionally narrow on feature parity. Pipeline is a qail-zig capability, but it is not part of the pg.zig comparison page so the benchmark stays on the clearest shared surface.

Benchmark Discipline

The benchmark numbers are only meaningful when the compared paths are equivalent. The current work explicitly separated:

  • shared SQL template after qail-zig AST compilation
  • matched prepared execution on both sides
  • interleaved rounds with median reporting

That keeps the comparison at the driver/runtime boundary instead of turning it into a fake API-surface mismatch.

  • Read the public benchmark page at /zig/benchmarks for the published matrix and interpretation.
  • Read README.md in the repo root for the short current benchmark summary.
  • If you want pipeline numbers, treat them as qail-zig-only capability measurements rather than as a direct pg.zig comparison.

qail.rs Parity Status

qail-zig tracks qail.rs as the reference implementation for PostgreSQL driver behavior and hardening.

Current Snapshot

As of 2026-04-23, the narrow AST/codegen parity checks against a local qail.rs checkout are green:

  • ./scripts/check_codegen_sync.sh ../qail.rs -> codegen sync check passed
  • ./scripts/check_parity.sh ../qail.rs -> AST actions: rust=75 zig=76, Encoder actions: rust=57 zig=76, parity check passed

That means the Rust-driven AST porting/codegen path is working for its current scope, and the PostgreSQL AST encoder still covers the Rust action surface completely.

Real PostgreSQL CLI validation on the Zig side is also green on this date:

  • Broad CLI matrix pass: 16/16 on live DB paths (exec, seed, pull, migrate status|plan|up|down).
  • Migration receipt-collision stress pass: 6/6 immediate dual-migrate up runs across fresh databases.

Active Areas with Strong Coverage

  • AST core exports
  • Rust-driven AST codegen sync
  • PostgreSQL wire protocol
  • prepared execution and pipelines
  • pooling
  • TLS transport
  • COPY in/out helpers
  • LISTEN / NOTIFY
  • logical replication core
  • RLS helper APIs
  • CLI PostgreSQL execution path (exec, seed, pull, migrate status|plan|up|down)
  • startup/auth policy controls
  • TLS SCRAM channel-binding derivation and fail-closed precedence on TLS startup
  • protocol hardening suites
  • typed policy parsing and diff normalization for common pg_dump wrappers
  • typed recursive CTE AST support and typed source-query constructors for views/materialized views

Current Reality

Parity is not complete across the entire qail.rs ecosystem. The largest gaps remain outside the core PG driver track:

  • gateway / auto-REST / WebSocket / OpenAPI stack
  • qdrant vector driver and hybrid execution path
  • workflow engine
  • typed schema codegen (qail types) and build-time SQL / N+1 guard rails
  • CLI breadth outside the core PG path (qail init, types, vector/hybrid flows)
  • editor tooling breadth remains on the qail.rs OpenVSX LSP track (not bundled in qail-zig)
  • direct SDKs and broader non-driver surfaces

Important Policy Delta

The main remaining policy difference is narrower now:

  • qail.rs removed raw runtime SQL APIs from the normal execution path entirely.
  • qail-zig now rejects .raw and nested procedural/raw escape hatches on the public driver path by default.
  • On TLS connections, qail-zig now treats connection-derived tls-server-end-point bytes as authoritative instead of allowing caller-supplied binding overrides.
  • qail-zig now also matches libpq-style gssencmode preface semantics and resolves hostnames across plain, TLS, async, and GSSENC-preface connect paths instead of assuming IPv4 literals.
  • qail-zig now ships Linux Kerberos environment preflight diagnostics (linuxKrb5Preflight) and a built-in Linux Kerberos provider (linuxKrb5TokenProvider) via runtime GSSAPI loading on Linux.
  • qail-zig now also exposes a session-aware GssTokenProviderEx callback shape, which removes the old API limitation that prevented Rust-style stateful GSS provider implementations.
  • On Linux, accepted GSSENCRequest now proceeds into an encrypted GSS transport instead of failing closed after the preface.
  • The repository now also carries a dedicated Linux Kerberos/GSSENC smoke workflow that provisions a local realm + PostgreSQL service principal and proves one AST-native roundtrip over gssencmode=require.
  • Typed RLS helpers and typed policy parsing are now present on the Zig side, including normalization of common wrapped current_setting(...) forms emitted by pg_dump.
  • The old raw nested-query and raw policy-SQL string fields have been removed from the Zig AST shape entirely; trusted compatibility now flows through internal helper modules and raw AST variants that the public runtime gate already rejects.
  • Migration receipt recording now writes the full tracked shape (version, name, applied_at, checksum, sql_up, sql_down) and handles generated-version collisions without aborting roll-forward migrations.

The main remaining enterprise-auth gap is narrower now:

  • runtime coverage depth and maintenance burden are now the main gap, especially expanding beyond the new smoke path and keeping the local TLS/GSS compatibility layers stable across Zig upgrades

PG Driver Focus

The PG driver is the serious parity target right now. That is why recent work landed in:

  • sanitization
  • startup/auth sequencing
  • protocol hardening
  • replication hardening
  • benchmark comparability

For detailed driver parity notes, see the repository parity file:

  • PARITY_AST_PG_DRIVER.md

API Surface

The high-signal public surface for qail-zig currently centers on the PostgreSQL driver and related tooling.

Core Exports

  • qail.driver.driver.PgDriver
  • qail.ast.QailCmd
  • qail.ast.Expr
  • qail.validateAst

Driver Module

  • qail.driver.connection.Connection
  • qail.driver.pipeline.Pipeline
  • qail.driver.pool.PgPool
  • qail.driver.pool.PoolConfig
  • qail.driver.tls.TlsConnection
  • qail.driver.connect_url.ConnectOptions
  • qail.driver.auth_options.AuthOptions
  • qail.driver.rls.RlsContext

Current API Notes

  • Use qail.ast.QailCmd and typed qail.ast.Expr values for application queries.
  • Use qail.driver.driver.PgDriver.connect(...), connectUrl(...), connectEnv(...), or connectWithOptions(...) for direct driver connections.
  • Use qail.driver.pool.PgPool.init(allocator, config) or PgPool.initUri(allocator, uri) for pooled workloads.
  • Use qail.driver.pipeline.Pipeline for prepared batch execution.
  • Validate untrusted/deserialized commands with qail.validateAst before execution.
  • Do not depend on raw SQL, cursor SQL helper, trusted compatibility, or data-safety raw helper modules; those are internal implementation details on the current line.

Tooling

  • CLI entry via zig build cli
  • editor LSP via the published qail.rs extension (OpenVSX/VS Code)
  • benchmark runners under src/*bench*.zig

Verified Real-DB CLI Surface

  • qail exec: inline query, --file, --json, --tx, and --dry-run
  • qail seed --file on the PostgreSQL execution path
  • qail pull schema extraction from a live PostgreSQL database
  • qail migrate status|plan|up|down, including receipt recording on live DB
  • database URL resolution through QAIL_DATABASE_URL

Validation date: 2026-05-21, against the current docs/API surface.

  • Start with the driver docs.
  • Then read the hardening page.
  • Then use the parity page to understand what is intentionally in-scope versus still missing.

Changelog

QAIL Zig now tracks its own release notes separately from qail.rs.

Current Highlights (post-v0.8.3, 2026-05-21)

  • qail-zig’s latest release tag is v0.8.3; the current docs also cover post-v0.8.3 main-branch API hardening.
  • Public raw SQL inputs, cursor SQL helpers, trusted/raw compatibility helpers, and data-safety raw helpers are hidden from the current public API.
  • Public driver execution and public transpilation fail closed for raw commands and nested raw escape hatches.
  • Real PostgreSQL CLI matrix remains validated on live DB paths for exec (inline/file/json/tx/dry-run), seed, pull, and migrate status|plan|up|down.
  • Migration receipt writes include applied_at, sql_down, conflict-safe insertion, and generated-version retry semantics.
  • AST column-definition SQL rendering preserves nullable-by-default columns correctly; NOT NULL is emitted only when explicitly requested.
  • The Linux PgDriver.connect stack-size fix and pipeline failure metadata from v0.8.1 remain in place.

For the repository changelog, see: