| Crates.io | qail-macro |
| lib.rs | qail-macro |
| version | 0.8.10 |
| created_at | 2025-12-20 18:32:12.872375+00 |
| updated_at | 2025-12-23 15:19:34.752698+00 |
| description | Procedural macros for QAIL - compile-time validated database queries |
| homepage | |
| repository | https://github.com/qail-rs/qail |
| max_upload_size | |
| id | 1996829 |
| size | 41,242 |
Safe but Free. Write queries once. Run them everywhere. Zero lock-in.
For years, developers have been trapped between two choices:
QAIL is the third way.
"I originally built QAIL for internal use to solve my own headaches. But I realized that other engineers shouldn't have to suffer through the same 'Database Dilemma'. That's why I decided to open-source it." — The Creator
We moved validation from the networking layer to the grammar level. By treating queries as a compiled language instead of raw strings, QAIL provides compile-time safety with the freedom of raw SQL.
-- SQL (The Assembly)
SELECT id, email FROM users WHERE active = true LIMIT 10;
# QAIL (The Source Code)
get::users:'id'email [ 'active == true, 0..10 ]
One line. Zero ceremony. Runs everywhere.
cargo install qail
[dependencies]
qail-core = "0.8"
npm i qail-wasm
use qail_core::prelude::*;
// Parse and transpile
let sql = parse("get::users:'id'email [ 'active == true ]")?.to_sql();
// Returns: "SELECT id, email FROM users WHERE active = true"
// Use with your existing driver (sqlx, diesel, etc.)
let users = sqlx::query_as::<_, User>(&sql)
.fetch_all(&pool)
.await?;
import { parseAndTranspile } from 'qail-wasm';
const sql = parseAndTranspile("get::users:'id'email [ 'active == true ]");
// Returns: "SELECT id, email FROM users WHERE active = true"
// Use with your existing driver (pg, mysql2, etc.)
const result = await client.query(sql);
| Symbol | Name | Function | Example |
|---|---|---|---|
:: |
The Gate | Action (get/set/del/add) | get:: |
: |
The Link | Connect table to columns | users:'id |
' |
The Label | Mark a column | 'email'name |
'_ |
The Wildcard | All columns | users:'_ |
[ ] |
The Cage | Constraints block | [ 'active == true ] |
== |
The Equal | Equality check | 'status == "active" |
~ |
The Fuse | Fuzzy match (ILIKE) | 'name ~ "john" |
| |
The Split | Logical OR | 'a == 1 | 'b == 2 |
& |
The Bind | Logical AND | 'a == 1 & 'b == 2 |
+/- |
Sort Order | ASC/DESC | -created_at |
N..M |
The Range | Pagination | 0..10 |
$ |
The Var | Parameter placeholder | $1 |
! |
The Unique | DISTINCT | get!:: |
<- |
Left Join | LEFT JOIN | users<-profiles |
-> |
Inner Join | INNER JOIN | users->orders |
get::users:'id'email [ 'active == true ]
# → SELECT id, email FROM users WHERE active = true
get::users:'_
# → SELECT * FROM users
get::users:'_ [ -created_at, 0..10 ]
# → SELECT * FROM users ORDER BY created_at DESC LIMIT 10
get::users:'id'name [ 'name ~ "john" ]
# → SELECT id, name FROM users WHERE name ILIKE '%john%'
set::users:[ status = "active" ] [ 'id == $1 ]
# → UPDATE users SET status = 'active' WHERE id = $1
del::users:[ 'id == $1 ]
# → DELETE FROM users WHERE id = $1
get::users<-profiles:'name'avatar
# → SELECT name, avatar FROM users LEFT JOIN profiles ON ...
Create and modify tables with the same concise syntax.
make::)make::users:'id:uuid^pk'email:varchar^unique^comment("User email")
# → CREATE TABLE users (id UUID PRIMARY KEY, email VARCHAR(255) UNIQUE);
# → COMMENT ON COLUMN users.email IS 'User email'
make::posts:'id:uuid^pk'status:varchar^def("draft")'views:int^def(0)
# → CREATE TABLE posts (
# id UUID PRIMARY KEY,
# status VARCHAR(255) DEFAULT 'draft',
# views INT DEFAULT 0
# )
make::bookings:'user_id:uuid'slot_id:uuid^unique(user_id, slot_id)
# → CREATE TABLE bookings (..., UNIQUE (user_id, slot_id))
index::)index::idx_email^on(users:'email)^unique
# → CREATE UNIQUE INDEX idx_email ON users (email)
QAIL provides multiple integration paths:
| Platform | Package | Description |
|---|---|---|
| Rust | qail-core |
Native crate, zero overhead |
| Node.js / Browser | qail-wasm |
WebAssembly module (~50KB) |
| C / C++ | libqail |
Universal C-API for FFI |
| Python, Go, PHP, Java | via C-API/FFI | Native bindings available |
Instead of building separate bindings for each language, we expose a Universal C-API (libqail). Any language with FFI support can call QAIL directly.
Installation (Linux/macOS):
libqail-v0.8.0.tar.gz from Releases.sudo cp include/qail.h /usr/local/include/
sudo cp lib/libqail_ffi.so /usr/local/lib/ # .dylib on macOS
sudo ldconfig # Linux only
Usage (C/C++):
Compile with -lqail_ffi:
#include <qail.h>
// ...
// char* sql = qail_transpile("get::users:'_");
Usage (Python):
from ctypes import cdll
lib = cdll.LoadLibrary("libqail_ffi.so") # or .dylib
# ...
Usage (Go):
/*
#cgo LDFLAGS: -lqail_ffi
#include <qail.h>
*/
import "C"
// ...
We welcome contributions!
git clone https://github.com/qail-rs/qail.git
cd qail
cargo test
MIT © 2025 QAIL Contributors
Built with 🦀 Rust
qail.rs