Skip to content

fmt: preserve ') VALUES (' seams and !=/<> operator spellings - #4597

Open
kyleconroy wants to merge 1 commit into
mainfrom
claude/cloud-repo-sqlc-fmt-3jmuk3
Open

fmt: preserve ') VALUES (' seams and !=/<> operator spellings#4597
kyleconroy wants to merge 1 commit into
mainfrom
claude/cloud-repo-sqlc-fmt-3jmuk3

Conversation

@kyleconroy

Copy link
Copy Markdown
Collaborator

Two formatting fixes found by running sqlc fmt on a real project (sqlc-dev/cloud#604).

) VALUES ( seams broke apart

The boundary before a bare VALUES list was decided by comparing the source lines of the neighbouring nodes — the last column name and the first value. When both paren lists are multi-line those always sit on different lines, so an authored seam was forced apart:

INSERT INTO archives (
  id,
  project_id
) VALUES (          -- was reformatted to `)` + newline + `VALUES (`
  $1,
  $2
);

The seam now gets its own layout group in InsertStmt.Format, and AttachComments reads the author's actual choice out of the source: scanning back from the first value across ( and the VALUES keyword, the whitespace in front of the keyword says whether the author broke the line. Glued stays glued; VALUES on its own line stays on its own line. Source that doesn't scan cleanly (an extra paren, a comment against the keyword) falls back to the old heuristic.

!= and <> were rewritten to each other

PostgreSQL's grammar normalizes != to <> before the AST exists, so fmt printed <> for authors who wrote !=. The MySQL converter mapped opcode.NE to != unconditionally, rewriting in the other direction. Both format parsers now read the author's spelling back out of the source, the same way the SQLite converter already did:

  • PostgreSQL gets a NewFormatParser that rewrites A_Expr names at the operator's recorded location (the A_Expr location points at the operator token). The compiler keeps using NewParser, which preserves the canonical <> the catalog knows.
  • The dolphin format parser (already split off for identifier-case preservation) threads the source into the converter and checks the token in front of the right operand.

Testing

  • Extended internal/endtoend/testdata/fmt/{postgresql,mysql} with a multi-line ) VALUES ( INSERT, a broken-seam INSERT, and mixed !=/<> queries; regenerated goldens. The new cases produce no diff hunks — fmt leaves them exactly as written.
  • Full TestReplay/base corpus and TestFormat pass.
  • Re-ran the fixed fmt on the cloud repo's queries: seams and spellings preserved, output still AST-equivalent, sqlc fmt idempotent on the result.

🤖 Generated with Claude Code

https://claude.ai/code/session_01T4UpYmwPdxzePtsRXoL1H8


Generated by Claude Code

Two formatting fixes reported from running sqlc fmt on a real project:

The boundary before a bare VALUES list was decided by comparing the
source lines of the neighbouring nodes (the last column and the first
value), which always differ when both paren lists are multi-line — so
an authored ') VALUES (' seam broke apart. The seam now gets its own
group, and AttachComments reads the author's actual choice out of the
source by scanning back from the first value across '(' and the VALUES
keyword.

The parsers normalized inequality spellings: PostgreSQL's grammar turns
!= into <>, and the MySQL converter mapped opcode.NE to != regardless
of what was written. The format parsers now read the author's spelling
back out of the source — PostgreSQL via a new NewFormatParser that
rewrites A_Expr names at the operator's recorded location, MySQL via
the same source-scan approach SQLite already used. The compiler's
parsers keep the canonical names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4UpYmwPdxzePtsRXoL1H8
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.

2 participants