Crates.io | xlg-sqlfmt |
lib.rs | xlg-sqlfmt |
version | 0.2.0 |
created_at | 2025-09-24 18:39:43.670612+00 |
updated_at | 2025-09-24 21:19:59.452423+00 |
description | A command-line SQL formatter that reads SQL from stdin and writes formatted SQL to stdout |
homepage | https://github.com/xlgmokha/sqlfmt |
repository | https://github.com/xlgmokha/sqlfmt |
max_upload_size | |
id | 1853568 |
size | 50,281 |
A fast, reliable SQL formatter written in Rust that reads SQL from stdin and writes beautifully formatted SQL to stdout.
cargo install xlg-sqlfmt
git clone https://github.com/xlgmokha/sqlfmt.git
cd sqlfmt
cargo install --path .
# Format SQL from stdin
echo "select * from users where active=1" | xlg-sqlfmt
# Format a SQL file
xlg-sqlfmt < query.sql
# Format and save to file
xlg-sqlfmt < input.sql > formatted.sql
# Use in a pipeline
cat messy.sql | xlg-sqlfmt | less
Add to your .vimrc
or init.vim
:
" Format SQL with xlg-sqlfmt
command! SQLFormat %!xlg-sqlfmt
Simple projections (single column or literal) are formatted on one line:
-- Input
SELECT 1 AS one FROM users WHERE active = true
-- Output
SELECT 1 AS one
FROM
users
WHERE active = TRUE;
Complex projections are formatted with each column on its own line:
-- Input
SELECT id, name, email, created_at FROM users
-- Output
SELECT
id,
name,
email,
created_at
FROM
users;
Each logical operator starts a new line with proper indentation:
-- Input
SELECT * FROM users WHERE active = true AND age > 18 AND name LIKE 'A%'
-- Output
SELECT *
FROM
users
WHERE active = TRUE
AND age > 18
AND name LIKE 'A%';
Each JOIN clause is on its own line, aligned properly:
-- Input
SELECT u.name, p.title FROM users u INNER JOIN posts p ON u.id = p.user_id LEFT JOIN comments c ON p.id = c.post_id
-- Output
SELECT
u.name,
p.title
FROM
users AS u
INNER JOIN posts AS p ON u.id = p.user_id
LEFT JOIN comments AS c ON p.id = c.post_id;
Subqueries are indented and recursively formatted:
-- Input
SELECT * FROM (SELECT id, name FROM users WHERE active = true) AS active_users WHERE name LIKE 'A%'
-- Output
SELECT *
FROM
(
SELECT
id,
name
FROM
users
WHERE active = TRUE
) AS active_users
WHERE name LIKE 'A%';
-- Input
WITH active_users AS (SELECT * FROM users WHERE active = true) SELECT * FROM active_users
-- Output
WITH
active_users AS (
SELECT *
FROM
users
WHERE active = TRUE
)
SELECT *
FROM
active_users;
-- Input
SELECT CASE WHEN age < 18 THEN 'minor' WHEN age >= 65 THEN 'senior' ELSE 'adult' END AS age_group FROM users
-- Output
SELECT
CASE
WHEN age < 18 THEN 'minor'
WHEN age >= 65 THEN 'senior'
ELSE 'adult'
END AS age_group
FROM
users;
If the SQL cannot be parsed, xlg-sqlfmt
will:
This makes it safe to use in pipelines and scripts:
# This will pass through invalid SQL unchanged
echo "INVALID SQL SYNTAX" | xlg-sqlfmt
echo $? # Returns 1
# Valid SQL will be formatted
echo "SELECT * FROM users" | xlg-sqlfmt
echo $? # Returns 0
Running xlg-sqlfmt
multiple times on the same SQL produces identical output:
echo "SELECT * FROM users" | xlg-sqlfmt | xlg-sqlfmt | xlg-sqlfmt
# All three runs produce identical output
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
# Clone the repository
git clone https://github.com/xlgmokha/sqlfmt.git
cd sqlfmt
# Run tests
cargo test
# Run clippy for linting
cargo clippy
# Format code
cargo fmt
# Test the binary
echo "SELECT * FROM users" | cargo run
This project is licensed under the MIT License - see the LICENSE file for details.