sqlt 0.3.2

SQL parser, translator, and linter for MySQL, MariaDB, Postgres, MSSQL, SQLite
Documentation

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.md for what's shipped and OUT-OF-SCOPE.md for what isn't.

Install

# Homebrew (macOS / Linux) — via the codedeviate tap
brew install codedeviate/cli/sqlt

# crates.io
cargo install sqlt

# From a clone of this repo
cargo install --path .

Usage

# Parse SQL → JSON AST
echo "SELECT 1" | sqlt parse --from mysql --pretty

# Emit JSON AST → SQL
sqlt parse --from postgres schema.sql | sqlt emit --to mysql

# Translate SQL between dialects
sqlt translate --from mariadb --to postgres input.sql

# Lint SQL for common pitfalls and improvement suggestions
sqlt lint --from mariadb schema.sql
sqlt lint --from mariadb --to postgres schema.sql        # adds translation pre-flight checks
sqlt lint --from mariadb --format json schema.sql        # JSON output
sqlt lint --from mariadb --format sarif schema.sql       # SARIF for GitHub code scanning
sqlt lint --explain SQLT0300                             # rule documentation

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.

sqlt parse     --from mysql -e latin1 export.sql        # decode latin1, emit UTF-8 JSON
sqlt translate --from mysql --to mariadb -e latin1 in.sql > out.sql   # latin1 in and out
sqlt emit      --to mysql -e windows-1252 tree.json     # JSON (UTF-8) -> windows-1252 SQL

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

cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check

See CLAUDE.md for project conventions (semver, conventional commits, changelog, module map).

License

MIT — see LICENSE.