Registered SQLite queries with build-time schema validation. Queries are named and compiled once at module scope; handlers reference them by name.
import { sql, sqlOne, sqlMany, sqlExec } from "zigttp:sql";
sql("listTodos", "SELECT id, title, done FROM todos ORDER BY id ASC");
sql("getTodo", "SELECT id, title, done FROM todos WHERE id = :id");
sql("createTodo", "INSERT INTO todos (title, done) VALUES (:title, 0)");
function handler(req) {
if (req.method === "GET" && req.path === "/") {
return Response.json({ items: sqlMany("listTodos") });
}
if (req.method === "POST") {
const body = JSON.parse(req.body);
return Response.json(sqlExec("createTodo", { title: body.title }), { status: 201 });
}
return Response.text("Not Found", { status: 404 });
}Start the server with --sqlite <FILE> so the registered queries
execute against a real database:
zigttp serve examples/sql/sql-crud.ts --sqlite ./todos.db| Export | Signature | Effect | Purpose |
|---|---|---|---|
sql |
sql(name, statement): boolean |
register | Compile and register a named query. Module scope only. |
sqlOne |
sqlOne(name, params?): row | undefined |
read | Run a SELECT returning 0 or 1 row. |
sqlMany |
sqlMany(name, params?): row[] |
read | Run a SELECT returning any number of rows. |
sqlExec |
sqlExec(name, params?): { changes, lastInsertRowid } |
write | Run an INSERT, UPDATE, or DELETE. |
Parameters are bound by name using :name placeholders. Positional
binding is not supported.
- Every literal
sql(name, statement)registers the query in thesql.queriescontract section with its operation kind (select,insert,update,delete) and the tables it touches. - Pass
-Dsql-schema=<path.sql>to validate every registered statement against a schema snapshot. Unknown tables or columns fail the build.
zig build -Dhandler=examples/sql/sql-crud.ts -Dsql-schema=examples/sql/schema.sql- Unknown query names throw synchronously.
- Missing parameters throw with the placeholder name in the message.
sqlExec()on a SELECT orsqlOne()/sqlMany()on a write throws with a kind-mismatch message.
--sqlite <FILE>to point at the database file. The file is created on first use.--sqlite :memory:for ephemeral databases in tests.
zigttp:cache- in-process cache for values that do not need durable storage.zigttp:validate- validate request bodies before binding them into SQL parameters.