Skip to main content

SQLite SQL tools — parser, formatter, validator, and MCP server

Project description

  syntaqlite

CI Crates.io VS Code

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.

Docs · Playground · VS Code Extension · MCP Server

Note: syntaqlite is at 0.x — APIs and CLI flags may change before 1.0.

Why syntaqlite

Developer tooling for SQLite treats it as a second-class language. Most tools build a generic SQL parser and bolt SQLite on as a "flavor" — hand-written grammars, regex-based tokenizers, or subsets of SQL that approximate SQLite rather than matching it. That falls apart because SQLite has a deep surface area of syntax that generic parsers don't handle.

syntaqlite uses SQLite's own Lemon-generated grammar and tokenizer, compiled from C. The parser doesn't approximate SQLite — it is SQLite's grammar compiled into a reusable library.

SQLite SQL is also not one fixed language. It has 22 compile-time flags that change what syntax the parser accepts, another 12 that gate built-in functions, and the language constantly evolves across versions. Because SQLite is embedded, you can't assume everyone is on the latest version — Android 15 ships SQLite 3.44.3, seven major versions behind latest. syntaqlite tracks all of this:

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 *;
  |                                ^~~~~~~~~

RETURNING was added in SQLite 3.35.0 — Android 13 still ships SQLite 3.32.2.

We've tested against ~396K statements from SQLite's upstream test suite with ~99.7% agreement on parse acceptance. See the detailed comparison for how syntaqlite stacks up against other tools in parser accuracy, formatter correctness, validator quality, and performance.

What it does

Validate — catch errors without a database (docs)

Finds 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:

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;

sqlite3 stops at the first error and misses the function typo entirely:

Error: in prepare, table monthly_stats has 2 values for 3 columns

syntaqlite finds both — CTE column count mismatch and the ROUDN typo — with source locations and suggestions:

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'?

Format (docs)

Deterministic formatting with configurable line width, keyword casing, and indentation:

echo "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" \
  | syntaqlite fmt
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;

Version and compile-flag aware (docs)

Pin the parser to a specific SQLite version or enable compile-time flags to match your exact build:

# Reject syntax your target SQLite version doesn't support
syntaqlite --sqlite-version 3.32.0 validate query.sql

# Enable optional syntax from compile-time flags
syntaqlite --sqlite-cflag SQLITE_ENABLE_MATH_FUNCTIONS validate query.sql

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:

# app.py
def get_user_stats(user_id: int):
    return conn.execute(
        f"SELECT nme, ROUDN(score, 2) FROM users WHERE id = {user_id}"
    )
syntaqlite validate --experimental-lang python app.py
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'?

Project configuration

Create a syntaqlite.toml in your project root to configure schemas and formatting. The LSP, CLI, and all editor integrations read it automatically:

# Map SQL files to schema DDL files for validation and completions.
[schemas]
"src/**/*.sql" = ["schema/main.sql", "schema/views.sql"]
"tests/**/*.sql" = ["schema/main.sql", "schema/test_fixtures.sql"]
"migrations/*.sql" = []  # no schema validation for migrations

# Default schema for SQL files that don't match any glob above.
# schema = ["schema.sql"]

# Formatting options (all optional, shown with defaults).
[format]
line-width = 80
indent-width = 2
keyword-case = "upper"    # "upper" | "lower"
semicolons = true

The config file is discovered by walking up from the file being processed — same as rustfmt.toml or ruff.toml. CLI flags override config file values.

Editor integration (docs)

Full language server — no database connection required. Diagnostics, format on save, completions, and semantic highlighting.

VS Code — install the syntaqlite extension from the marketplace.

Claude Codeclaude plugin install syntaqlite@LalitMaganti/claude-code-plugin (docs) · Claude Desktop / Cursor / Windsurfsyntaqlite mcp (docs)

Other editors — point your LSP client at:

syntaqlite lsp

Parse (docs)

Full abstract syntax tree with side tables for tokens, comments, and whitespace — for code generation, migration tooling, or static analysis.

syntaqlite parse -e "SELECT 1 + 2"

Install (all methods)

Download and run (all platforms, no install)

curl -sSf https://raw.githubusercontent.com/LalitMaganti/syntaqlite/main/tools/syntaqlite | python3 - fmt -e "select 1"

Downloads the binary on first run, caches it, auto-updates weekly.

mise

mise use github:LalitMaganti/syntaqlite

pip (all platforms, bundled binary)

pip install syntaqlite

Homebrew (macOS)

brew install LalitMaganti/tap/syntaqlite

Cargo

cargo install syntaqlite-cli

Use as a library (docs)

Rust (API docs)

[dependencies]
syntaqlite = { version = "0.0.30", features = ["fmt"] }

JavaScript / WASM (API docs)

npm install syntaqlite

C — the parser, tokenizer, formatter, and validator all have C APIs. See the C API docs for details.

Architecture (docs)

The parser and tokenizer are written in C, directly wrapping SQLite's own grammar. Everything else — formatter, validator, LSP — is written in Rust with C bindings available.

The split is intentional. The C parser is as portable as SQLite itself: it can run inside database engines, embedded systems, or anywhere SQLite runs. The Rust layer moves fast for developer tooling where the standard library and the crate ecosystem matter.

Building from source

tools/install-build-deps
tools/cargo build

Contributing

See the contributing guide for architecture overview and testing instructions.

License

Apache 2.0. SQLite components are public domain under the SQLite blessing. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

syntaqlite-0.0.30-py3-none-win_arm64.whl (5.3 MB view details)

Uploaded Python 3Windows ARM64

syntaqlite-0.0.30-py3-none-win_amd64.whl (5.8 MB view details)

Uploaded Python 3Windows x86-64

syntaqlite-0.0.30-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

syntaqlite-0.0.30-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (6.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

syntaqlite-0.0.30-py3-none-macosx_11_0_arm64.whl (5.8 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

syntaqlite-0.0.30-py3-none-macosx_10_12_x86_64.whl (6.0 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file syntaqlite-0.0.30-py3-none-win_arm64.whl.

File metadata

  • Download URL: syntaqlite-0.0.30-py3-none-win_arm64.whl
  • Upload date:
  • Size: 5.3 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for syntaqlite-0.0.30-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 db5114a8489bac506cf3fc4a360e8ad5332751cad6bafe53b8c2481e516d6008
MD5 48f03c7b1a82fb0471e1aa64a0146e8e
BLAKE2b-256 678c80078ac3231ff7d0920562391e06bd84b616619a73df29f0fea98265d6d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-win_arm64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file syntaqlite-0.0.30-py3-none-win_amd64.whl.

File metadata

  • Download URL: syntaqlite-0.0.30-py3-none-win_amd64.whl
  • Upload date:
  • Size: 5.8 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for syntaqlite-0.0.30-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 33ca07dad2f3961bdf78ca71be7b1da5ae3f230c3db887627399c72b39aab6d9
MD5 49efad665f8ee26af0e637ada17c4c76
BLAKE2b-256 5c48f57416a6736d33b89df2aad772bfffeca38ad20f7d9244b9be74f25202f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-win_amd64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file syntaqlite-0.0.30-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for syntaqlite-0.0.30-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9a95f2f8dda19f4d89d96c005678319e3c55422562838413c7cf87e302a0987a
MD5 192037efafac200b4d0e9bea0b835286
BLAKE2b-256 64daaeb58a61de932004f1d0d6b07f2e9f0d270d9e2f42495b93c1d1d52d59b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file syntaqlite-0.0.30-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for syntaqlite-0.0.30-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 7d63825fdd3922f092eaba4b7844e904205f992b780daffb29a7750a61b79375
MD5 b1aeb77d947ef50bcc0721d868214ce9
BLAKE2b-256 5c040d7700cb1334ac5fdc87c6cd1d401b5bb5f613a803adde11713537e5680e

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file syntaqlite-0.0.30-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for syntaqlite-0.0.30-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 39ef20d91afef9addbcba5421a55bf60443fef691d56828b7976c55c17f0e20e
MD5 f77b64dfd74a0e2e153619483911019c
BLAKE2b-256 cf96e9ca54d4632fa389b51debf490040111dffb8b80dcf76bad6beef3451fb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file syntaqlite-0.0.30-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for syntaqlite-0.0.30-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d6a227be6938b3f0c135f9386d6fae9e8ae7121d8eda36007ac6bd12d5eae157
MD5 70a61e2741823203319f40c144953e69
BLAKE2b-256 aa92c8496e3714e39ef2aaf3a949fd702d19cfad2823f93bbc4fc1aaab4bc802

See more details on using hashes here.

Provenance

The following attestation bundles were made for syntaqlite-0.0.30-py3-none-macosx_10_12_x86_64.whl:

Publisher: publish-pypi.yml on LalitMaganti/syntaqlite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page