Skip to content
| Marketplace
Sign in
Visual Studio Code>Formatters>SQL River FormatterNew to Visual Studio Code? Get it now.
SQL River Formatter

SQL River Formatter

Ondrej Bartak

|
1 install
| (0) | Free
Formats T-SQL and Databricks SQL according to a JSON style configuration
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

SQL River Formatter

A VS Code extension by Ondrej Bartak that formats T-SQL and Databricks SQL according to a JSON style configuration with 115 formatting options — all of them honored. The formatting engine is custom-built (tokenizer → parser → printer) with a strict safety model: it can change whitespace and letter case, and nothing else.

Using it

  1. Open a .sql file (language mode sql).
  2. Run Format Document (or Format Document With… → SQL River Formatter, then Configure Default Formatter to make it the default). Format Selection works too and expands the selection to whole statements.
  3. On first use you'll be prompted to create a style file. It is scaffolded with every option at its default value and JSON IntelliSense via the bundled schema.

Default style: sqlstyle.guide

The default option values follow sqlstyle.guide: uppercase keywords right-aligned to a "river", lowercase identifiers, trailing commas, spaces (4-wide):

SELECT f.species_name,
       AVG(f.height) AS average_height
  FROM flora AS f
 WHERE f.species_name = 'Banksia'
   AND f.height > 100;

Case-sensitive collations: the default casing.identifiers: "lowercase" rewrites unquoted identifier casing (quoted identifiers like [Name], `name` are never touched). If your database resolves identifiers case-sensitively, set "identifiers": "leaveAsIs" in your style file.

Style files

  • Styles live in a folder owned by the extension (under VS Code's globalStorage, so they survive extension updates). Use the commands:
    • SQL River Formatter: Select Style — pick the active style (also shown in the status bar for SQL editors).
    • SQL River Formatter: Create New Style — scaffold a new style file.
    • SQL River Formatter: Open Styles Folder — reveal the folder.
  • A style file may set any subset of options; everything else falls back to the defaults from resources/formattingstyle-schema.json.
  • Invalid files produce a friendly error with Open style file / Use defaults choices; formatting never destroys code on a bad config.
  • The style file owns all whitespace decisions — VS Code's tabSize / insertSpaces settings are intentionally ignored.

Dialects

sqlRiverFormatter.dialect: auto (default) | tsql | databricks. auto detects per document (backticks, ${var}, QUALIFY, LATERAL VIEW → Databricks; [brackets], GO, @@vars, N'…', TOP → T-SQL; tie → T-SQL).

Key lexing differences handled: "…" is an identifier in T-SQL but a string in Databricks; backtick identifiers and \' escapes (Databricks); [brackets], GO batch separators, @/@@ variables, N'…', nested block comments (T-SQL); ${var} / :param pass through opaquely (Databricks).

Safety model

  • Statement isolation: the file is split into statements before parsing. A statement the engine cannot parse is passed through verbatim (with casing still applied); one bad statement never affects its neighbors. Failures are listed in the SQL River Formatter output channel and the status bar tooltip — never modal dialogs.
  • Token safety: after parsing, the AST's token walk is checked against the input token stream; the printer therefore can never add, drop, or reorder code — only whitespace and letter case change.
  • Comments round-trip: comments (including trailing -- comments) are preserved through formatting.
  • Idempotency: format(format(x)) === format(x) is enforced by tests on every fixture.

What is formatted today

Parsed & fully formatted: SELECT (DISTINCT/TOP, all JOINs, set operators, subqueries, CASE, IN, BETWEEN, window OVER), INSERT … VALUES / INSERT … SELECT, UPDATE, DELETE, WITH CTEs, ORDER/GROUP BY, LIMIT / OFFSET-FETCH tails, DECLARE / SET @var, control-flow blocks (IF/WHILE … BEGIN … END, BEGIN TRY/CATCH, nested statements inside blocks), CREATE TABLE (column defs, constraints, filegroup tails), and CREATE [OR ALTER] PROCEDURE (parameters + body).

Passed through verbatim (casing still applied): MERGE, EXEC, cursors, table variables, SET NOCOUNT ON-style options, single-statement IF without BEGIN, other DDL (CREATE INDEX/VIEW, ALTER TABLE, DROP, CTAS), and anything else the parser does not model. These pass through silently — they are not reported as errors.

Options

All 115 options in every group are honored — whitespace, lists, parentheses (full 9-value parenthesisStyle, indent, collapse), casing (incl. useObjectDefinitionCase), dml (incl. clauseAlignment: toFirstListItem), ddl, controlFlow, cte, variables, joinStatements, insertStatements, functionCalls, caseExpressions, and operators (incl. comparison.align and in.alignment).

The repository's docs/showcase.html demonstrates every option on real engine output: unformatted input → formatted output for every enum value / boolean / representative numbers, organized by the option tree, with a coverage summary and an audit of sqlstyle.guide rules (covered / out-of-scope). The same runs are pinned as golden tests, and every option must provably change the output across its demonstrated values.

Roadmap

Possible future work:

  • MERGE statement formatting.
  • ELSE IF chains and single-statement IF/WHILE bodies (today they pass through verbatim).
  • Layouts for the remaining DDL forms: CREATE INDEX/VIEW, ALTER TABLE, CTAS.
  • AS-keyword insertion for aliases (deliberately deferred: inserting tokens would break the token-safety invariant, so it needs a separate opt-in mechanism).
  • Marketplace publication.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft