Convert SQL schema DDL between dialects using a compact intermediate representation.
xsql is a lightweight CLI and TUI that parses, diffs, and emits SQL schema DDL for MySQL, PostgreSQL, and SQLite. It relies on an experimental IR v2 to improve portability, enable round-tripping and linting, and to pave the way for future ALTER-statement generation.
- Parses schema DDL from:
- MySQL
- PostgreSQL
- SQLite
- Emits schema DDL to:
- MySQL
- PostgreSQL
- SQLite
- Converts:
- a single
.sqlfile → another.sqlfile - a whole folder tree of
.sqlfiles → a destination folder (preserves relative paths)
- a single
- Includes an interactive TUI (
xsql tui).
Install and run quickly (recommended):
# one-line install (clones, builds, installs to $HOME/.cargo/bin)
curl -fsSL https://raw.githubusercontent.com/Dawaman43/xsql/main/install.sh | sh
# then run the tool
xsql --helpIf you prefer to build locally:
cargo build --releaseThe development binary will be at target/release/xsql.
There is also an installer script at install.sh in this repo; the curl one-liner above runs it.
Convert SQL schema DDL between dialects (focused on CREATE TABLE) via a small intermediate representation (IR).
Install and run quickly (recommended):
# one-line installer (clones, builds, installs xsql)
curl -fsSL https://raw.githubusercontent.com/Dawaman43/xsql/main/install.sh | sh
# then run the tool
xsql --helpIR v2 is an opt-in richer intermediate representation for schema portability. It captures:
- Table-level constraints (
UNIQUE,FOREIGN KEY,CHECK) - Column-level constraints (
NOT NULL,DEFAULT,AUTO_INCREMENT/identity) - Portable data types (
Integer,Boolean,Float,Varchar,Text,Timestamp) - Free-form
metadataandannotationsfor tools to add hints
Parsers can output V2 JSON and emitters can read V2 JSON to produce dialect SQL. This is useful for round-tripping, linting, and future ALTER-generation.
CLI examples (v2):
# Parse a Postgres SQL file into V2 JSON
xsql v2-parse schema.sql --dialect postgres > schema.v2.json
# Emit MySQL SQL from a V2 JSON file
xsql v2-emit schema.v2.json --dialect mysql > schema.mysql.sql
# Diff two V2 JSON files (human output)
xsql v2-diff old.v2.json new.v2.json
# Diff two V2 JSON files (machine JSON output)
xsql v2-diff old.v2.json new.v2.json --json > diff.jsonNotes and limitations:
- V2 is still experimental: some vendor-specific types and complex CHECK expressions
may be preserved as
Custom/annotationsand not always round-trippable. - ALTER-statement generation is planned; currently emitters output
CREATE TABLE.
xsql uses a small intermediate representation (IR) to separate parsing from emitting:
- Parser crates (in
crates/xsql-parser) read dialect-specific SQL into the IR. - The IR crate (
crates/xsql-ir) contains a minimal typed model for tables, columns and basic constraints. - Emitter crates (in
crates/xsql-emitter) produce dialect-specific SQL from the IR.
This design makes it straightforward to add new dialects and to centralize mapping logic between types and constraints.
- Bidirectional conversion: parse → IR → emit avoids ad-hoc text transforms.
- Easier testing: round-trip tests (parse → IR → emit → parse) validate correctness.
- Incremental growth: start with CREATE TABLE and expand IR for indexes, constraints and more.
If you prefer to build locally:
cargo build --release --manifest-path crates/xsql-cli/Cargo.tomlThe development binary will be at crates/xsql-cli/target/release/xsql (or in the workspace target/release).
There is also an installer script at install.sh in this repo; the curl one-liner above runs it.
Use v2-parse/v2-emit in CI to validate schema round-trips and detect portability issues. Example GitHub Actions step:
- name: Validate schema roundtrip
uses: actions/checkout@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build xsql
run: cargo build --release --manifest-path crates/xsql-cli/Cargo.toml
- name: Parse and emit (roundtrip)
run: |
./target/release/xsql v2-parse examples/postgres.sql --dialect postgres > /tmp/schema.v2.json
./target/release/xsql v2-emit /tmp/schema.v2.json --dialect mysql > /tmp/schema.mysql.sql
- name: Compute v2 diff
run: |
./target/release/xsql v2-parse examples/postgres.sql --dialect postgres > /tmp/old.v2.json
./target/release/xsql v2-parse examples/mysql.sql --dialect mysql > /tmp/new.v2.json
./target/release/xsql v2-diff /tmp/old.v2.json /tmp/new.v2.json --json > /tmp/diff.json- The installer runs a quiet build and shows a spinner animation while compiling.
- It will try to move the installed
xsqlbinary into/usr/local/bin(this may prompt forsudo) so the tool is immediately available system-wide. - If moving to
/usr/local/binis not possible, the installer adds$HOME/.cargo/binto your shell RC (prefers~/.zshrc, then~/.bashrc, then~/.profile) soxsqlwill be available in future sessions. - If the installer cannot move the binary, you can make it available immediately in your current shell by running:
export PATH="$HOME/.cargo/bin:$PATH"
# or source the updated rc, e.g.:
source ~/.zshrcDo not run the curl+sh command with sudo — the installer handles any required privilege escalation when moving the binary to /usr/local/bin.
xsqlOr explicitly:
xsql tuixsql --from mysql --to postgres --input schema.sql --output schema.pg.sqlxsql --from postgres --to sqlite --input ./schemas --output ./outOnly files ending in .sql are converted; others are ignored.
xsql tuiTab/Shift+Tabmoves between fields↑/↓or←/→changes dialect when focused on From/Toiopens input picker,oopens output pickerxswaps from/to dialects,rruns conversionEnterruns conversion when focused on Run- If the output folder doesn't exist, the TUI will ask to create it (
y/n). Escquits
While the TUI is open, these keys are available:
- Navigation:
Up/Down(move selection) - Fast navigation:
PageUp/PageDown,Home/End - Parent directory:
LeftorBackspace - Open / enter directory:
RightorEnter - Select item:
s(select file or directory) - Start search/filter:
/(then type to filter results)- While searching: typing adds to the query,
Backspaceremoves a character,Escexits search
- While searching: typing adds to the query,
- Confirm directory selection: when prompted after selecting a directory press
ato select all files orfto pick individual files - Toggling:
dtoggles dry-run,xswapsfrom/todialects,rruns conversion - Quick pickers:
iopen input picker,oopen output picker
Hints are shown at the top of the picker when active.
TUI workflow is designed to be “no typing”:
- Pick input file or folder
- Pick output folder
- Press Enter to run
See the examples/ folder for small sample schemas (mysql.sql, postgres.sql, sqlite.sql).
This project currently focuses on a small subset of SQL needed for schema conversion:
- Only
CREATE TABLEis converted. - The intermediate representation is intentionally minimal (
xsql-ir). - Many dialect-specific features (indexes, constraints beyond primary keys, foreign keys, check constraints, extensions, etc.) are not yet mapped.
- Type mapping is best-effort (unknown types become
TEXT).
- Expand IR to cover more schema features (constraints, indexes)
- Improve type mapping and defaults across dialects
- Add more dialects (e.g. MSSQL, BigQuery, Snowflake) as the IR grows
See CONTRIBUTING.md.
MIT. See LICENSE.