Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,9 +559,11 @@ const (

// ExplainQuery represents an EXPLAIN statement.
type ExplainQuery struct {
Position token.Position `json:"-"`
ExplainType ExplainType `json:"explain_type"`
Statement Statement `json:"statement"`
Position token.Position `json:"-"`
ExplainType ExplainType `json:"explain_type"`
Statement Statement `json:"statement"`
HasSettings bool `json:"has_settings,omitempty"`
ExplicitType bool `json:"explicit_type,omitempty"` // true if type was explicitly specified
}

func (e *ExplainQuery) Pos() token.Position { return e.Position }
Expand Down
22 changes: 18 additions & 4 deletions internal/explain/statements.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,22 +384,36 @@ func explainSystemQuery(sb *strings.Builder, indent string) {
}

func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string, depth int) {
// Determine the type string - only show if explicitly specified
typeStr := ""
if n.ExplicitType {
typeStr = " " + string(n.ExplainType)
}

// EXPLAIN CURRENT TRANSACTION has no children
if n.ExplainType == ast.ExplainCurrentTransaction {
// At top level (depth 0), ClickHouse outputs "Explain EXPLAIN <TYPE>"
if depth == 0 {
fmt.Fprintf(sb, "%sExplain EXPLAIN %s\n", indent, n.ExplainType)
fmt.Fprintf(sb, "%sExplain EXPLAIN%s\n", indent, typeStr)
} else {
fmt.Fprintf(sb, "%sExplain %s\n", indent, n.ExplainType)
fmt.Fprintf(sb, "%sExplain%s\n", indent, typeStr)
}
return
}
// Count children: settings (if present) + statement
children := 1
if n.HasSettings {
children++
}
// At top level (depth 0), ClickHouse outputs "Explain EXPLAIN <TYPE>"
// Nested in subqueries, it outputs "Explain <TYPE>"
if depth == 0 {
fmt.Fprintf(sb, "%sExplain EXPLAIN %s (children %d)\n", indent, n.ExplainType, 1)
fmt.Fprintf(sb, "%sExplain EXPLAIN%s (children %d)\n", indent, typeStr, children)
} else {
fmt.Fprintf(sb, "%sExplain %s (children %d)\n", indent, n.ExplainType, 1)
fmt.Fprintf(sb, "%sExplain%s (children %d)\n", indent, typeStr, children)
}
if n.HasSettings {
fmt.Fprintf(sb, "%s Set\n", indent)
}
Node(sb, n.Statement, depth+1)
}
Expand Down
7 changes: 7 additions & 0 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2895,18 +2895,23 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
switch strings.ToUpper(p.current.Value) {
case "AST":
explain.ExplainType = ast.ExplainAST
explain.ExplicitType = true
p.nextToken()
case "SYNTAX":
explain.ExplainType = ast.ExplainSyntax
explain.ExplicitType = true
p.nextToken()
case "PLAN":
explain.ExplainType = ast.ExplainPlan
explain.ExplicitType = true
p.nextToken()
case "PIPELINE":
explain.ExplainType = ast.ExplainPipeline
explain.ExplicitType = true
p.nextToken()
case "ESTIMATE":
explain.ExplainType = ast.ExplainEstimate
explain.ExplicitType = true
p.nextToken()
case "CURRENT":
// EXPLAIN CURRENT TRANSACTION
Expand All @@ -2915,6 +2920,7 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
p.nextToken()
}
explain.ExplainType = ast.ExplainCurrentTransaction
explain.ExplicitType = true
return explain // No statement follows CURRENT TRANSACTION
default:
explain.ExplainType = ast.ExplainPlan
Expand All @@ -2926,6 +2932,7 @@ func (p *Parser) parseExplain() *ast.ExplainQuery {
// Options can be identifiers or keywords like OPTIMIZE followed by =
for p.peekIs(token.EQ) && !p.currentIs(token.SELECT) && !p.currentIs(token.WITH) {
// This is an option (name = value)
explain.HasSettings = true
p.nextToken() // skip option name
p.nextToken() // skip =
p.parseExpression(LOWEST) // skip value
Expand Down
2 changes: 1 addition & 1 deletion parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func TestParser(t *testing.T) {
if len(metadata.ExplainTodo) == 0 {
metadata.ExplainTodo = nil
}
updatedBytes, err := json.Marshal(metadata)
updatedBytes, err := json.MarshalIndent(metadata, "", " ")
if err != nil {
t.Errorf("Failed to marshal updated metadata: %v", err)
} else if err := os.WriteFile(metadataPath, append(updatedBytes, '\n'), 0644); err != nil {
Expand Down
6 changes: 1 addition & 5 deletions parser/testdata/01508_explain_header/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt2": true
}
}
{}
Original file line number Diff line number Diff line change
@@ -1,12 +1 @@
{
"explain_todo": {
"stmt15": true,
"stmt16": true,
"stmt18": true,
"stmt19": true,
"stmt4": true,
"stmt5": true,
"stmt7": true,
"stmt8": true
}
}
{"explain_todo":{"stmt16":true,"stmt19":true,"stmt5":true,"stmt8":true}}
18 changes: 1 addition & 17 deletions parser/testdata/01576_alias_column_rewrite/metadata.json
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
{
"explain_todo": {
"stmt22": true,
"stmt23": true,
"stmt3": true,
"stmt32": true,
"stmt33": true,
"stmt34": true,
"stmt36": true,
"stmt37": true,
"stmt38": true,
"stmt4": true,
"stmt42": true,
"stmt5": true,
"stmt51": true
}
}
{"explain_todo":{"stmt22":true,"stmt23":true,"stmt3":true,"stmt4":true,"stmt42":true,"stmt5":true,"stmt51":true}}
9 changes: 1 addition & 8 deletions parser/testdata/01763_filter_push_down_bugs/metadata.json
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
{
"explain_todo": {
"stmt11": true,
"stmt23": true,
"stmt24": true,
"stmt5": true
}
}
{"explain_todo":{"stmt11":true,"stmt5":true}}
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
{
"explain_todo": {
"stmt2": true,
"stmt3": true
}
}
{}
Original file line number Diff line number Diff line change
@@ -1,20 +1 @@
{
"explain_todo": {
"stmt10": true,
"stmt11": true,
"stmt12": true,
"stmt14": true,
"stmt15": true,
"stmt16": true,
"stmt17": true,
"stmt18": true,
"stmt19": true,
"stmt20": true,
"stmt21": true,
"stmt5": true,
"stmt6": true,
"stmt7": true,
"stmt8": true,
"stmt9": true
}
}
{"explain_todo":{"stmt11":true,"stmt12":true,"stmt16":true,"stmt17":true,"stmt20":true,"stmt21":true,"stmt7":true,"stmt8":true}}
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
{
"explain_todo": {
"stmt11": true,
"stmt12": true,
"stmt13": true,
"stmt14": true
}
}
{}
45 changes: 1 addition & 44 deletions parser/testdata/02154_bit_slice_for_fixedstring/metadata.json
Original file line number Diff line number Diff line change
@@ -1,44 +1 @@
{
"explain_todo": {
"stmt100": true,
"stmt101": true,
"stmt102": true,
"stmt103": true,
"stmt104": true,
"stmt105": true,
"stmt109": true,
"stmt110": true,
"stmt111": true,
"stmt124": true,
"stmt126": true,
"stmt127": true,
"stmt72": true,
"stmt73": true,
"stmt74": true,
"stmt75": true,
"stmt76": true,
"stmt77": true,
"stmt78": true,
"stmt79": true,
"stmt80": true,
"stmt81": true,
"stmt82": true,
"stmt83": true,
"stmt84": true,
"stmt85": true,
"stmt86": true,
"stmt87": true,
"stmt88": true,
"stmt89": true,
"stmt90": true,
"stmt91": true,
"stmt92": true,
"stmt93": true,
"stmt94": true,
"stmt95": true,
"stmt96": true,
"stmt97": true,
"stmt98": true,
"stmt99": true
}
}
{}
43 changes: 1 addition & 42 deletions parser/testdata/02154_bit_slice_for_string/metadata.json
Original file line number Diff line number Diff line change
@@ -1,42 +1 @@
{
"explain_todo": {
"stmt100": true,
"stmt101": true,
"stmt102": true,
"stmt103": true,
"stmt104": true,
"stmt105": true,
"stmt109": true,
"stmt110": true,
"stmt111": true,
"stmt124": true,
"stmt126": true,
"stmt127": true,
"stmt74": true,
"stmt75": true,
"stmt76": true,
"stmt77": true,
"stmt78": true,
"stmt79": true,
"stmt80": true,
"stmt81": true,
"stmt82": true,
"stmt83": true,
"stmt84": true,
"stmt85": true,
"stmt86": true,
"stmt87": true,
"stmt88": true,
"stmt89": true,
"stmt90": true,
"stmt91": true,
"stmt92": true,
"stmt93": true,
"stmt94": true,
"stmt95": true,
"stmt96": true,
"stmt97": true,
"stmt98": true,
"stmt99": true
}
}
{}
6 changes: 1 addition & 5 deletions parser/testdata/02227_union_match_by_name/metadata.json
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt2": true
}
}
{}
9 changes: 1 addition & 8 deletions parser/testdata/02353_explain_ast_optimize/metadata.json
Original file line number Diff line number Diff line change
@@ -1,8 +1 @@
{
"explain_todo": {
"stmt1": true,
"stmt2": true,
"stmt3": true,
"stmt4": true
}
}
{}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt8": true
}
}
{}
19 changes: 1 addition & 18 deletions parser/testdata/02354_vector_search_queries/metadata.json
Original file line number Diff line number Diff line change
@@ -1,18 +1 @@
{
"explain_todo": {
"stmt12": true,
"stmt19": true,
"stmt55": true,
"stmt57": true,
"stmt59": true,
"stmt6": true,
"stmt61": true,
"stmt63": true,
"stmt65": true,
"stmt67": true,
"stmt69": true,
"stmt71": true,
"stmt73": true,
"stmt90": true
}
}
{"explain_todo":{"stmt90":true}}
8 changes: 1 addition & 7 deletions parser/testdata/02354_vector_search_subquery/metadata.json
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
{
"explain_todo": {
"stmt5": true,
"stmt6": true,
"stmt7": true
}
}
{}
18 changes: 1 addition & 17 deletions parser/testdata/02497_if_transform_strings_to_enum/metadata.json
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
{
"explain_todo": {
"stmt11": true,
"stmt14": true,
"stmt17": true,
"stmt20": true,
"stmt23": true,
"stmt26": true,
"stmt29": true,
"stmt31": true,
"stmt32": true,
"stmt36": true,
"stmt39": true,
"stmt5": true,
"stmt8": true
}
}
{"explain_todo":{"stmt11":true,"stmt14":true,"stmt17":true,"stmt20":true,"stmt23":true,"stmt26":true,"stmt29":true,"stmt32":true,"stmt36":true,"stmt39":true,"stmt5":true,"stmt8":true}}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt2": true
}
}
{}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt11": true
}
}
{}
Original file line number Diff line number Diff line change
@@ -1,9 +1 @@
{
"explain_todo": {
"stmt4": true,
"stmt5": true,
"stmt6": true,
"stmt7": true,
"stmt8": true
}
}
{"explain_todo":{"stmt4":true,"stmt5":true,"stmt8":true}}
7 changes: 1 addition & 6 deletions parser/testdata/02707_skip_index_with_in/metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
{
"explain_todo": {
"stmt4": true,
"stmt5": true
}
}
{"explain_todo":{"stmt4":true}}
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
{
"explain_todo": {
"stmt7": true
}
}
{}
Loading