Skip to content

Commit 8194d94

Browse files
kyleconroyclaude
andcommitted
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 <[email protected]>
1 parent dc44702 commit 8194d94

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed

internal/engine/postgresql/reserved.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,39 @@ func (p *Parser) QuoteIdent(s string) string {
2222
return s
2323
}
2424

25+
// TypeName returns the SQL type name for the given namespace and name.
26+
// This implements the format.Formatter interface.
27+
func (p *Parser) TypeName(ns, name string) string {
28+
if ns == "pg_catalog" {
29+
switch name {
30+
case "int4":
31+
return "integer"
32+
case "int8":
33+
return "bigint"
34+
case "int2":
35+
return "smallint"
36+
case "float4":
37+
return "real"
38+
case "float8":
39+
return "double precision"
40+
case "bool":
41+
return "boolean"
42+
case "bpchar":
43+
return "character"
44+
case "timestamptz":
45+
return "timestamp with time zone"
46+
case "timetz":
47+
return "time with time zone"
48+
default:
49+
return name
50+
}
51+
}
52+
if ns != "" {
53+
return ns + "." + name
54+
}
55+
return name
56+
}
57+
2558
// https://www.postgresql.org/docs/current/sql-keywords-appendix.html
2659
func (p *Parser) IsReservedKeyword(s string) bool {
2760
switch strings.ToLower(s) {

internal/sql/ast/print.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ func (t *TrackedBuffer) QuoteIdent(s string) string {
3434
return s
3535
}
3636

37+
// TypeName returns the SQL type name for the given namespace and name.
38+
// If no formatter is set, it returns "ns.name" or just "name".
39+
func (t *TrackedBuffer) TypeName(ns, name string) string {
40+
if t.formatter != nil {
41+
return t.formatter.TypeName(ns, name)
42+
}
43+
if ns != "" {
44+
return ns + "." + name
45+
}
46+
return name
47+
}
48+
3749
func (t *TrackedBuffer) astFormat(n Node) {
3850
if ft, ok := n.(nodeFormatter); ok {
3951
ft.Format(t)

internal/sql/ast/type_name.go

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -20,68 +20,30 @@ func (n *TypeName) Pos() int {
2020
return n.Location
2121
}
2222

23-
// mapTypeName converts internal PostgreSQL type names to their SQL equivalents
24-
func mapTypeName(name string) string {
25-
switch name {
26-
case "int4":
27-
return "integer"
28-
case "int8":
29-
return "bigint"
30-
case "int2":
31-
return "smallint"
32-
case "float4":
33-
return "real"
34-
case "float8":
35-
return "double precision"
36-
case "bool":
37-
return "boolean"
38-
case "bpchar":
39-
return "character"
40-
case "timestamptz":
41-
return "timestamp with time zone"
42-
case "timetz":
43-
return "time with time zone"
44-
default:
45-
return name
46-
}
47-
}
48-
4923
func (n *TypeName) Format(buf *TrackedBuffer) {
5024
if n == nil {
5125
return
5226
}
5327
if items(n.Names) {
54-
// Check if this is a pg_catalog type that should be expanded
28+
// Check if this is a qualified type (e.g., pg_catalog.int4)
5529
if len(n.Names.Items) == 2 {
5630
first, _ := n.Names.Items[0].(*String)
5731
second, _ := n.Names.Items[1].(*String)
58-
if first != nil && second != nil && first.Str == "pg_catalog" {
59-
// pg_catalog.timestamptz -> timestamp with time zone
60-
// pg_catalog.timetz -> time with time zone
61-
// etc.
62-
buf.WriteString(mapTypeName(second.Str))
32+
if first != nil && second != nil {
33+
buf.WriteString(buf.TypeName(first.Str, second.Str))
6334
goto addMods
6435
}
6536
}
66-
// For single name types, just output as-is (don't expand)
37+
// For single name types, just output as-is
6738
if len(n.Names.Items) == 1 {
6839
if s, ok := n.Names.Items[0].(*String); ok {
69-
buf.WriteString(s.Str)
40+
buf.WriteString(buf.TypeName("", s.Str))
7041
goto addMods
7142
}
7243
}
7344
buf.join(n.Names, ".")
74-
} else if n.Schema == "pg_catalog" {
75-
// pg_catalog.typename -> expanded form (via Schema/Name fields)
76-
buf.WriteString(mapTypeName(n.Name))
77-
} else if n.Schema != "" {
78-
// schema.typename
79-
buf.WriteString(n.Schema)
80-
buf.WriteString(".")
81-
buf.WriteString(n.Name)
8245
} else {
83-
// Simple type name - don't expand aliases
84-
buf.WriteString(n.Name)
46+
buf.WriteString(buf.TypeName(n.Schema, n.Name))
8547
}
8648
addMods:
8749
// Add type modifiers (e.g., varchar(255))

internal/sql/format/format.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@ type Formatter interface {
55
// QuoteIdent returns a quoted identifier if it needs quoting
66
// (e.g., reserved words, mixed case identifiers)
77
QuoteIdent(s string) string
8+
9+
// TypeName returns the SQL type name for the given namespace and name.
10+
// This handles dialect-specific type name mappings (e.g., pg_catalog.int4 -> integer)
11+
TypeName(ns, name string) string
812
}

0 commit comments

Comments
 (0)