Skip to content

Commit dd0215b

Browse files
Ajit Pratap SinghAjit Pratap Singh
authored andcommitted
refactor(formatter): thread nodeFormatter through tableRefSQL and joinSQL
Previously these package-level renderers hardcoded keyword literals (PIVOT, UNPIVOT, FOR, IN, LATERAL, JOIN, ON) which bypassed the caller's case policy (f.kw). Thread *nodeFormatter into both functions and route every keyword through f.kw so uppercase/lowercase options apply uniformly across FROM, JOIN, MERGE, DELETE USING, and UPDATE FROM paths. Addresses claude-review feedback on PR #477. All formatter, parser, and tokenizer tests pass with -race.
1 parent 865e8c6 commit dd0215b

1 file changed

Lines changed: 41 additions & 21 deletions

File tree

pkg/formatter/render.go

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -227,15 +227,15 @@ func renderSelect(s *ast.SelectStatement, opts ast.FormatOptions) string {
227227
sb.WriteString(" ")
228228
froms := make([]string, len(s.From))
229229
for i := range s.From {
230-
froms[i] = tableRefSQL(&s.From[i])
230+
froms[i] = tableRefSQL(&s.From[i], f)
231231
}
232232
sb.WriteString(strings.Join(froms, ", "))
233233
}
234234

235235
for _, j := range s.Joins {
236236
j := j
237237
sb.WriteString(f.clauseSep())
238-
sb.WriteString(joinSQL(&j))
238+
sb.WriteString(joinSQL(&j, f))
239239
}
240240

241241
if s.Sample != nil {
@@ -400,7 +400,7 @@ func renderUpdate(u *ast.UpdateStatement, opts ast.FormatOptions) string {
400400
sb.WriteString(" ")
401401
froms := make([]string, len(u.From))
402402
for i := range u.From {
403-
froms[i] = tableRefSQL(&u.From[i])
403+
froms[i] = tableRefSQL(&u.From[i], f)
404404
}
405405
sb.WriteString(strings.Join(froms, ", "))
406406
}
@@ -452,7 +452,7 @@ func renderDelete(d *ast.DeleteStatement, opts ast.FormatOptions) string {
452452
sb.WriteString(" ")
453453
usings := make([]string, len(d.Using))
454454
for i := range d.Using {
455-
usings[i] = tableRefSQL(&d.Using[i])
455+
usings[i] = tableRefSQL(&d.Using[i], f)
456456
}
457457
sb.WriteString(strings.Join(usings, ", "))
458458
}
@@ -883,7 +883,7 @@ func renderMerge(m *ast.MergeStatement, opts ast.FormatOptions) string {
883883

884884
sb.WriteString(f.kw("MERGE INTO"))
885885
sb.WriteString(" ")
886-
sb.WriteString(tableRefSQL(&m.TargetTable))
886+
sb.WriteString(tableRefSQL(&m.TargetTable, f))
887887
if m.TargetAlias != "" {
888888
sb.WriteString(" ")
889889
sb.WriteString(m.TargetAlias)
@@ -892,7 +892,7 @@ func renderMerge(m *ast.MergeStatement, opts ast.FormatOptions) string {
892892
sb.WriteString(f.clauseSep())
893893
sb.WriteString(f.kw("USING"))
894894
sb.WriteString(" ")
895-
sb.WriteString(tableRefSQL(&m.SourceTable))
895+
sb.WriteString(tableRefSQL(&m.SourceTable, f))
896896
if m.SourceAlias != "" {
897897
sb.WriteString(" ")
898898
sb.WriteString(m.SourceAlias)
@@ -1173,11 +1173,13 @@ func orderBySQL(orders []ast.OrderByExpression) string {
11731173
return strings.Join(parts, ", ")
11741174
}
11751175

1176-
// tableRefSQL renders a TableReference.
1177-
func tableRefSQL(t *ast.TableReference) string {
1176+
// tableRefSQL renders a TableReference. The formatter is threaded through
1177+
// so PIVOT/UNPIVOT/FOR/IN/AS/LATERAL keywords honor the caller's case policy.
1178+
func tableRefSQL(t *ast.TableReference, f *nodeFormatter) string {
11781179
var sb strings.Builder
11791180
if t.Lateral {
1180-
sb.WriteString("LATERAL ")
1181+
sb.WriteString(f.kw("LATERAL"))
1182+
sb.WriteString(" ")
11811183
}
11821184
if t.Subquery != nil {
11831185
sb.WriteString("(")
@@ -1187,28 +1189,42 @@ func tableRefSQL(t *ast.TableReference) string {
11871189
sb.WriteString(t.Name)
11881190
}
11891191
if t.Pivot != nil {
1190-
sb.WriteString(" PIVOT (")
1192+
sb.WriteString(" ")
1193+
sb.WriteString(f.kw("PIVOT"))
1194+
sb.WriteString(" (")
11911195
sb.WriteString(exprSQL(t.Pivot.AggregateFunction))
1192-
sb.WriteString(" FOR ")
1196+
sb.WriteString(" ")
1197+
sb.WriteString(f.kw("FOR"))
1198+
sb.WriteString(" ")
11931199
sb.WriteString(t.Pivot.PivotColumn)
1194-
sb.WriteString(" IN (")
1200+
sb.WriteString(" ")
1201+
sb.WriteString(f.kw("IN"))
1202+
sb.WriteString(" (")
11951203
sb.WriteString(strings.Join(t.Pivot.InValues, ", "))
11961204
sb.WriteString("))")
11971205
}
11981206
if t.Unpivot != nil {
1199-
sb.WriteString(" UNPIVOT (")
1207+
sb.WriteString(" ")
1208+
sb.WriteString(f.kw("UNPIVOT"))
1209+
sb.WriteString(" (")
12001210
sb.WriteString(t.Unpivot.ValueColumn)
1201-
sb.WriteString(" FOR ")
1211+
sb.WriteString(" ")
1212+
sb.WriteString(f.kw("FOR"))
1213+
sb.WriteString(" ")
12021214
sb.WriteString(t.Unpivot.NameColumn)
1203-
sb.WriteString(" IN (")
1215+
sb.WriteString(" ")
1216+
sb.WriteString(f.kw("IN"))
1217+
sb.WriteString(" (")
12041218
sb.WriteString(strings.Join(t.Unpivot.InColumns, ", "))
12051219
sb.WriteString("))")
12061220
}
12071221
if t.Alias != "" {
12081222
// PIVOT/UNPIVOT aliases conventionally use AS to avoid ambiguity
12091223
// with the closing paren of the clause.
12101224
if t.Pivot != nil || t.Unpivot != nil {
1211-
sb.WriteString(" AS ")
1225+
sb.WriteString(" ")
1226+
sb.WriteString(f.kw("AS"))
1227+
sb.WriteString(" ")
12121228
} else {
12131229
sb.WriteString(" ")
12141230
}
@@ -1241,13 +1257,17 @@ func sampleSQL(s *ast.SampleClause, f *nodeFormatter) string {
12411257
}
12421258

12431259
// joinSQL renders a JOIN clause.
1244-
func joinSQL(j *ast.JoinClause) string {
1260+
func joinSQL(j *ast.JoinClause, f *nodeFormatter) string {
12451261
var sb strings.Builder
1246-
sb.WriteString(j.Type)
1247-
sb.WriteString(" JOIN ")
1248-
sb.WriteString(tableRefSQL(&j.Right))
1262+
sb.WriteString(f.kw(j.Type))
1263+
sb.WriteString(" ")
1264+
sb.WriteString(f.kw("JOIN"))
1265+
sb.WriteString(" ")
1266+
sb.WriteString(tableRefSQL(&j.Right, f))
12491267
if j.Condition != nil {
1250-
sb.WriteString(" ON ")
1268+
sb.WriteString(" ")
1269+
sb.WriteString(f.kw("ON"))
1270+
sb.WriteString(" ")
12511271
sb.WriteString(exprSQL(j.Condition))
12521272
}
12531273
return sb.String()

0 commit comments

Comments
 (0)