Skip to content

fix: keep DuckDB array-slice colon dense inside [ ] - #960

Open
gaoflow wants to merge 1 commit into
sql-formatter-org:masterfrom
gaoflow:fix/duckdb-array-slice-colon-spacing
Open

fix: keep DuckDB array-slice colon dense inside [ ]#960
gaoflow wants to merge 1 commit into
sql-formatter-org:masterfrom
gaoflow:fix/duckdb-array-slice-colon-spacing

Conversation

@gaoflow

@gaoflow gaoflow commented Jul 27, 2026

Copy link
Copy Markdown

DuckDB's array-slice operator formats with a stray space: foo[:5] comes out as foo[: 5] and baz[1:5] as baz[1: 5].

Root cause

Commit f9575c0 ("Support ':' as struct key-value separator") removed ':' from DuckDB's alwaysDenseOperators, so struct literals like {'a': 1} keep the space after the colon. As a side effect the array-slice colon, which travels the same generic operator-spacing path, also became spaced. The identical test still passes for PostgreSQL (which keeps ':' dense and has no struct literals), and the DuckDB copy was skipped with a // TODO: This currently conflicts with ":"-operator in struct literals.

The colon is genuinely context-dependent in DuckDB — dense inside [...] (array slice), spaced inside {...} (struct key) — but alwaysDenseOperators is a flat, dialect-global list with no notion of context, so neither setting is correct for both.

Fix

Make the ':' spacing decision depend on the nearest enclosing bracket rather than being dialect-global: dense inside [...], spaced otherwise. The bracket context flows through the recursive ExpressionFormatter (each parenthesis passes its own openParen down to its children), so a struct nested in a list — [{'a': 1}] — still gets the spaced colon because its nearest bracket is {.

Only the colon-followed-by-a-value case was visibly wrong (foo[:5], baz[1:5]); bar[1:] and zap[:] already rendered correctly because the trailing space was absorbed by the closing bracket.

Tests

  • Un-skips the pre-existing supports array slice operator test (all four forms: foo[:5], bar[1:], baz[1:5], zap[:]).
  • Adds a test pinning both directions in one statement — {'k': list[1:5]} — where the struct colon stays spaced while the slice colon is dense.

The four formats {} struct literal ... and formats prefix aliases tests double as an over-fix guard: making : dense unconditionally passes the slice test but breaks all of them. Full pnpm test is green across every dialect.

Note

alwaysDenseOperators has no context mechanism today, so I threaded the bracket context through the formatter rather than widening that config surface. If you'd prefer a different shape (e.g. recognising the slice colon at the grammar level), happy to adjust.

DuckDB dropped ':' from alwaysDenseOperators (f9575c0) so struct literals
like {'a': 1} get their key-value space. That also spaced the array-slice
colon, so foo[:5] formatted as foo[: 5] and baz[1:5] as baz[1: 5]. Only the
colon followed by a value was affected; bar[1:] and zap[:] were already fine.

Make the ':' spacing depend on the nearest enclosing bracket rather than
being dialect-global: dense inside [ ] (array slice), spaced elsewhere
({ } struct keys, prefix aliases). This keeps the struct-literal fix intact.

Un-skips the existing "supports array slice operator" test.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 942768cf-7f95-4dc8-a454-10c6df1f5703

📥 Commits

Reviewing files that changed from the base of the PR and between aa8efae and d248e73.

📒 Files selected for processing (2)
  • src/formatter/ExpressionFormatter.ts
  • test/duckdb.test.ts

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved formatting for array-slice expressions by removing unnecessary spacing around the slice colon.
    • Preserved standard spacing for colons in struct and list literals.
  • Tests

    • Enabled coverage for array-slice formatting.
    • Added validation to distinguish array-slice colons from literal key/value colons.

Walkthrough

ExpressionFormatter now propagates enclosing bracket context to nested expressions, allowing array-slice colons to be formatted densely without changing struct or list literal colon spacing. DuckDB tests cover multiple slice forms and mixed literal expressions.

Changes

Array slice formatting

Layer / File(s) Summary
Bracket-context propagation and colon spacing
src/formatter/ExpressionFormatter.ts, test/duckdb.test.ts
Formatter instances carry enclosing bracket context through nested and inline expressions; colons inside square brackets use dense spacing, with DuckDB tests covering slice syntax and spaced literal colons.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: nene, sarathfrancis90

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: keeping DuckDB array-slice colons dense inside brackets.
Description check ✅ Passed The description directly explains the DuckDB colon-spacing fix, root cause, and tests, and matches the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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