sqlt
Multi-dialect SQL parser and translator in Rust.
Parses SQL from MySQL, MariaDB, PostgreSQL, MSSQL (T-SQL), and SQLite into a JSON AST, emits SQL back from JSON, and translates between dialects.
Status: early development — see
CHANGELOG.mdfor what's shipped andOUT-OF-SCOPE.mdfor what isn't.
Install
# Homebrew (macOS / Linux) — via the codedeviate tap
# crates.io
# From a clone of this repo
Usage
# Parse SQL → JSON AST
|
# Emit JSON AST → SQL
|
# Translate SQL between dialects
# Lint SQL for common pitfalls and improvement suggestions
Reads from a file path or stdin (use - or omit the path).
Dialects
mysql, mariadb, postgres (alias postgresql), mssql (alias tsql), sqlite, generic.
MariaDB is a first-class target — features that diverge from MySQL (RETURNING on DML, CREATE SEQUENCE, system versioning, FOR SYSTEM_TIME, Oracle-compat packages) are recognized rather than silently aliased.
Non-UTF-8 input
Pass --encoding/-e to read or write SQL in a non-UTF-8 code page. Useful when one of your systems still emits ISO-8859-1 / Latin-1.
Supported encodings: utf-8 (default), iso-8859-1 / latin1, windows-1252 / cp1252. Decoding is strict — invalid bytes for the declared encoding are rejected with exit 1 rather than silently replaced.
Translation gaps
When a construct has no faithful equivalent in the target dialect (e.g. translating RETURNING to MySQL), sqlt translate emits the closest equivalent and prints a warning to stderr. Pass --strict to make any warning a non-zero exit.
Lint
sqlt lint runs ~38 rules across seven categories: dialect cross-contamination, translation pre-flight (when --to is set), join hygiene, subquery improvements, performance pitfalls, correctness pitfalls, style/readability, and DDL hygiene. Every rule has a stable id (SQLT0500), a slug (select-star), and inline documentation (sqlt lint --explain SQLT0500).
Common flags:
--from <dialect> required; the source SQL dialect
--to <dialect> optional; enables translation pre-flight rules
--format text|pretty|json|sarif output format (default text)
--rule <id>... enable a specific rule (repeatable)
--no-rule <id>... disable a specific rule (repeatable)
--severity error|warning|info filter the output (rules still run)
--exit-on error|warning|info controls exit code 1 (default error)
--explain <id> print rule documentation and exit 0
-e, --encoding same encoding handling as parse/translate
Exit codes match the rest of the CLI: 0 clean, 1 lint findings at or above --exit-on (or a parse error), 2 usage error, 3 reserved.
Development
See CLAUDE.md for project conventions (semver, conventional commits, changelog, module map).
License
MIT — see LICENSE.