Skip to content

feat(convert): lay out converted DuckDB SQL and helper macros with the formatter - #169

Merged
kvlonge merged 8 commits into
mainfrom
feat/convert-duckdb-layout
Nov 11, 2026
Merged

kvlonge merged 8 commits into
mainfrom
feat/convert-duckdb-layout

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

Why

sqlquack convert printed DuckDB SQL through a simple clause-per-line layout, and helper macros stayed on one line. The formatter lays SQL out better, so converted SQL and its helper macros now go through it, along with two formatter improvements that apply to every profile.

Changes

  • feat(convert): lay out converted SQL and helper macros with the DuckDB formatter at width 100, keeping token case. The CLI, the Python API and the playground all use it; --compact still prints one line. A layout whose characters other than whitespace differ is refused, and the SQL is printed on one line.
  • feat(format): break a wide window specification inside OVER, and keep a single-item BY clause and a short ON or USING on their header line. 36 of the 1,066 format corpus entries change layout.
  • fix(syntax), fix(format): keyword lambda parameters, nested parenthesised set operations, and a sign touching a modulo, found while laying out recorded output.
  • docs: CLI examples in the docs and on the landing page show the new layout.

Verification

  • make check-ci passed.
  • make verify-recorded: 12,236 cases, 0 failed, 0 unproven, and the same counts as main. translation-results shows 0 changes; sql-sizes is unchanged at 13,903,263 B over 9,375 cases.
  • Token identity: for each of the 5,253 converted recorded cases, the laid-out and compact SQL give the same DuckDB 2.0.0 token stream, and so do their 6,101 helper-macro statements. 0 mismatches.
  • The CLI examples in the docs match what the built binary prints.

… set operations

DuckDB takes a keyword such as row or top as a LAMBDA parameter name, and
((SELECT 1) UNION ALL (SELECT 2)) UNION ALL (SELECT 3) nests a set operation
in parentheses. Converted SQL uses both, so the DuckDB profile parses them.
… SQL

FormatOptions gains keep_case, which leaves every token's case as written.
The DuckDB profile now lays out what convert emits: CREATE OR REPLACE stays
together when a long macro wraps, a lambda body that starts with a
parenthesis stays an expression, /, // and % are spaced and broken as binary
operators, a keyword lambda parameter keeps its spaced colon, and a group a
broken operator leaves open is indented with it.
…tter

convert's text and JSON output, the Python API and the playground engine lay
converted SQL and its helper macros out with sqlquack-format's DuckDB profile
at 100 columns and a 4-space indent, keeping each token and its case. SQL the
formatter refuses stays on one line; --compact still prints one line. The
hand-written layout in sqlquack-blocks goes, and the docs and landing page
show the new output.
…nger one

((S1) UNION (S2)) INTERSECT (S3) passed the union to the set-operation parser
bare, so Snowflake's INTERSECT precedence moved the INTERSECT inside it and
changed the result. The parenthesised union now stays a subquery.
… operator

DuckDB lexes %- and %+ as single operators, so spacing 7%-2 as 7 % -2 would
turn an error into a value. The spacing guard now refuses to separate them.
…ses on their header

A window specification wider than the layout guide now puts PARTITION BY,
ORDER BY and its frame each on their own line inside OVER (...), instead of
leaving one long line. A narrow window stays inline.

A GROUP BY, ORDER BY or other BY clause whose single item fits now stays on
the header line (`GROUP BY a`), and a join's ON or USING condition without a
top-level AND or OR joins the JOIN line when the result fits.

The format corpus is re-recorded: 36 entries change layout, none moves
between formatted and refused, and each keeps its earlier layout as
previously_formatted. The docs samples are relaid to match.
…s convert prints it

The formatter keeps a single-item BY clause on its header line, so
`sqlquack convert revenue.sql` prints GROUP BY and its column on one
line. The docs pages already show that; the landing page still showed
the column on the next line.
…e version

The playground's lockfile recorded sqlquack-format at 0.4.1, the version
when the dependency was added. The workspace is now 0.5.1, so the
website build's --locked cargo commands refused to update it.
@kvlonge
kvlonge force-pushed the feat/convert-duckdb-layout branch from 75d60e7 to 0f0c43d Compare November 11, 2026 15:42
@kvlonge
kvlonge enabled auto-merge November 11, 2026 17:57
@kvlonge
kvlonge added this pull request to the merge queue Nov 11, 2026
Merged via the queue into main with commit 2e43768 Nov 11, 2026
15 of 19 checks passed
@kvlonge
kvlonge deleted the feat/convert-duckdb-layout branch November 11, 2026 18:47
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