@@ -92,12 +92,45 @@ func explainLiteral(sb *strings.Builder, n *ast.Literal, indent string, depth in
9292func explainBinaryExpr (sb * strings.Builder , n * ast.BinaryExpr , indent string , depth int ) {
9393 // Convert operator to function name
9494 fnName := OperatorToFunction (n .Op )
95+
96+ // For || (concat) operator, flatten chained concatenations
97+ if n .Op == "||" {
98+ operands := collectConcatOperands (n )
99+ fmt .Fprintf (sb , "%sFunction %s (children %d)\n " , indent , fnName , 1 )
100+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (operands ))
101+ for _ , op := range operands {
102+ Node (sb , op , depth + 2 )
103+ }
104+ return
105+ }
106+
95107 fmt .Fprintf (sb , "%sFunction %s (children %d)\n " , indent , fnName , 1 )
96108 fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
97109 Node (sb , n .Left , depth + 2 )
98110 Node (sb , n .Right , depth + 2 )
99111}
100112
113+ // collectConcatOperands flattens chained || (concat) operations into a list of operands
114+ func collectConcatOperands (n * ast.BinaryExpr ) []ast.Expression {
115+ var operands []ast.Expression
116+
117+ // Recursively collect from left side if it's also a concat
118+ if left , ok := n .Left .(* ast.BinaryExpr ); ok && left .Op == "||" {
119+ operands = append (operands , collectConcatOperands (left )... )
120+ } else {
121+ operands = append (operands , n .Left )
122+ }
123+
124+ // Recursively collect from right side if it's also a concat
125+ if right , ok := n .Right .(* ast.BinaryExpr ); ok && right .Op == "||" {
126+ operands = append (operands , collectConcatOperands (right )... )
127+ } else {
128+ operands = append (operands , n .Right )
129+ }
130+
131+ return operands
132+ }
133+
101134func explainUnaryExpr (sb * strings.Builder , n * ast.UnaryExpr , indent string , depth int ) {
102135 fnName := UnaryOperatorToFunction (n .Op )
103136 fmt .Fprintf (sb , "%sFunction %s (children %d)\n " , indent , fnName , 1 )
@@ -142,10 +175,20 @@ func explainAliasedExpr(sb *strings.Builder, n *ast.AliasedExpr, depth int) {
142175 case * ast.BinaryExpr :
143176 // Binary expressions become functions with alias
144177 fnName := OperatorToFunction (e .Op )
145- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
146- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
147- Node (sb , e .Left , depth + 2 )
148- Node (sb , e .Right , depth + 2 )
178+ // For || (concat) operator, flatten chained concatenations
179+ if e .Op == "||" {
180+ operands := collectConcatOperands (e )
181+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
182+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (operands ))
183+ for _ , op := range operands {
184+ Node (sb , op , depth + 2 )
185+ }
186+ } else {
187+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Alias , 1 )
188+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
189+ Node (sb , e .Left , depth + 2 )
190+ Node (sb , e .Right , depth + 2 )
191+ }
149192 case * ast.UnaryExpr :
150193 // Unary expressions become functions with alias
151194 fnName := UnaryOperatorToFunction (e .Op )
@@ -185,10 +228,20 @@ func explainWithElement(sb *strings.Builder, n *ast.WithElement, indent string,
185228 case * ast.BinaryExpr :
186229 // Binary expressions become functions
187230 fnName := OperatorToFunction (e .Op )
188- fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
189- fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
190- Node (sb , e .Left , depth + 2 )
191- Node (sb , e .Right , depth + 2 )
231+ // For || (concat) operator, flatten chained concatenations
232+ if e .Op == "||" {
233+ operands := collectConcatOperands (e )
234+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
235+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , len (operands ))
236+ for _ , op := range operands {
237+ Node (sb , op , depth + 2 )
238+ }
239+ } else {
240+ fmt .Fprintf (sb , "%sFunction %s (alias %s) (children %d)\n " , indent , fnName , n .Name , 1 )
241+ fmt .Fprintf (sb , "%s ExpressionList (children %d)\n " , indent , 2 )
242+ Node (sb , e .Left , depth + 2 )
243+ Node (sb , e .Right , depth + 2 )
244+ }
192245 case * ast.Subquery :
193246 fmt .Fprintf (sb , "%sSubquery (alias %s) (children %d)\n " , indent , n .Name , 1 )
194247 Node (sb , e .Query , depth + 1 )
0 commit comments