Skip to content

Commit 734ba84

Browse files
kyleconroyclaude
andcommitted
Handle SETTINGS/COMMENT order in CREATE TABLE explain output
When COMMENT comes before SETTINGS in a CREATE TABLE statement, SETTINGS should be output at the CreateQuery level (outside Storage definition). When SETTINGS comes before COMMENT, it stays inside Storage definition. Added SettingsBeforeComment field to track the order in the AST. Fixes: - 03234_enable_secure_identifiers stmt11, stmt14 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent cbc4d68 commit 734ba84

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

ast/ast.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ type CreateQuery struct {
291291
PrimaryKey []Expression `json:"primary_key,omitempty"`
292292
SampleBy Expression `json:"sample_by,omitempty"`
293293
TTL *TTLClause `json:"ttl,omitempty"`
294-
Settings []*SettingExpr `json:"settings,omitempty"`
294+
Settings []*SettingExpr `json:"settings,omitempty"`
295+
SettingsBeforeComment bool `json:"settings_before_comment,omitempty"` // True if SETTINGS comes before COMMENT
295296
AsSelect Statement `json:"as_select,omitempty"`
296297
AsTableFunction Expression `json:"as_table_function,omitempty"` // AS table_function(...) in CREATE TABLE
297298
CloneAs string `json:"clone_as,omitempty"` // CLONE AS source_table in CREATE TABLE

internal/explain/statements.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,17 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
215215
if len(n.Columns) > 0 || len(n.Indexes) > 0 || len(n.Projections) > 0 || len(n.Constraints) > 0 {
216216
children++
217217
}
218-
hasStorageChild := n.Engine != nil || len(n.OrderBy) > 0 || len(n.PrimaryKey) > 0 || n.PartitionBy != nil || n.SampleBy != nil || n.TTL != nil || len(n.Settings) > 0 || len(n.ColumnsPrimaryKey) > 0 || hasColumnPrimaryKey
218+
// When SETTINGS comes after COMMENT (not before), Settings goes outside Storage definition
219+
// SettingsBeforeComment=true means SETTINGS came first, so it stays in Storage
220+
settingsInStorage := len(n.Settings) > 0 && (n.Comment == "" || n.SettingsBeforeComment)
221+
hasStorageChild := n.Engine != nil || len(n.OrderBy) > 0 || len(n.PrimaryKey) > 0 || n.PartitionBy != nil || n.SampleBy != nil || n.TTL != nil || settingsInStorage || len(n.ColumnsPrimaryKey) > 0 || hasColumnPrimaryKey
219222
if hasStorageChild {
220223
children++
221224
}
225+
// When SETTINGS comes after COMMENT, Settings is a separate child of CreateQuery
226+
if n.Comment != "" && len(n.Settings) > 0 && !n.SettingsBeforeComment {
227+
children++
228+
}
222229
// For materialized views with TO clause but no storage, count ViewTargets as a child
223230
if n.Materialized && n.To != "" && !hasStorageChild {
224231
children++ // ViewTargets
@@ -347,7 +354,7 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
347354
inCreateQueryContext = false
348355
}
349356
}
350-
hasStorage := n.Engine != nil || len(n.OrderBy) > 0 || len(n.PrimaryKey) > 0 || n.PartitionBy != nil || n.SampleBy != nil || n.TTL != nil || len(n.Settings) > 0 || len(n.ColumnsPrimaryKey) > 0 || hasColumnPrimaryKey
357+
hasStorage := n.Engine != nil || len(n.OrderBy) > 0 || len(n.PrimaryKey) > 0 || n.PartitionBy != nil || n.SampleBy != nil || n.TTL != nil || settingsInStorage || len(n.ColumnsPrimaryKey) > 0 || hasColumnPrimaryKey
351358
if hasStorage {
352359
storageChildren := 0
353360
if n.Engine != nil {
@@ -369,7 +376,7 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
369376
if n.TTL != nil {
370377
storageChildren++
371378
}
372-
if len(n.Settings) > 0 {
379+
if settingsInStorage {
373380
storageChildren++
374381
}
375382
// For materialized views, wrap storage definition in ViewTargets
@@ -514,7 +521,7 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
514521
}
515522
}
516523
}
517-
if len(n.Settings) > 0 {
524+
if settingsInStorage {
518525
fmt.Fprintf(sb, "%s Set\n", storageIndent)
519526
}
520527
} else if n.Materialized && n.To != "" {
@@ -547,6 +554,10 @@ func explainCreateQuery(sb *strings.Builder, n *ast.CreateQuery, indent string,
547554
if n.Comment != "" {
548555
fmt.Fprintf(sb, "%s Literal \\'%s\\'\n", indent, escapeStringLiteral(n.Comment))
549556
}
557+
// Output Settings at CreateQuery level when SETTINGS comes after COMMENT
558+
if n.Comment != "" && len(n.Settings) > 0 && !n.SettingsBeforeComment {
559+
fmt.Fprintf(sb, "%s Set\n", indent)
560+
}
550561
}
551562

552563
func explainDropQuery(sb *strings.Builder, n *ast.DropQuery, indent string, depth int) {

parser/parser.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,6 +2687,10 @@ func (p *Parser) parseTableOptions(create *ast.CreateQuery) {
26872687
}
26882688
}
26892689
case p.currentIs(token.SETTINGS):
2690+
// Track if SETTINGS comes before COMMENT
2691+
if create.Comment == "" && len(create.Settings) == 0 {
2692+
create.SettingsBeforeComment = true
2693+
}
26902694
p.nextToken()
26912695
create.Settings = p.parseSettingsList()
26922696
case p.currentIs(token.COMMENT):
@@ -2695,6 +2699,10 @@ func (p *Parser) parseTableOptions(create *ast.CreateQuery) {
26952699
create.Comment = p.current.Value
26962700
p.nextToken()
26972701
}
2702+
// If we see COMMENT but Settings wasn't set yet, clear the flag
2703+
if len(create.Settings) == 0 {
2704+
create.SettingsBeforeComment = false
2705+
}
26982706
default:
26992707
return
27002708
}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt11": true,
4-
"stmt14": true
5-
}
6-
}
1+
{}

0 commit comments

Comments
 (0)