Quick Start
Check a Single Migration File
diesel-guard check migrations/2024_01_01_create_users/up.sql
Check All Migrations in a Directory
diesel-guard check # defaults to ./migrations/
diesel-guard check migrations/ # or specify an explicit path
Pipe SQL Directly
cat migrations/2024_01_01_create_users/up.sql | diesel-guard check -
Example Output
When diesel-guard finds an unsafe operation:
❌ Unsafe migration detected in migrations/2024_01_01_create_users/up.sql
❌ ADD COLUMN with DEFAULT
Problem:
Adding column 'admin' with DEFAULT on table 'users' requires a full table rewrite on Postgres < 11,
which acquires an ACCESS EXCLUSIVE lock. On large tables, this can take significant time and block all operations.
Safe alternative:
1. Add the column without a default:
ALTER TABLE users ADD COLUMN admin BOOLEAN;
2. Backfill data in batches (outside migration):
UPDATE users SET admin = <value> WHERE admin IS NULL;
3. Add default for new rows only:
ALTER TABLE users ALTER COLUMN admin SET DEFAULT <value>;
Note: For Postgres 11+, this is safe if the default is a constant value.
Parse Errors
If a migration file contains invalid SQL, diesel-guard reports the file name and points to the exact failing statement:
× Failed to parse SQL: Invalid statement: syntax error at or near "@"
╭─[migrations/2024_01_01_create_users/up.sql:3:1]
2 │ CREATE TABLE b ();
3 │ CREATE TABLE @bad;
· ▲
· problematic SQL
╰─
help: Check that your SQL syntax is valid
JSON Output
For CI/CD or programmatic processing:
diesel-guard check migrations/ --format json
Inspect the AST
Use dump-ast to see the pg_query AST as JSON — essential for writing custom checks:
diesel-guard dump-ast --sql "CREATE INDEX idx_users_email ON users(email);"
diesel-guard dump-ast --file migration.sql
Example output:
[
{
"IndexStmt": {
"access_method": "btree",
"concurrent": false,
"idxname": "idx_users_email",
"if_not_exists": false,
"index_params": [
{
"node": {
"IndexElem": {
"name": "email",
...
}
}
}
],
"relation": {
"relname": "users",
"relpersistence": "p",
...
},
"unique": false,
...
}
}
]
The AST structure shown here tells you exactly which fields are available when writing custom Rhai checks. For example, node.IndexStmt.concurrent maps to the concurrent field above.