Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Command line

sqlsift [OPTIONS] <COMMAND>

Commands:
  init    Detect the project layout and write sqlsift.toml
  check   Check SQL files against schema definitions
  impact  Show the queries a schema change breaks or fixes
  rules   List all rules with their category and default level
  schema  Display the schema sqlsift loaded (tables, views, enum types)
  parse   Parse SQL and display AST (for debugging)

Global options:
  -v, --verbose   Enable verbose logging to stderr (-vv for debug)
  -q, --quiet     Suppress summary/non-error output
  -h, --help      Print help
  -V, --version   Print version

sqlsift init

sqlsift init [OPTIONS] [DIR]

Arguments:
  [DIR]                  Project directory [default: current directory]

Options:
      --force            Overwrite an existing sqlsift.toml
  -d, --dialect <NAME>   SQL dialect to write instead of the detected one
      --no-check         Don't run a first check after writing sqlsift.toml
      --dry-run          Print the configuration to stdout instead of writing sqlsift.toml

Looks at the project, writes a commented sqlsift.toml in DIR, runs a first sqlsift check with it and prints a summary (diagnostics per rule) and the next steps. It never asks questions, so it also works in scripts. An existing sqlsift.toml is left alone unless --force is given. Directories of dependencies and build output (node_modules, target, vendor, dist, ...) and hidden directories are not searched.

FoundWritten
sqlc.yaml / sqlc.yml / sqlc.jsonschema / schema_dir and files from its schema and queries, dialect from engine
prisma/migrations/, schema.prismaschema_dir = "prisma/migrations", dialect from the datasource provider
prisma/sql/ (TypedSQL)files
supabase/migrations/schema_dir, dialect = "postgresql"
Drizzle output (drizzle/, out of drizzle.config.*)schema_dir, dialect from the config's dialect
Flyway (V1__name.sql), golang-migrate / sqlx (*.up.sql), goose, dbmate or plain SQL migrations in a migrations/ / migration/ / migrate/ directoryschema_dir
db/structure.sql (Rails), schema.sql, *_schema.sql dumps, schema/ directories of DDLschema / schema_dir; for Rails, dialect from config/database.yml
dbt_project.ymlfiles for the models (model-paths); the dialect from profiles.yml in the project or the dbt-<adapter> requirement
Other .sql filesfiles, grouped by directory and kept clear of the schema files (with ignore where needed)
.ts / .js / .vue / .svelte files with sql`...` or Prisma $queryRaw`...` templatesfiles, and embedded_sql_tags for $queryRaw / $executeRaw

When several schema sources are found, the most specific one is used and the others are written as comments. The dialect comes from the most specific source: the tool's own configuration first, then DATABASE_URL in .env.example / .env.sample / .env, database images in docker-compose.yml, database drivers in package.json, go.mod, Gemfile, Python requirements or Cargo.toml, and finally the syntax of the schema files; otherwise PostgreSQL. Disagreeing hints are printed. When the first check reports many diagnostics, init suggests a baseline.

Exit codes: 0 when the configuration was written (whatever the first check found), 2 when sqlsift.toml already exists (without --force) or the options are invalid.

sqlsift check

sqlsift check [OPTIONS] [FILES]...

Arguments:
  [FILES]...                SQL, TypeScript or JavaScript files to check (glob patterns supported; `-` reads stdin).
                            Defaults to `files` in sqlsift.toml.

Options:
  -s, --schema <FILE>       Schema definition file (repeatable)
      --schema-dir <DIR>    Directory containing schema files
      --ignore <PATTERN>    Skip query files matching a glob pattern (repeatable)
  -c, --config <FILE>       Path to configuration file [default: sqlsift.toml in the
                            current or a parent directory]
  -A, --allow <RULE>        Turn a rule or category off (alias: --disable)
  -W, --warn <RULE>         Report a rule or category as warnings
  -D, --deny <RULE>         Report a rule or category as errors
  -d, --dialect <NAME>      SQL dialect: postgresql, mysql, sqlite, snowflake, bigquery, redshift, databricks [default: postgresql]
      --templating <ENGINE> Query file templating: jinja (dbt models), none [default: jinja
                            when dbt_project.yml is in the current or the config file's
                            directory or above the query file, else none]
      --dbt-catalog <PATH>  dbt catalog.json with the columns of the models and sources
                            that ref() / source() name (alpha) [default:
                            target/catalog.json of the dbt project, if it exists]
  -f, --format <FORMAT>     Output format: human, json, sarif, github [default: human]
      --max-errors <N>      Maximum number of errors before stopping [default: 100, 0 = unlimited]
      --max-warnings <N>    Fail (exit 1) when more than N warnings are reported
      --baseline <PATH>     Baseline file of known diagnostics, which are not reported
      --write-baseline      Write every current diagnostic of the checked files to the
                            baseline file and exit 0, keeping the entries of other files
                            that still exist (--baseline, `baseline` in sqlsift.toml, or
                            sqlsift-baseline.json)
      --stdin-filename <PATH>
                            File name to report for the query read from stdin (`-`)

Command-line options override sqlsift.toml. -A, -W and -D accept a rule code (E0006), a rule name (ambiguous-column) or a category (suspicious), and can be repeated.

Exit codes: 0 no errors, 1 errors reported (or more warnings than --max-warnings), 2 usage or configuration error (including a missing or invalid baseline file). Diagnostics in the baseline don't count; see Baseline.

sqlsift impact

sqlsift impact [OPTIONS] [MIGRATIONS]...

Arguments:
  [MIGRATIONS]...           Migration (schema) files whose effect is shown (glob patterns
                            supported). Required unless --base is given.

Options:
      --base <REV>          Also the schema files added or changed since the current branch
                            left this git revision (e.g. origin/main), uncommitted and
                            untracked files included
      --references          Also list the lines that use a changed table or view without a
                            diagnostic changing (where to look when reviewing the change)
      --queries <PATTERN>   Query files to check (repeatable, glob patterns supported)
                            [default: `files` in sqlsift.toml]
  -s, --schema <FILE>       Schema definition file (repeatable)
      --schema-dir <DIR>    Directory containing schema files
      --ignore <PATTERN>    Skip query files matching a glob pattern (repeatable)
  -c, --config <FILE>       Path to configuration file
  -A, --allow <RULE>        Turn a rule or category off (alias: --disable)
  -W, --warn <RULE>         Report a rule or category as warnings
  -D, --deny <RULE>         Report a rule or category as errors
  -d, --dialect <NAME>      SQL dialect [default: postgresql]
      --templating <ENGINE> Query file templating: jinja, none
      --dbt-catalog <PATH>  dbt catalog.json (alpha)
  -f, --format <FORMAT>     Output format: human, json, sarif, github [default: human]

impact builds the schema twice, without and with the migrations, checks the query files against both and reports only the diagnostics that differ: those the change introduces and those it fixes. Problems the queries already had are not shown.

  • A migration that is one of the schema files is left out of the "before" schema together with every schema file after it (files are applied in filename order). A migration that isn't one of them is applied after all schema files.
  • Only query files that name a changed table or view are checked, so the run stays fast on large projects. Changes that can affect any query (enum types, the search path, functions the schema defines) check every file.
  • A diagnostic whose message changes but stays at the same place (a different type in a type mismatch) counts as the same problem.
$ sqlsift impact --base origin/main
Impact of migrations/0042_rename_email.sql
  changed table public.users

error[E0002]: Column 'email' not found in table 'users'
  --> queries/users.sql:12:12
   ...
    = help: 'email' was renamed to 'email_address' in migrations/0042_rename_email.sql:1

The change introduces 1 problem(s) in 1 file(s) and fixes 0
Checked 3 of 41 query file(s); the others name no changed table or view

With --format json the output is {"migrations": [...], "changes": [{"name", "kind", "relation"}], "other_changes": bool, "introduced": [...], "resolved": [...]}, where introduced and resolved list files and diagnostics as check --format json does. sarif and github report what the change introduces.

With --references, the JSON output also has references: [{"file", "lines": [{"line", "uses": ["public.users", "public.users.email", ...]}]}].

Exit codes: 0 the change introduces no errors, 1 it does, 2 usage or configuration error.

sqlsift schema

sqlsift schema [OPTIONS] [FILES]...

Arguments:
  [FILES]...                Schema definition files (same as --schema; glob patterns supported)

Options:
  -s, --schema <FILE>       Schema definition file (repeatable)
      --schema-dir <DIR>    Directory containing schema files
  -c, --config <FILE>       Path to configuration file
  -d, --dialect <NAME>      SQL dialect: postgresql, mysql, sqlite, snowflake, bigquery, redshift, databricks [default: postgresql]
  -f, --format <FORMAT>     Output format: human, json [default: human]

Without schema arguments, the schema settings from sqlsift.toml are used. See Loading your schema.

sqlsift rules

Prints every rule with its code, name, category, default level and description. See Rules and levels.

sqlsift parse

sqlsift parse <FILE>

Prints the parsed syntax tree of a file. Useful when reporting a parse problem.