Skip to content

Commit af21faa

Browse files
committed
Add WITH clause element explain output support
- Add explainWithElement function to handle WITH clause expressions - Add explainFunctionCallWithAlias helper for function calls with aliases - Update select.go to output WITH clause ExpressionList - Update explain.go to handle *ast.WithElement nodes Test count: 5505 -> 5517 (+12 tests)
1 parent e65fcd7 commit af21faa

4 files changed

Lines changed: 44 additions & 2 deletions

File tree

internal/explain/explain.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
6363
explainSubquery(sb, n, indent, depth)
6464
case *ast.AliasedExpr:
6565
explainAliasedExpr(sb, n, depth)
66+
case *ast.WithElement:
67+
explainWithElement(sb, n, indent, depth)
6668
case *ast.Asterisk:
6769
explainAsterisk(sb, n, indent)
6870

internal/explain/expressions.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,28 @@ func explainAsterisk(sb *strings.Builder, n *ast.Asterisk, indent string) {
149149
fmt.Fprintf(sb, "%sAsterisk\n", indent)
150150
}
151151
}
152+
153+
func explainWithElement(sb *strings.Builder, n *ast.WithElement, indent string, depth int) {
154+
// For WITH elements, we need to show the underlying expression with the name as alias
155+
switch e := n.Query.(type) {
156+
case *ast.Literal:
157+
fmt.Fprintf(sb, "%sLiteral %s (alias %s)\n", indent, FormatLiteral(e), n.Name)
158+
case *ast.Identifier:
159+
fmt.Fprintf(sb, "%sIdentifier %s (alias %s)\n", indent, e.Name(), n.Name)
160+
case *ast.FunctionCall:
161+
explainFunctionCallWithAlias(sb, e, n.Name, indent, depth)
162+
case *ast.BinaryExpr:
163+
// Binary expressions become functions
164+
fnName := OperatorToFunction(e.Op)
165+
fmt.Fprintf(sb, "%sFunction %s (alias %s) (children %d)\n", indent, fnName, n.Name, 1)
166+
fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, 2)
167+
Node(sb, e.Left, depth+2)
168+
Node(sb, e.Right, depth+2)
169+
case *ast.Subquery:
170+
fmt.Fprintf(sb, "%sSubquery (alias %s) (children %d)\n", indent, n.Name, 1)
171+
Node(sb, e.Query, depth+1)
172+
default:
173+
// For other types, just output the expression (alias may be lost)
174+
Node(sb, n.Query, depth)
175+
}
176+
}

internal/explain/functions.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ import (
88
)
99

1010
func explainFunctionCall(sb *strings.Builder, n *ast.FunctionCall, indent string, depth int) {
11+
explainFunctionCallWithAlias(sb, n, n.Alias, indent, depth)
12+
}
13+
14+
func explainFunctionCallWithAlias(sb *strings.Builder, n *ast.FunctionCall, alias string, indent string, depth int) {
1115
children := 1 // arguments ExpressionList
1216
if len(n.Parameters) > 0 {
1317
children++ // parameters ExpressionList
1418
}
1519
// Normalize function name
1620
fnName := NormalizeFunctionName(n.Name)
17-
if n.Alias != "" {
18-
fmt.Fprintf(sb, "%sFunction %s (alias %s) (children %d)\n", indent, fnName, n.Alias, children)
21+
if alias != "" {
22+
fmt.Fprintf(sb, "%sFunction %s (alias %s) (children %d)\n", indent, fnName, alias, children)
1923
} else {
2024
fmt.Fprintf(sb, "%sFunction %s (children %d)\n", indent, fnName, children)
2125
}

internal/explain/select.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ func explainSelectWithUnionQuery(sb *strings.Builder, n *ast.SelectWithUnionQuer
2727
func explainSelectQuery(sb *strings.Builder, n *ast.SelectQuery, indent string, depth int) {
2828
children := countSelectQueryChildren(n)
2929
fmt.Fprintf(sb, "%sSelectQuery (children %d)\n", indent, children)
30+
// WITH clause (ExpressionList) - output before columns
31+
if len(n.With) > 0 {
32+
fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.With))
33+
for _, w := range n.With {
34+
Node(sb, w, depth+2)
35+
}
36+
}
3037
// Columns (ExpressionList)
3138
fmt.Fprintf(sb, "%s ExpressionList (children %d)\n", indent, len(n.Columns))
3239
for _, col := range n.Columns {
@@ -95,6 +102,10 @@ func countSelectUnionChildren(n *ast.SelectWithUnionQuery) int {
95102

96103
func countSelectQueryChildren(n *ast.SelectQuery) int {
97104
count := 1 // columns ExpressionList
105+
// WITH clause
106+
if len(n.With) > 0 {
107+
count++
108+
}
98109
// FROM and ARRAY JOIN together count as one child (TablesInSelectQuery)
99110
if n.From != nil || n.ArrayJoin != nil {
100111
count++

0 commit comments

Comments
 (0)