qail 0.9.4

The Universal Query Transpiler - SQL is Assembly, Compile to Safety
Documentation

🪝 QAIL — The AST-Native Query Language

Write queries as data. Send them as bytes. No SQL strings.

Crates.io License


The Vision

QAIL is not a query transpiler. QAIL is a data language.

Instead of passing SQL strings through your stack, you work directly with a typed AST (Abstract Syntax Tree). This AST compiles to database wire protocol bytes — no string interpolation, no SQL injection, no parsing at runtime.

┌─────────────────────────────────────────────────────────────────┐
│  Layer 1: Intent                                                │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │   let cmd = QailCmd::get("users").filter("id", Eq, 42); │    │
│  └─────────────────────────────────────────────────────────┘    │
│                              │                                   │
│                              ▼                                   │
│  Layer 2: Brain (Pure Logic - NO ASYNC)                         │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │   let bytes = PgEncoder::encode(&cmd);  // → BytesMut   │    │
│  └─────────────────────────────────────────────────────────┘    │
│                              │                                   │
│                              ▼                                   │
│  Layer 3: Muscle (Async I/O - Tokio)                            │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │   stream.write_all(&bytes).await?;                      │    │
│  └─────────────────────────────────────────────────────────┘    │
│                              │                                   │
│                              ▼                                   │
│  Layer 4: Database                                              │
│  ┌─────────────────────────────────────────────────────────┐    │
│  │   PostgreSQL / MySQL / etc.                             │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

Why This Matters

Old Way (SQL Strings) QAIL Way (AST-Native)
"SELECT * FROM users WHERE id = $1" QailCmd::get("users").filter("id", Eq, id)
String concatenation risk Typed at compile time
Parse SQL at runtime Compile to bytes directly
Locked to one driver (sqlx, pg) Runtime-agnostic

Architecture

qail.rs/
├── qail-core/          # Layer 1: AST + Parser
│   ├── ast/            #   QailCmd, Expr, Value
│   ├── parser/         #   Text → AST (for CLI, LSP)
│   └── transpiler/     #   AST → SQL text (legacy path)
│
├── qail-pg/            # PostgreSQL Driver
│   ├── protocol/       #   Layer 2: AST → BytesMut (pure, sync)
│   └── driver/         #   Layer 3: Async I/O (tokio)
│
├── qail-cli/           # Command-line tool
├── qail-lsp/           # Language server
├── qail-wasm/          # Browser playground
└── qail-ffi/           # C-API for other languages

Quick Start

Rust

use qail_core::ast::QailCmd;
use qail_pg::{PgEncoder, PgDriver};

// Layer 1: Express intent as AST
let cmd = QailCmd::get("users")
    .columns(vec!["id", "email"])
    .filter("active", Operator::Eq, true);

// Layer 2: Compile to wire protocol (pure, sync)
let bytes = PgEncoder::encode_simple_query(&cmd);

// Layer 3: Send over network (async)
let mut driver = PgDriver::connect("localhost", 5432, "user", "db").await?;
let rows = driver.fetch_all(&cmd).await?;

CLI (for migration / debugging)

# Install
cargo install qail

# Transpile QAIL text to SQL (legacy mode)
qail "get users fields id, email where active = true"
# → SELECT id, email FROM users WHERE active = true

The Three Layers

Layer 2: The Brain (Pure Logic)

This is the key innovation. The encoder:

  • Takes a QailCmd (AST)
  • Returns BytesMut (wire protocol bytes)
  • Has zero async, zero I/O, zero tokio
// This is PURE computation - can compile to WASM
let bytes = PgEncoder::encode_simple_query(&cmd);

Layer 3: The Muscle (Async Runtime)

The only place where tokio lives. If a better runtime emerges, only this layer changes:

// Currently uses tokio - swappable in the future
let mut driver = PgDriver::connect(...).await?;
driver.send(&bytes).await?;

Supported Databases

Database Status Crate
PostgreSQL 🔄 In Progress qail-pg
MySQL 📋 Planned qail-mysql
SQLite 📋 Planned qail-sqlite

Each database has its own wire protocol, so each gets its own encoder.


Contributing

git clone https://github.com/qail-rs/qail.git
cd qail
cargo test

License

MIT © 2025 QAIL Contributors