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 Documentation

The AST-Native Query Compiler

QAIL compiles typed query ASTs directly to database wire protocols. No SQL strings. No injection surface. Just pure, type-safe queries.

Philosophy: AST = Meaning

If a database doesn’t let us encode semantic intent, we don’t fake it.

QAIL compiles typed query ASTs directly to database wire protocols. No SQL strings. No injection surface.

Supported Databases

TierCategorySupportedWhy?
1SQL-ASTPostgreSQL, SQLiteOpen wire protocols allow full AST encoding.
2Document-ASTMongoDB, DynamoDB, QdrantNative AST query structure (BSON/JSON).

❌ Not Supported

  • Oracle, SQL Server, MySQL: Proprietary/Closed protocols.
  • Redis: Imperative command model (not a query language).

Quick Example

#![allow(unused)]
fn main() {
use qail_core::{Qail, Operator, SortOrder};

// Build a query with the AST builder
let cmd = Qail::get("users")
    .columns(["id", "email", "name"])
    .filter("active", Operator::Eq, true)
    .order_by("created_at", SortOrder::Desc)
    .limit(10);

// Execute with qail-pg driver
let mut driver = PgDriver::connect("localhost", 5432, "user", "db").await?;
let rows = driver.query(&cmd).await?;
}

Current Status (~80% Production Ready)

FeatureStatus
SSL/TLS
SCRAM-SHA-256 Auth
Connection Pooling
AST-Native Migrations
JSON/JSONB Types
UUID, Timestamps, INTERVAL
CTEs (WITH)
DISTINCT ON
CASE WHEN
Ergonomic Builders
qail-lsp (IDE)
COPY Protocol
Arrays (Value::Array)
Transactions (BEGIN/COMMIT/ROLLBACK)
Query Plan Caching
Window Functions (OVER)
Subqueries & EXISTS
UPSERT (ON CONFLICT)
RETURNING Clause
LATERAL JOIN
Unix Socket & mTLS
Savepoints
UNION/INTERSECT/EXCEPT
TRUNCATE
Batch Transactions
Statement Timeout
EXPLAIN / EXPLAIN ANALYZE
LOCK TABLE
Connection Timeout
Materialized Views

Note: QAIL’s AST-native design eliminates SQL injection by construction — no strings, no injection surface. Query plan caching (prepare(), pipeline_prepared_fast()) is purely a PostgreSQL performance optimization, not a security measure.

Why Some SQL Features Don’t Exist in QAIL

QAIL speaks AST, not SQL strings. Many traditional SQL “security features” are solutions to string-based problems that don’t exist in an AST-native world:

SQL FeatureWhy It ExistsQAIL Replacement
Parameterized QueriesPrevent string injectionNot needed — Value::Param is a typed AST node, not a string hole
Prepared Statements (for security)Separate SQL from dataNot needed — AST has no SQL text to inject into
Query EscapingSanitize user inputNot needed — values are typed (Value::Text, Value::Int), never interpolated
SQL ValidatorsDetect malformed queriesNot needed — invalid AST won’t compile
LISTEN/NOTIFYPub/sub channelsNot planned — string-based protocol, outside AST scope

The AST Guarantee

#![allow(unused)]
fn main() {
// SQL String (vulnerable):
let sql = format!("SELECT * FROM users WHERE id = {}", user_input);

// QAIL AST (impossible to inject):
Qail::get("users").filter("id", Operator::Eq, user_input)
// user_input becomes Value::Int(123) or Value::Text("...") 
// — never interpolated into a string
}

Getting Help

🤝 Contributing & Support

We welcome issue reports on GitHub! Please provide detailed descriptions to help us reproduce and fix the problem. We aim to address critical issues within 1-5 business days.

Caution

Alpha Software: QAIL is currently in alpha. While we strive for stability, the API is evolving to ensure it remains ergonomic and truly AST-native. Do not use in production environments yet.