(node *pg_query.Node, changed *bool)
| 52 | } |
| 53 | |
| 54 | func (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 |
no test coverage detected