Skip to content

Commit 548d700

Browse files
committed
Fix EXPLAIN output for FORMAT and SETTINGS clauses
Handle FORMAT and SETTINGS ordering in EXPLAIN output: - Extract FORMAT clause to be a child of Explain node - Extract SETTINGS after FORMAT (SettingsAfterFormat flag) to Explain level - Keep SETTINGS before FORMAT within the SelectQuery Fixed tests: - 02989_join_using_parent_scope (stmt32) - 02798_explain_settings_not_applied_bug (stmt8)
1 parent 75f36e8 commit 548d700

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

internal/explain/statements.go

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -806,25 +806,44 @@ func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string
806806
}
807807

808808
// Check if inner statement has FORMAT clause - this should be output as child of Explain
809+
// Also check for SETTINGS after FORMAT (these are at the EXPLAIN level, not part of the SELECT)
809810
var format *ast.Identifier
811+
var hasSettingsAfterFormat bool
812+
var savedSettings []*ast.SettingExpr
810813
if swu, ok := n.Statement.(*ast.SelectWithUnionQuery); ok {
814+
// Check for union-level settings after format
815+
if swu.SettingsAfterFormat && len(swu.Settings) > 0 {
816+
hasSettingsAfterFormat = true
817+
savedSettings = swu.Settings
818+
swu.Settings = nil
819+
defer func() { swu.Settings = savedSettings }()
820+
}
811821
for _, sel := range swu.Selects {
812-
if sq, ok := sel.(*ast.SelectQuery); ok && sq.Format != nil {
813-
format = sq.Format
814-
// Temporarily nil out the format so it's not output by SelectWithUnionQuery
815-
sq.Format = nil
816-
defer func() { sq.Format = format }()
822+
if sq, ok := sel.(*ast.SelectQuery); ok {
823+
if sq.Format != nil {
824+
format = sq.Format
825+
// Temporarily nil out the format so it's not output by SelectWithUnionQuery
826+
sq.Format = nil
827+
defer func() { sq.Format = format }()
828+
}
829+
// Check for settings after format in the SelectQuery
830+
if sq.SettingsAfterFormat && len(sq.Settings) > 0 && !hasSettingsAfterFormat {
831+
hasSettingsAfterFormat = true
832+
savedSettings = sq.Settings
833+
sq.Settings = nil
834+
defer func() { sq.Settings = savedSettings }()
835+
}
817836
break
818837
}
819838
}
820839
}
821840

822-
// Count children: settings (if present) + statement + format (if present)
841+
// Count children: statement + format (if present) + settings (if present)
823842
children := 1
824-
if n.HasSettings {
843+
if format != nil {
825844
children++
826845
}
827-
if format != nil {
846+
if n.HasSettings || hasSettingsAfterFormat {
828847
children++
829848
}
830849

@@ -835,13 +854,20 @@ func explainExplainQuery(sb *strings.Builder, n *ast.ExplainQuery, indent string
835854
} else {
836855
fmt.Fprintf(sb, "%sExplain%s (children %d)\n", indent, typeStr, children)
837856
}
857+
// EXPLAIN-level settings (like header = 0) come BEFORE the statement
838858
if n.HasSettings {
839859
fmt.Fprintf(sb, "%s Set\n", indent)
840860
}
861+
// Output the statement
841862
Node(sb, n.Statement, depth+1)
863+
// Format comes after statement
842864
if format != nil {
843865
fmt.Fprintf(sb, "%s Identifier %s\n", indent, format.Parts[len(format.Parts)-1])
844866
}
867+
// Settings after format (at the query level, e.g., FORMAT Null SETTINGS ...) come last
868+
if hasSettingsAfterFormat {
869+
fmt.Fprintf(sb, "%s Set\n", indent)
870+
}
845871
}
846872

847873
func explainShowQuery(sb *strings.Builder, n *ast.ShowQuery, indent string) {
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt8": true
4-
}
5-
}
1+
{}
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt32": true
4-
}
5-
}
1+
{}

0 commit comments

Comments
 (0)