Skip to content

Commit d875f47

Browse files
authored
Add EXPLAIN settings and explicit type support (#67)
1 parent 761ca2a commit d875f47

File tree

62 files changed

+89
-631
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+89
-631
lines changed

ast/ast.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,11 @@ const (
559559

560560
// ExplainQuery represents an EXPLAIN statement.
561561
type ExplainQuery struct {
562-
Position token.Position `json:"-"`
563-
ExplainType ExplainType `json:"explain_type"`
564-
Statement Statement `json:"statement"`
562+
Position token.Position `json:"-"`
563+
ExplainType ExplainType `json:"explain_type"`
564+
Statement Statement `json:"statement"`
565+
HasSettings bool `json:"has_settings,omitempty"`
566+
ExplicitType bool `json:"explicit_type,omitempty"` // true if type was explicitly specified
565567
}
566568

567569
func (e *ExplainQuery) Pos() token.Position { return e.Position }

internal/explain/statements.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,22 +384,36 @@ func explainSystemQuery(sb *strings.Builder, indent string) {
384384
}
385385

386386
func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string, depth int) {
387+
// Determine the type string - only show if explicitly specified
388+
typeStr := ""
389+
if n.ExplicitType {
390+
typeStr = " " + string(n.ExplainType)
391+
}
392+
387393
// EXPLAIN CURRENT TRANSACTION has no children
388394
if n.ExplainType == ast.ExplainCurrentTransaction {
389395
// At top level (depth 0), ClickHouse outputs "Explain EXPLAIN <TYPE>"
390396
if depth == 0 {
391-
fmt.Fprintf(sb, "%sExplain EXPLAIN %s\n", indent, n.ExplainType)
397+
fmt.Fprintf(sb, "%sExplain EXPLAIN%s\n", indent, typeStr)
392398
} else {
393-
fmt.Fprintf(sb, "%sExplain %s\n", indent, n.ExplainType)
399+
fmt.Fprintf(sb, "%sExplain%s\n", indent, typeStr)
394400
}
395401
return
396402
}
403+
// Count children: settings (if present) + statement
404+
children := 1
405+
if n.HasSettings {
406+
children++
407+
}
397408
// At top level (depth 0), ClickHouse outputs "Explain EXPLAIN <TYPE>"
398409
// Nested in subqueries, it outputs "Explain <TYPE>"
399410
if depth == 0 {
400-
fmt.Fprintf(sb, "%sExplain EXPLAIN %s (children %d)\n", indent, n.ExplainType, 1)
411+
fmt.Fprintf(sb, "%sExplain EXPLAIN%s (children %d)\n", indent, typeStr, children)
401412
} else {
402-
fmt.Fprintf(sb, "%sExplain %s (children %d)\n", indent, n.ExplainType, 1)
413+
fmt.Fprintf(sb, "%sExplain%s (children %d)\n", indent, typeStr, children)
414+
}
415+
if n.HasSettings {
416+
fmt.Fprintf(sb, "%s Set\n", indent)
403417
}
404418
Node(sb, n.Statement, depth+1)
405419
}

parser/parser.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,18 +2895,23 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
28952895
switch strings.ToUpper(p.current.Value) {
28962896
case "AST":
28972897
explain.ExplainType = ast.ExplainAST
2898+
explain.ExplicitType = true
28982899
p.nextToken()
28992900
case "SYNTAX":
29002901
explain.ExplainType = ast.ExplainSyntax
2902+
explain.ExplicitType = true
29012903
p.nextToken()
29022904
case "PLAN":
29032905
explain.ExplainType = ast.ExplainPlan
2906+
explain.ExplicitType = true
29042907
p.nextToken()
29052908
case "PIPELINE":
29062909
explain.ExplainType = ast.ExplainPipeline
2910+
explain.ExplicitType = true
29072911
p.nextToken()
29082912
case "ESTIMATE":
29092913
explain.ExplainType = ast.ExplainEstimate
2914+
explain.ExplicitType = true
29102915
p.nextToken()
29112916
case "CURRENT":
29122917
// EXPLAIN CURRENT TRANSACTION
@@ -2915,6 +2920,7 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
29152920
p.nextToken()
29162921
}
29172922
explain.ExplainType = ast.ExplainCurrentTransaction
2923+
explain.ExplicitType = true
29182924
return explain // No statement follows CURRENT TRANSACTION
29192925
default:
29202926
explain.ExplainType = ast.ExplainPlan
@@ -2926,6 +2932,7 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
29262932
// Options can be identifiers or keywords like OPTIMIZE followed by =
29272933
for p.peekIs(token.EQ) && !p.currentIs(token.SELECT) && !p.currentIs(token.WITH) {
29282934
// This is an option (name = value)
2935+
explain.HasSettings = true
29292936
p.nextToken() // skip option name
29302937
p.nextToken() // skip =
29312938
p.parseExpression(LOWEST) // skip value

parser/parser_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ func TestParser(t *testing.T) {
245245
if len(metadata.ExplainTodo) == 0 {
246246
metadata.ExplainTodo = nil
247247
}
248-
updatedBytes, err := json.Marshal(metadata)
248+
updatedBytes, err := json.MarshalIndent(metadata, "", " ")
249249
if err != nil {
250250
t.Errorf("Failed to marshal updated metadata: %v", err)
251251
} else if err := os.WriteFile(metadataPath, append(updatedBytes, '\n'), 0644); err != nil {
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt2": true
4-
}
5-
}
1+
{}
Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt15": true,
4-
"stmt16": true,
5-
"stmt18": true,
6-
"stmt19": true,
7-
"stmt4": true,
8-
"stmt5": true,
9-
"stmt7": true,
10-
"stmt8": true
11-
}
12-
}
1+
{"explain_todo":{"stmt16":true,"stmt19":true,"stmt5":true,"stmt8":true}}
Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt22": true,
4-
"stmt23": true,
5-
"stmt3": true,
6-
"stmt32": true,
7-
"stmt33": true,
8-
"stmt34": true,
9-
"stmt36": true,
10-
"stmt37": true,
11-
"stmt38": true,
12-
"stmt4": true,
13-
"stmt42": true,
14-
"stmt5": true,
15-
"stmt51": true
16-
}
17-
}
1+
{"explain_todo":{"stmt22":true,"stmt23":true,"stmt3":true,"stmt4":true,"stmt42":true,"stmt5":true,"stmt51":true}}
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt11": true,
4-
"stmt23": true,
5-
"stmt24": true,
6-
"stmt5": true
7-
}
8-
}
1+
{"explain_todo":{"stmt11":true,"stmt5":true}}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt2": true,
4-
"stmt3": true
5-
}
6-
}
1+
{}
Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt10": true,
4-
"stmt11": true,
5-
"stmt12": true,
6-
"stmt14": true,
7-
"stmt15": true,
8-
"stmt16": true,
9-
"stmt17": true,
10-
"stmt18": true,
11-
"stmt19": true,
12-
"stmt20": true,
13-
"stmt21": true,
14-
"stmt5": true,
15-
"stmt6": true,
16-
"stmt7": true,
17-
"stmt8": true,
18-
"stmt9": true
19-
}
20-
}
1+
{"explain_todo":{"stmt11":true,"stmt12":true,"stmt16":true,"stmt17":true,"stmt20":true,"stmt21":true,"stmt7":true,"stmt8":true}}

0 commit comments

Comments
 (0)