Skip to content

fix: stability fixes, more tests and a corpus runner - #15

Merged
dsherret merged 4 commits into
mainfrom
fix/stability-and-corpus
Oct 18, 2026
Merged

dsherret merged 4 commits into
mainfrom
fix/stability-and-corpus

Conversation

@dsherret

Copy link
Copy Markdown
Member

These are the follow-ups to #14 that weren't pushed before it was merged.

Fixes

  • Trailing comma before FROM: SELECT a, b, FROM t (valid in BigQuery and Snowflake) left FROM on the list's line. This was a regression from the change that keeps a column named like a clause (ex. offset) in its list.
  • Output that changed on a second pass:
    • MySQL /*!50705 x,*/'2014-09-25' gained a space.
    • SELECT %x became % x. Fixing this also keeps Databricks %python magics and Exasol %jar intact.
    • A CASE whose operand broke across lines at a narrow width moved its branches onto their own lines.
  • Refusal: in Oracle, SET AUTOCOMMIT=0; was refused, because once formatted it reads as a SQL*Plus command.

Tests

  • New specs for syntax no spec reached:
    • subquery aliases, and BETWEEN within other conditions
    • comments before END, ELSE and EXCEPTION, after an opening bracket, and after a list's last item
    • lateral views, LOCK IN SHARE MODE, TOP (n) PERCENT, SELECT AS STRUCT and MATCH_RECOGNIZE
    • number literals and Oracle q'<..>' strings
    • unfinished procedural code, and empty or unformattable $$ bodies
  • New specs for options:
    • casing and the legacy uppercase together, and casing: preserve set explicitly
    • joinsAsTopLevel within a subquery
    • range formatting in SQL Server, MySQL and PostgreSQL
  • Specs that only checked stability: 67 of the 99 specs whose input was already formatted now have messy input, so they check formatting as well.
  • Unit tests that the safety check rejects losing the line break between joined strings, and compares template tags in place. There's also a test of CRLF output.

Spec-only line coverage goes from 94.1% to 95.3%.

Corpus runner

deno run -A scripts/corpus.ts fetches only the .sql files of 14 projects pinned to commits, and formats each in its own dialect:

  • PostgreSQL: the regression tests and pgTAP
  • SQL Server: Microsoft's samples, the First Responder Kit and Ola Hallengren's maintenance solution
  • Oracle: Oracle's sample schemas
  • MySQL: test_db
  • BigQuery and Snowflake: bigquery-utils and Snowflake's quickstarts
  • dbt: jaffle_shop and dbt-utils
  • Several dialects: sqlfluff's fixtures, sakila and chinook

It reports panics, refusals, unstable output, timeouts and slow files.

  • --all-dialects formats every file in every dialect.
  • --line-width 30,120 formats at several widths.
  • --compare <ref> writes how the output differs from the formatter at another ref.

It isn't run in CI. How to use it is documented in CLAUDE.md.

It found the four bugs listed above. With them fixed, all 4,304 files run clean in every dialect at widths 30 and 120: no panics, refusals, unstable output or timeouts.

BigQuery and Snowflake allow `SELECT a, b, FROM t`, whose FROM was read as
a column after the change that keeps a column named like a clause (ex.
`offset`) in its list.
- specs for syntax no spec reached: subquery aliases, BETWEEN within
  conditions, comments before END, ELSE and EXCEPTION, lateral views, LOCK
  IN SHARE MODE, TOP PERCENT, SELECT AS STRUCT, MATCH_RECOGNIZE, number and
  quoted string literals, unfinished procedural code and unformattable
  bodies
- specs for the casing and legacy uppercase options together, explicit
  preserve, joins as top level within a subquery, and range formatting in
  SQL Server, MySQL and PostgreSQL
- give the specs whose input was already formatted messy input, so they
  check formatting rather than only stability
- unit tests for checking the line breaks between joined strings and
  template tags in place, and a test of CRLF output
…E operands

Found by formatting the corpus of real projects:

- keep a block comment against the value after it (ex. MySQL's
  `/*!50705 x,*/'a'`), which once gained a space the second time
- keep a `%` against the word after it (ex. `SELECT %x`, a Databricks
  `%python` magic), which once gained a space the second time
- don't read a SET statement as a SQL*Plus command once its `=` is spaced
  (ex. `SET AUTOCOMMIT=0`), which refused to format it
- don't break the branches of a CASE onto lines because its operand broke
`deno run -A scripts/corpus.ts` fetches only the .sql files of 14 projects
pinned to commits (sqlfluff's fixtures, PostgreSQL's regression tests,
pgTAP, SQL Server samples, the First Responder Kit, Ola Hallengren's
maintenance solution, Oracle's sample schemas, test_db, sakila, chinook,
bigquery-utils, Snowflake quickstarts, jaffle_shop and dbt-utils) and
formats each in its own dialect, or in all of them with --all-dialects.
It reports panics, refusals, unstable output, timeouts and slow files,
and --compare <ref> writes how the output differs from the formatter at
another ref. It isn't run in CI.
@dsherret
dsherret merged commit 24890c0 into main Oct 18, 2026
2 checks passed
@dsherret
dsherret deleted the fix/stability-and-corpus branch October 18, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant