feat(dml): implement DML statement formatting and tests
CI / Test (push) Failing after 45s
CI / Build snapshot (push) Has been skipped

* Add formatDML function for formatting top-level DML statements
* Introduce tests for various DML scenarios including SELECT, INSERT, UPDATE, and DELETE
* Enhance printer to handle DML statements correctly
This commit is contained in:
2026-06-28 16:20:37 +02:00
parent f378bf4a18
commit a98dee1877
4 changed files with 727 additions and 2 deletions
+19 -2
View File
@@ -142,8 +142,25 @@ Legend: ✅ done · 🚧 in progress · ⬜ not started
3. ✅ Idempotence: `fmt(fmt(x)) == fmt(x)` (corpus + CLI tests).
4. ✅ Graceful degradation: unparsable spans pass through verbatim (Raw nodes + verbatim body).
## ✅ DML statement formatting (top-level)
- `pkg/format/dml.go`: `formatDML` formats top-level SELECT/INSERT/UPDATE/DELETE/WITH.
- Clause-per-line layout at depth-0 boundaries; handles: SELECT, FROM, WHERE, HAVING,
GROUP BY, ORDER BY, LIMIT, OFFSET, RETURNING, JOIN variants (LEFT/RIGHT/INNER/FULL/
CROSS/NATURAL, optional OUTER), ON CONFLICT, UNION/INTERSECT/EXCEPT, SET, VALUES,
INSERT INTO, DELETE FROM, WITH (including multi-CTE bodies).
- SELECT, SET, and RETURNING bodies formatted as leading-comma column lists.
- Keywords inside subqueries (paren depth > 0) cased correctly via `dmlInline`.
- `needSpace`: added `parenKws` set (AS, EXISTS, IN, NOT, LIKE, ILIKE, SIMILAR) so
these keywords get a space before `(` instead of the no-space function-call rule.
- Printer `writeItem`: detects DML-starting Raw nodes and routes to `formatDML`.
- Tests: 13 targeted golden tests + idempotence sweep in `pkg/format/dml_test.go`.
- Note: table name before `(` in INSERT column list is indistinguishable from a
function call at the token level — formatted without space (known limitation).
- Note: SQL keywords inside PL/pgSQL function bodies remain lowercase (matching
the corpus golden files); casing is applied only to top-level DML.
- _Still TODO: Wadler Doc-IR printer for width-aware wrapping of long lines._
- _Still TODO: LSP range formatting._
## Open risks
- Lossless PL/pgSQL recursive-descent parser is the largest effort; pass-through fallback
bounds risk and allows shipping construct-by-construct.
- `go-pgquery` tracks PG17 (not PG18) — fine for lint; irrelevant to formatter path.
- Leading-comma + one-per-line is a first-class style option, not an afterthought.