MCPcopy Create free account
hub / github.com/PostHog/duckgres / walkAndTransform

Method walkAndTransform

transpiler/transform/typecast.go:54–280  ·  view source on GitHub ↗
(node *pg_query.Node, changed *bool)

Source from the content-addressed store, hash-verified

52}
53
54func (t *TypeCastTransform) walkAndTransform(node *pg_query.Node, changed *bool) {
55 if node == nil {
56 return
57 }
58
59 switch n := node.Node.(type) {
60 case *pg_query.Node_TypeCast:
61 if n.TypeCast != nil && n.TypeCast.TypeName != nil {
62 // PG curly-brace array literal cast: '{1,2,3}'::int[] -> ARRAY['1','2','3']::int[].
63 // DuckDB cannot parse PG's array_in text form; rewrite the literal to an ARRAY[...]
64 // expression and keep the element-wise ::TARGET[] cast.
65 if len(n.TypeCast.TypeName.ArrayBounds) > 0 {
66 if arrExpr := pgArrayLiteralToArrayExpr(n.TypeCast.Arg); arrExpr != nil {
67 n.TypeCast.Arg = arrExpr
68 *changed = true
69 }
70 }
71 // Check if this is a pg_catalog type cast
72 typeName := n.TypeCast.TypeName
73 typeLower := ""
74
75 if len(typeName.Names) >= 2 {
76 // Check for pg_catalog.typename pattern
77 if first := typeName.Names[0]; first != nil {
78 if str := first.GetString_(); str != nil && strings.EqualFold(str.Sval, "pg_catalog") {
79 if second := typeName.Names[1]; second != nil {
80 if typeStr := second.GetString_(); typeStr != nil {
81 typeLower = strings.ToLower(typeStr.Sval)
82 }
83 }
84 }
85 }
86 } else if len(typeName.Names) == 1 {
87 // Single name
88 if first := typeName.Names[0]; first != nil {
89 if str := first.GetString_(); str != nil {
90 typeLower = strings.ToLower(str.Sval)
91 }
92 }
93 }
94
95 // Special handling for ::regclass casts
96 // String literal: 'tablename'::regclass -> (SELECT oid FROM pg_class WHERE relname = 'tablename')
97 // OID/integer: oid_val::regclass -> (SELECT relname FROM pg_class WHERE oid = oid_val)
98 if typeLower == "regclass" {
99 // First check if argument is a string literal (table name lookup -> OID)
100 if sublink := t.createRegclassFromNameSubquery(n.TypeCast.Arg); sublink != nil {
101 node.Node = &pg_query.Node_SubLink{SubLink: sublink}
102 *changed = true
103 return
104 }
105 // Check if argument is an integer/OID (OID lookup -> table name, for ::regclass::text pattern)
106 if sublink := t.createRegclassFromOidSubquery(n.TypeCast.Arg); sublink != nil {
107 node.Node = &pg_query.Node_SubLink{SubLink: sublink}
108 *changed = true
109 return
110 }
111 // For other expressions, convert to varchar as fallback

Callers 2

TransformMethod · 0.95
walkSelectStmtMethod · 0.95

Tested by

no test coverage detected