Commit 405a905
feat(ast): implement comprehensive SQL AST formatting (#4205)
* refactor(fmt_test): use config-based engine detection and parser for statement boundaries
- Parse sqlc config file to determine database engine instead of
hardcoding pgx/v5 path filter
- Use parser's StmtLocation/StmtLen for proper statement boundaries
instead of naive semicolon splitting
- Handle both file and directory paths in queries config
- Only test PostgreSQL for now (formatting support is PostgreSQL-only)
This fixes issues with multi-query files containing semicolons in
strings, PL/pgSQL functions, or DO blocks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(ast): add and improve Format methods for SQL AST nodes
Add Format methods:
- A_ArrayExpr: Format ARRAY[...] literals
- NullIfExpr: Format NULLIF(arg1, arg2) function calls
- OnConflictClause: Format ON CONFLICT ... DO UPDATE/NOTHING
- InferClause: Format conflict target (columns) or ON CONSTRAINT
- IndexElem: Format index elements for conflict targets
- WindowDef: Format window definitions with PARTITION BY, ORDER BY, and frame clauses
Improve existing Format methods:
- A_Expr: Add BETWEEN, NOT BETWEEN, ILIKE, SIMILAR TO, IS DISTINCT FROM handling
- A_Expr_Kind: Add all expression kind constants
- CaseExpr: Handle CASE with test argument and optional ELSE
- DeleteStmt: Add USING clause formatting
- FuncCall: Add DISTINCT, ORDER BY, FILTER, and OVER clause support
- InsertStmt: Delegate to OnConflictClause.Format
- JoinExpr: Add RIGHT JOIN, FULL JOIN, NATURAL, and USING clause
- LockingClause: Add OF clause, SKIP LOCKED, NOWAIT, and fix strength values
- RangeFunction: Add LATERAL support and fix alias spacing
- SelectStmt: Add HAVING clause formatting
These changes reduce test failures from 135 to 102.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(ast): add more Format methods for SQL AST nodes
Add Format methods:
- NullTest: Format IS NULL / IS NOT NULL expressions
- ScalarArrayOpExpr: Format scalar op ANY/ALL (array) expressions
- CommonTableExpr: Add column alias list support
Improve existing Format methods:
- WithClause: Fix spacing after WITH and RECURSIVE keywords
These changes reduce test failures from 102 to 91.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(postgresql): add custom Deparse wrapper with bug fixes
- Switch fmt_test.go to use postgresql.Deparse instead of ast.Format
- Add deparse.go and deparse_wasi.go with Deparse wrapper function
- Fix pg_query_go bug: missing space before SKIP LOCKED
- Skip tests with parse errors (e.g., syntax_errors test cases)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(ast): complete SQL AST formatting implementation
Fixes all ast.Format test failures by implementing comprehensive
Format methods for SQL AST nodes. Key improvements include:
- Named parameters (@param) formatting without space after @
- NULLIF expression support in A_Expr
- NULLS FIRST/LAST in ORDER BY clauses
- Type name mapping (int4→integer, timestamptz→timestamp with time zone)
- Array type support (text[]) and type modifiers (varchar(32))
- CREATE FUNCTION with parameters, options (AS, LANGUAGE), and modes
- CREATE EXTENSION statement formatting
- DO $$ ... $$ anonymous code blocks
- WITHIN GROUP clause for ordered-set aggregates
- Automatic quoting for SQL reserved words and mixed-case identifiers
- CROSS JOIN detection (JOIN without ON/USING clause)
- LATERAL keyword in subselects and function calls
- Array subscript access in UPDATE statements (names[$1])
- Proper AS keyword before aliases
Also removes unused deparse files and cleans up fmt_test.go to use
ast.Format directly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(postgresql): use existing convert functions instead of translate helpers
Replace custom translate functions (translateTypeNameFromPG, translateOptions,
translateNode, translateDefElem) with existing convert.go functions
(convertTypeName, convertSlice) to maintain architectural consistency.
Both parse.go and convert.go import the same pg_query_go/v6 package, so the
types are compatible and the existing convert functions can be used directly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(format): add Formatter interface for SQL dialect-specific quoting
- Create internal/sql/format package with Formatter interface
- Add QuoteIdent method to TrackedBuffer that delegates to Formatter
- Implement QuoteIdent on postgresql.Parser using existing IsReservedKeyword
- Update all Format() methods to use buf.QuoteIdent() instead of local quoteIdent()
- Remove duplicate reserved word logic from ast/column_ref.go
- Update ast.Format() to accept a Formatter parameter
This allows each SQL dialect to provide its own identifier quoting logic
based on its reserved keywords and quoting rules.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(format): add TypeName method to Formatter interface
- Add TypeName(ns, name string) string method to Formatter interface
- Implement TypeName on postgresql.Parser with pg_catalog type mappings
- Add TypeName method to TrackedBuffer that delegates to Formatter
- Update ast.TypeName.Format to use buf.TypeName()
- Remove mapTypeName from ast package (moved to postgresql package)
This allows each SQL dialect to provide its own type name mappings
(e.g., pg_catalog.int4 -> integer for PostgreSQL).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(postgresql): restore parseRelationFromNodes for column type resolution
The convertTypeName function populates extra fields (Names, ArrayBounds,
Typmods) on the TypeName struct which breaks the catalog's type equality
check used for ALTER TYPE RENAME operations.
This change:
- Reverts to using parseRelationFromNodes + rel.TypeName() which only
populates Catalog, Schema, Name fields needed for type resolution
- Updates ColumnDef.Format to use IsArray field for array formatting
since TypeName.ArrayBounds is no longer set
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 3436b28 commit 405a905
File tree
40 files changed
+851
-107
lines changed- internal
- endtoend
- engine/postgresql
- sql
- ast
- format
40 files changed
+851
-107
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
18 | | - | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | 21 | | |
32 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
33 | 25 | | |
34 | 26 | | |
35 | 27 | | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
57 | 44 | | |
58 | | - | |
59 | | - | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
60 | 51 | | |
61 | | - | |
| 52 | + | |
62 | 53 | | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
69 | 63 | | |
70 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
71 | 126 | | |
72 | 127 | | |
73 | 128 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1965 | 1965 | | |
1966 | 1966 | | |
1967 | 1967 | | |
| 1968 | + | |
| 1969 | + | |
| 1970 | + | |
| 1971 | + | |
| 1972 | + | |
| 1973 | + | |
| 1974 | + | |
| 1975 | + | |
| 1976 | + | |
| 1977 | + | |
| 1978 | + | |
| 1979 | + | |
| 1980 | + | |
| 1981 | + | |
| 1982 | + | |
| 1983 | + | |
1968 | 1984 | | |
1969 | 1985 | | |
1970 | 1986 | | |
| |||
3420 | 3436 | | |
3421 | 3437 | | |
3422 | 3438 | | |
| 3439 | + | |
| 3440 | + | |
| 3441 | + | |
3423 | 3442 | | |
3424 | 3443 | | |
3425 | 3444 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
494 | 494 | | |
495 | 495 | | |
496 | 496 | | |
| 497 | + | |
497 | 498 | | |
498 | 499 | | |
499 | 500 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
5 | 58 | | |
6 | 59 | | |
7 | 60 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
21 | 19 | | |
22 | 20 | | |
| 21 | + | |
23 | 22 | | |
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
29 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
30 | 97 | | |
31 | | - | |
32 | | - | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
33 | 102 | | |
34 | 103 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
8 | 20 | | |
9 | 21 | | |
10 | 22 | | |
| |||
0 commit comments