syntaqlite
A parser, formatter, validator, and language server for SQLite SQL, built on SQLite's own grammar and tokenizer. If SQLite accepts it, syntaqlite parses it. If SQLite rejects it, so does syntaqlite, including syntax gated behind specific versions and compile-time flags.
Note: syntaqlite is at 0.x. APIs and CLI flags may change before 1.0.
What it does
Format
Configurable line width, keyword casing, and indentation. The formatter is deterministic — the same input always produces the same output.
select u.id,u.name, p.title from
users u join posts p on u.id
=p.user_id where u.active
=1 and p.published=true
order by p.created_at
desc limit 10
SELECT u.id, u.name, p.title
FROM users u
JOIN posts p ON u.id = p.user_id
WHERE u.active = 1
AND p.published = true
ORDER BY p.created_at DESC
LIMIT 10;
Validate
Catches unknown tables, columns, and functions against your schema —
the same errors sqlite3_prepare would catch, but without
needing a database. Unlike sqlite3, syntaqlite finds
all errors in one pass and shows exactly where they are:
CREATE TABLE orders (id, status, total, created_at);
WITH
monthly_stats(month, revenue, order_count) AS (
SELECT strftime('%Y-%m', o.created_at), SUM(o.total)
FROM orders o WHERE o.status = 'completed'
GROUP BY strftime('%Y-%m', o.created_at)
)
SELECT ms.month, ms.revenue, ms.order_count,
ROUDN(ms.revenue / ms.order_count, 2) AS avg_order
FROM monthly_stats ms;
Two errors: CTE declares 3 columns but the SELECT produces 2, and ROUDN is a typo for ROUND.
Error: in prepare, table monthly_stats
has 2 values for 3 columns
Stops at first error. Misses the ROUDN typo entirely.
error: table 'monthly_stats' has 2
values for 3 columns
|
2 | monthly_stats(month, revenue,
| ^~~~~~~~~~~~~
warning: unknown function 'ROUDN'
|
14 | ROUDN(ms.revenue / ms.order_count,
| ^~~~~
= help: did you mean 'round'?
Version and compile-flag aware
SQLite isn't one fixed language — syntax changes between releases, and compile-time flags enable optional features. syntaqlite tracks this across all tools: parser, formatter, validator, and LSP.
# RETURNING was added in SQLite 3.35.0
# Android 13 ships SQLite 3.32.2 — catch the mismatch:
syntaqlite --sqlite-version 3.32.0 validate \
-e "DELETE FROM users WHERE id = 1 RETURNING *;"
error: syntax error near 'RETURNING'
--> <stdin>:1:32
|
1 | DELETE FROM users WHERE id = 1 RETURNING *;
| ^~~~~~~~~
Validate SQL inside other languages experimental
SQL lives inside Python and TypeScript strings in most real codebases. syntaqlite extracts and validates it — handling interpolation holes and still catching errors with did-you-mean suggestions.
def get_user_stats(user_id: int):
return conn.execute(
f"SELECT nme, ROUDN(score, 2) FROM users WHERE id = {user_id}"
)
warning: unknown function 'ROUDN'
--> app.py:3:23
|
3 | f"SELECT nme, ROUDN(score, 2) FROM users WHERE id = {user_id}"
| ^~~~~
= help: did you mean 'round'?
Parse
Abstract syntax tree with side tables for tokens, comments, and whitespace boundaries.
SelectStmt
columns:
ResultColumn
expr:
ColumnRef
column: "id"
ResultColumn
expr:
ColumnRef
column: "name"
from_clause:
TableRef
table_name: "users"
where_clause:
BinaryExpr
op: EQ
left:
ColumnRef
column: "active"
right:
Literal "1"
Editor integration
Full language server (LSP) — no database connection required. Real-time diagnostics, format on save, completions for keywords, functions, tables and columns, and semantic syntax highlighting.
# VS Code — install from the marketplace
ext install syntaqlite.syntaqlite
# Any editor — point your LSP client at:
syntaqlite lsp
Design principles
- Reliability — uses SQLite's own tokenizer and grammar rules, verified by running the full SQLite test suite through the parser.
-
Speed — parses 3,500 lines of SQL in 2.6ms, formats in
4.9ms, validates in 7.3ms. Faster than
sqlite3itself for validation. Zero-copy tokenizer, arena-allocated parser, Wadler-Lindig formatter — all allocations are reused across inputs. - Portability — no runtime dependencies beyond the C and Rust standard libraries. Runs natively, in WASM, and as a shared library.
- Extensibility — the grammar system supports database engines that extend SQLite's syntax. Define custom grammar rules, AST nodes, and formatting recipes, then load your dialect as a shared library at runtime.
syntaqlite grew out of 8+ years of maintaining PerfettoSQL and scaling it to 100K+ line SQL codebases. See the comparison for how it stacks up against other tools.
What it does not do
- It does not support other SQL engines. syntaqlite is SQLite-only by design — this is what allows it to use the real grammar rather than a lowest-common-denominator subset.
-
It does not do runtime type checking. It catches what
sqlite3_preparecatches (syntax errors, unknown names), not data-dependent errors like division by zero or type mismatches.
Get started
Pick your starting point: