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

Method rewriteFormat

transpiler/transform/functions_compat.go:65–127  ·  view source on GitHub ↗

rewriteFormat rewrites format('...literal template...', args...) with PG %-specifiers into a || concatenation. Only fires for a literal first arg containing at least one %-spec. NULL handling matches PG: %s renders NULL as empty string (coalesce), %L as the unquoted keyword NULL (quote_nullable); %I

(node *pg_query.Node, fc *pg_query.FuncCall)

Source from the content-addressed store, hash-verified

63// to an error() call: DuckDB's native format would silently return the template
64// unsubstituted, which is the exact corruption mode this transform exists to fix.
65func (t *FunctionTransform) rewriteFormat(node *pg_query.Node, fc *pg_query.FuncCall) bool {
66 if len(fc.Args) == 0 {
67 return false
68 }
69 tmpl := extractStringConstant(fc.Args[0])
70 if tmpl == "" || !strings.Contains(tmpl, "%") {
71 return false // non-literal or no specifier: leave for native format
72 }
73 rewriteToError := func(msg string) bool {
74 node.Node = funcCallNode("error", strConstNode(msg)).Node
75 return true
76 }
77 var segments []*pg_query.Node
78 var lit strings.Builder
79 flushLit := func() {
80 if lit.Len() > 0 {
81 segments = append(segments, strConstNode(lit.String()))
82 lit.Reset()
83 }
84 }
85 argIdx := 1 // Args[0] is the template
86 for i := 0; i < len(tmpl); i++ {
87 if tmpl[i] != '%' {
88 lit.WriteByte(tmpl[i])
89 continue
90 }
91 if i+1 >= len(tmpl) {
92 return rewriteToError("format(): unterminated format specifier")
93 }
94 spec := tmpl[i+1]
95 i++
96 switch spec {
97 case '%':
98 lit.WriteByte('%')
99 case 's', 'I', 'L':
100 if argIdx >= len(fc.Args) {
101 return rewriteToError("format(): too few arguments for format string")
102 }
103 arg := fc.Args[argIdx]
104 argIdx++
105 flushLit()
106 switch spec {
107 case 's':
108 // PG renders a NULL %s argument as the empty string.
109 segments = append(segments, coalesceNode(castToVarchar(arg), strConstNode("")))
110 case 'I':
111 segments = append(segments, funcCallNode("quote_ident", arg))
112 case 'L':
113 // quote_nullable matches PG %L exactly: NULL -> unquoted keyword NULL.
114 segments = append(segments, funcCallNode("quote_nullable", arg))
115 }
116 default:
117 return rewriteToError("format(): unsupported format specifier %" + string(spec) +
118 " (only %s, %I, %L and %% are supported)")
119 }
120 }
121 flushLit()
122 if len(segments) == 0 {

Callers 1

replaceCompatFuncNodeMethod · 0.95

Calls 7

extractStringConstantFunction · 0.85
funcCallNodeFunction · 0.85
strConstNodeFunction · 0.85
coalesceNodeFunction · 0.85
castToVarcharFunction · 0.85
concatNodesFunction · 0.85
StringMethod · 0.45

Tested by

no test coverage detected