Skip to content

Commit 3f729a2

Browse files
authored
Fix JSON path type accessor parsing and projection ORDER BY (#109)
1 parent cb711f7 commit 3f729a2

File tree

221 files changed

+1645
-1535
lines changed

Some content is hidden

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

221 files changed

+1645
-1535
lines changed

ast/ast.go

Lines changed: 90 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type SelectQuery struct {
6464
PreWhere Expression `json:"prewhere,omitempty"`
6565
Where Expression `json:"where,omitempty"`
6666
GroupBy []Expression `json:"group_by,omitempty"`
67+
GroupByAll bool `json:"group_by_all,omitempty"` // true if GROUP BY ALL was used
6768
GroupingSets bool `json:"grouping_sets,omitempty"` // true if GROUP BY uses GROUPING SETS
6869
WithRollup bool `json:"with_rollup,omitempty"`
6970
WithCube bool `json:"with_cube,omitempty"`
@@ -253,8 +254,9 @@ type CreateQuery struct {
253254
Table string `json:"table,omitempty"`
254255
View string `json:"view,omitempty"`
255256
Materialized bool `json:"materialized,omitempty"`
256-
To string `json:"to,omitempty"` // Target table for materialized views
257-
Populate bool `json:"populate,omitempty"` // POPULATE for materialized views
257+
ToDatabase string `json:"to_database,omitempty"` // Target database for materialized views
258+
To string `json:"to,omitempty"` // Target table for materialized views
259+
Populate bool `json:"populate,omitempty"` // POPULATE for materialized views
258260
Columns []*ColumnDeclaration `json:"columns,omitempty"`
259261
Indexes []*IndexDefinition `json:"indexes,omitempty"`
260262
Projections []*Projection `json:"projections,omitempty"`
@@ -497,6 +499,19 @@ func (d *DropQuery) Pos() token.Position { return d.Position }
497499
func (d *DropQuery) End() token.Position { return d.Position }
498500
func (d *DropQuery) statementNode() {}
499501

502+
// UndropQuery represents an UNDROP TABLE statement.
503+
type UndropQuery struct {
504+
Position token.Position `json:"-"`
505+
Database string `json:"database,omitempty"`
506+
Table string `json:"table"`
507+
OnCluster string `json:"on_cluster,omitempty"`
508+
UUID string `json:"uuid,omitempty"`
509+
}
510+
511+
func (u *UndropQuery) Pos() token.Position { return u.Position }
512+
func (u *UndropQuery) End() token.Position { return u.Position }
513+
func (u *UndropQuery) statementNode() {}
514+
500515
// AlterQuery represents an ALTER statement.
501516
type AlterQuery struct {
502517
Position token.Position `json:"-"`
@@ -529,6 +544,7 @@ type AlterCommand struct {
529544
ConstraintName string `json:"constraint_name,omitempty"`
530545
Partition Expression `json:"partition,omitempty"`
531546
FromTable string `json:"from_table,omitempty"`
547+
FromPath string `json:"from_path,omitempty"` // For FETCH PARTITION FROM
532548
TTL *TTLClause `json:"ttl,omitempty"`
533549
Settings []*SettingExpr `json:"settings,omitempty"`
534550
Where Expression `json:"where,omitempty"` // For DELETE WHERE
@@ -593,6 +609,8 @@ const (
593609
AlterDetachPartition AlterCommandType = "DETACH_PARTITION"
594610
AlterAttachPartition AlterCommandType = "ATTACH_PARTITION"
595611
AlterReplacePartition AlterCommandType = "REPLACE_PARTITION"
612+
AlterFetchPartition AlterCommandType = "FETCH_PARTITION"
613+
AlterMovePartition AlterCommandType = "MOVE_PARTITION"
596614
AlterFreezePartition AlterCommandType = "FREEZE_PARTITION"
597615
AlterFreeze AlterCommandType = "FREEZE"
598616
AlterDeleteWhere AlterCommandType = "DELETE_WHERE"
@@ -689,18 +707,24 @@ func (s *ShowQuery) statementNode() {}
689707
type ShowType string
690708

691709
const (
692-
ShowTables ShowType = "TABLES"
693-
ShowDatabases ShowType = "DATABASES"
694-
ShowProcesses ShowType = "PROCESSLIST"
695-
ShowCreate ShowType = "CREATE"
696-
ShowCreateDB ShowType = "CREATE_DATABASE"
697-
ShowCreateDictionary ShowType = "CREATE_DICTIONARY"
698-
ShowCreateView ShowType = "CREATE_VIEW"
699-
ShowCreateUser ShowType = "CREATE_USER"
700-
ShowColumns ShowType = "COLUMNS"
701-
ShowDictionaries ShowType = "DICTIONARIES"
702-
ShowFunctions ShowType = "FUNCTIONS"
703-
ShowSettings ShowType = "SETTINGS"
710+
ShowTables ShowType = "TABLES"
711+
ShowDatabases ShowType = "DATABASES"
712+
ShowProcesses ShowType = "PROCESSLIST"
713+
ShowCreate ShowType = "CREATE"
714+
ShowCreateDB ShowType = "CREATE_DATABASE"
715+
ShowCreateDictionary ShowType = "CREATE_DICTIONARY"
716+
ShowCreateView ShowType = "CREATE_VIEW"
717+
ShowCreateUser ShowType = "CREATE_USER"
718+
ShowCreateRole ShowType = "CREATE_ROLE"
719+
ShowCreatePolicy ShowType = "CREATE_POLICY"
720+
ShowCreateRowPolicy ShowType = "CREATE_ROW_POLICY"
721+
ShowCreateQuota ShowType = "CREATE_QUOTA"
722+
ShowCreateSettingsProfile ShowType = "CREATE_SETTINGS_PROFILE"
723+
ShowColumns ShowType = "COLUMNS"
724+
ShowDictionaries ShowType = "DICTIONARIES"
725+
ShowFunctions ShowType = "FUNCTIONS"
726+
ShowSettings ShowType = "SETTINGS"
727+
ShowGrants ShowType = "GRANTS"
704728
)
705729

706730
// ExplainQuery represents an EXPLAIN statement.
@@ -862,6 +886,7 @@ func (g *GrantQuery) statementNode() {}
862886
// ShowGrantsQuery represents a SHOW GRANTS statement.
863887
type ShowGrantsQuery struct {
864888
Position token.Position `json:"-"`
889+
Format string `json:"format,omitempty"`
865890
}
866891

867892
func (s *ShowGrantsQuery) Pos() token.Position { return s.Position }
@@ -881,12 +906,23 @@ func (s *ShowPrivilegesQuery) statementNode() {}
881906
type ShowCreateQuotaQuery struct {
882907
Position token.Position `json:"-"`
883908
Name string `json:"name,omitempty"`
909+
Format string `json:"format,omitempty"`
884910
}
885911

886912
func (s *ShowCreateQuotaQuery) Pos() token.Position { return s.Position }
887913
func (s *ShowCreateQuotaQuery) End() token.Position { return s.Position }
888914
func (s *ShowCreateQuotaQuery) statementNode() {}
889915

916+
// CreateQuotaQuery represents a CREATE QUOTA statement.
917+
type CreateQuotaQuery struct {
918+
Position token.Position `json:"-"`
919+
Name string `json:"name,omitempty"`
920+
}
921+
922+
func (c *CreateQuotaQuery) Pos() token.Position { return c.Position }
923+
func (c *CreateQuotaQuery) End() token.Position { return c.Position }
924+
func (c *CreateQuotaQuery) statementNode() {}
925+
890926
// CreateSettingsProfileQuery represents a CREATE SETTINGS PROFILE statement.
891927
type CreateSettingsProfileQuery struct {
892928
Position token.Position `json:"-"`
@@ -922,6 +958,7 @@ func (d *DropSettingsProfileQuery) statementNode() {}
922958
type ShowCreateSettingsProfileQuery struct {
923959
Position token.Position `json:"-"`
924960
Names []string `json:"names,omitempty"`
961+
Format string `json:"format,omitempty"`
925962
}
926963

927964
func (s *ShowCreateSettingsProfileQuery) Pos() token.Position { return s.Position }
@@ -951,6 +988,7 @@ func (d *DropRowPolicyQuery) statementNode() {}
951988
// ShowCreateRowPolicyQuery represents a SHOW CREATE ROW POLICY statement.
952989
type ShowCreateRowPolicyQuery struct {
953990
Position token.Position `json:"-"`
991+
Format string `json:"format,omitempty"`
954992
}
955993

956994
func (s *ShowCreateRowPolicyQuery) Pos() token.Position { return s.Position }
@@ -981,12 +1019,22 @@ func (d *DropRoleQuery) statementNode() {}
9811019
type ShowCreateRoleQuery struct {
9821020
Position token.Position `json:"-"`
9831021
RoleCount int `json:"role_count,omitempty"` // Number of roles specified
1022+
Format string `json:"format,omitempty"`
9841023
}
9851024

9861025
func (s *ShowCreateRoleQuery) Pos() token.Position { return s.Position }
9871026
func (s *ShowCreateRoleQuery) End() token.Position { return s.Position }
9881027
func (s *ShowCreateRoleQuery) statementNode() {}
9891028

1029+
// SetRoleQuery represents a SET DEFAULT ROLE statement.
1030+
type SetRoleQuery struct {
1031+
Position token.Position `json:"-"`
1032+
}
1033+
1034+
func (s *SetRoleQuery) Pos() token.Position { return s.Position }
1035+
func (s *SetRoleQuery) End() token.Position { return s.Position }
1036+
func (s *SetRoleQuery) statementNode() {}
1037+
9901038
// CreateResourceQuery represents a CREATE RESOURCE statement.
9911039
type CreateResourceQuery struct {
9921040
Position token.Position `json:"-"`
@@ -1143,11 +1191,12 @@ const (
11431191

11441192
// Asterisk represents a *.
11451193
type Asterisk struct {
1146-
Position token.Position `json:"-"`
1147-
Table string `json:"table,omitempty"` // for table.*
1148-
Except []string `json:"except,omitempty"` // for * EXCEPT (col1, col2)
1149-
Replace []*ReplaceExpr `json:"replace,omitempty"` // for * REPLACE (expr AS col)
1150-
Apply []string `json:"apply,omitempty"` // for * APPLY (func1) APPLY(func2)
1194+
Position token.Position `json:"-"`
1195+
Table string `json:"table,omitempty"` // for table.*
1196+
Except []string `json:"except,omitempty"` // for * EXCEPT (col1, col2) - deprecated, use Transformers
1197+
Replace []*ReplaceExpr `json:"replace,omitempty"` // for * REPLACE (expr AS col) - deprecated, use Transformers
1198+
Apply []string `json:"apply,omitempty"` // for * APPLY (func1) APPLY(func2) - deprecated, use Transformers
1199+
Transformers []*ColumnTransformer `json:"transformers,omitempty"` // ordered list of transformers
11511200
}
11521201

11531202
func (a *Asterisk) Pos() token.Position { return a.Position }
@@ -1164,15 +1213,28 @@ type ReplaceExpr struct {
11641213
func (r *ReplaceExpr) Pos() token.Position { return r.Position }
11651214
func (r *ReplaceExpr) End() token.Position { return r.Position }
11661215

1216+
// ColumnTransformer represents a single transformer (APPLY, EXCEPT, or REPLACE) in order.
1217+
type ColumnTransformer struct {
1218+
Position token.Position `json:"-"`
1219+
Type string `json:"type"` // "apply", "except", "replace"
1220+
Apply string `json:"apply,omitempty"` // function name for APPLY
1221+
ApplyLambda Expression `json:"apply_lambda,omitempty"` // lambda expression for APPLY x -> expr
1222+
Except []string `json:"except,omitempty"` // column names for EXCEPT
1223+
Replaces []*ReplaceExpr `json:"replaces,omitempty"` // replacement expressions for REPLACE
1224+
}
1225+
11671226
// ColumnsMatcher represents COLUMNS('pattern') or COLUMNS(col1, col2) expression.
11681227
// When Pattern is set, it's a regex matcher (ColumnsRegexpMatcher in explain).
11691228
// When Columns is set, it's a list matcher (ColumnsListMatcher in explain).
11701229
type ColumnsMatcher struct {
1171-
Position token.Position `json:"-"`
1172-
Pattern string `json:"pattern,omitempty"`
1173-
Columns []Expression `json:"columns,omitempty"` // For COLUMNS(id, name) syntax
1174-
Except []string `json:"except,omitempty"`
1175-
Qualifier string `json:"qualifier,omitempty"` // For qualified matchers like table.COLUMNS(...)
1230+
Position token.Position `json:"-"`
1231+
Pattern string `json:"pattern,omitempty"`
1232+
Columns []Expression `json:"columns,omitempty"` // For COLUMNS(id, name) syntax
1233+
Except []string `json:"except,omitempty"` // for EXCEPT (col1, col2) - deprecated, use Transformers
1234+
Replace []*ReplaceExpr `json:"replace,omitempty"` // for REPLACE (expr AS col) - deprecated, use Transformers
1235+
Apply []string `json:"apply,omitempty"` // for APPLY (func1) APPLY(func2) - deprecated, use Transformers
1236+
Qualifier string `json:"qualifier,omitempty"` // For qualified matchers like table.COLUMNS(...)
1237+
Transformers []*ColumnTransformer `json:"transformers,omitempty"` // ordered list of transformers
11761238
}
11771239

11781240
func (c *ColumnsMatcher) Pos() token.Position { return c.Position }
@@ -1392,9 +1454,10 @@ func (t *TupleAccess) expressionNode() {}
13921454

13931455
// Lambda represents a lambda expression.
13941456
type Lambda struct {
1395-
Position token.Position `json:"-"`
1396-
Parameters []string `json:"parameters"`
1397-
Body Expression `json:"body"`
1457+
Position token.Position `json:"-"`
1458+
Parameters []string `json:"parameters"`
1459+
Body Expression `json:"body"`
1460+
Parenthesized bool `json:"-"` // True if wrapped in explicit parentheses
13981461
}
13991462

14001463
func (l *Lambda) Pos() token.Position { return l.Position }

internal/explain/explain.go

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,16 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
113113
explainCreateQuery(sb, n, indent, depth)
114114
case *ast.DropQuery:
115115
explainDropQuery(sb, n, indent, depth)
116+
case *ast.UndropQuery:
117+
explainUndropQuery(sb, n, indent, depth)
116118
case *ast.RenameQuery:
117119
explainRenameQuery(sb, n, indent, depth)
118120
case *ast.ExchangeQuery:
119121
explainExchangeQuery(sb, n, indent)
120122
case *ast.SetQuery:
121123
explainSetQuery(sb, indent)
124+
case *ast.SetRoleQuery:
125+
fmt.Fprintf(sb, "%sSetRoleQuery\n", indent)
122126
case *ast.SystemQuery:
123127
explainSystemQuery(sb, n, indent)
124128
case *ast.TransactionControlQuery:
@@ -130,7 +134,14 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
130134
case *ast.ShowPrivilegesQuery:
131135
fmt.Fprintf(sb, "%sShowPrivilegesQuery\n", indent)
132136
case *ast.ShowCreateQuotaQuery:
133-
fmt.Fprintf(sb, "%sSHOW CREATE QUOTA query\n", indent)
137+
if n.Format != "" {
138+
fmt.Fprintf(sb, "%sSHOW CREATE QUOTA query (children 1)\n", indent)
139+
fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Format)
140+
} else {
141+
fmt.Fprintf(sb, "%sSHOW CREATE QUOTA query\n", indent)
142+
}
143+
case *ast.CreateQuotaQuery:
144+
fmt.Fprintf(sb, "%sCreateQuotaQuery\n", indent)
134145
case *ast.CreateSettingsProfileQuery:
135146
fmt.Fprintf(sb, "%sCreateSettingsProfileQuery\n", indent)
136147
case *ast.AlterSettingsProfileQuery:
@@ -140,27 +151,43 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
140151
fmt.Fprintf(sb, "%sDROP SETTINGS PROFILE query\n", indent)
141152
case *ast.ShowCreateSettingsProfileQuery:
142153
// Use PROFILES (plural) when multiple profiles are specified
154+
queryName := "SHOW CREATE SETTINGS PROFILE query"
143155
if len(n.Names) > 1 {
144-
fmt.Fprintf(sb, "%sSHOW CREATE SETTINGS PROFILES query\n", indent)
156+
queryName = "SHOW CREATE SETTINGS PROFILES query"
157+
}
158+
if n.Format != "" {
159+
fmt.Fprintf(sb, "%s%s (children 1)\n", indent, queryName)
160+
fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Format)
145161
} else {
146-
fmt.Fprintf(sb, "%sSHOW CREATE SETTINGS PROFILE query\n", indent)
162+
fmt.Fprintf(sb, "%s%s\n", indent, queryName)
147163
}
148164
case *ast.CreateRowPolicyQuery:
149165
fmt.Fprintf(sb, "%sCREATE ROW POLICY or ALTER ROW POLICY query\n", indent)
150166
case *ast.DropRowPolicyQuery:
151167
fmt.Fprintf(sb, "%sDROP ROW POLICY query\n", indent)
152168
case *ast.ShowCreateRowPolicyQuery:
153-
fmt.Fprintf(sb, "%sSHOW CREATE ROW POLICY query\n", indent)
169+
// ClickHouse uses "ROW POLICIES" (plural) when FORMAT is present
170+
if n.Format != "" {
171+
fmt.Fprintf(sb, "%sSHOW CREATE ROW POLICIES query (children 1)\n", indent)
172+
fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Format)
173+
} else {
174+
fmt.Fprintf(sb, "%sSHOW CREATE ROW POLICY query\n", indent)
175+
}
154176
case *ast.CreateRoleQuery:
155177
fmt.Fprintf(sb, "%sCreateRoleQuery\n", indent)
156178
case *ast.DropRoleQuery:
157179
fmt.Fprintf(sb, "%sDROP ROLE query\n", indent)
158180
case *ast.ShowCreateRoleQuery:
159181
// Use ROLES (plural) when multiple roles are specified
182+
queryName := "SHOW CREATE ROLE query"
160183
if n.RoleCount > 1 {
161-
fmt.Fprintf(sb, "%sSHOW CREATE ROLES query\n", indent)
184+
queryName = "SHOW CREATE ROLES query"
185+
}
186+
if n.Format != "" {
187+
fmt.Fprintf(sb, "%s%s (children 1)\n", indent, queryName)
188+
fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Format)
162189
} else {
163-
fmt.Fprintf(sb, "%sSHOW CREATE ROLE query\n", indent)
190+
fmt.Fprintf(sb, "%s%s\n", indent, queryName)
164191
}
165192
case *ast.CreateResourceQuery:
166193
fmt.Fprintf(sb, "%sCreateResourceQuery %s (children 1)\n", indent, n.Name)
@@ -181,7 +208,12 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
181208
case *ast.DropWorkloadQuery:
182209
fmt.Fprintf(sb, "%sDropWorkloadQuery\n", indent)
183210
case *ast.ShowGrantsQuery:
184-
fmt.Fprintf(sb, "%sShowGrantsQuery\n", indent)
211+
if n.Format != "" {
212+
fmt.Fprintf(sb, "%sShowGrantsQuery (children 1)\n", indent)
213+
fmt.Fprintf(sb, "%s Identifier %s\n", indent, n.Format)
214+
} else {
215+
fmt.Fprintf(sb, "%sShowGrantsQuery\n", indent)
216+
}
185217
case *ast.GrantQuery:
186218
fmt.Fprintf(sb, "%sGrantQuery\n", indent)
187219
case *ast.UseQuery:
@@ -285,7 +317,11 @@ func Column(sb *strings.Builder, col *ast.ColumnDeclaration, depth int) {
285317
if col.Codec != nil {
286318
children++
287319
}
288-
fmt.Fprintf(sb, "%sColumnDeclaration %s (children %d)\n", indent, col.Name, children)
320+
if children > 0 {
321+
fmt.Fprintf(sb, "%sColumnDeclaration %s (children %d)\n", indent, col.Name, children)
322+
} else {
323+
fmt.Fprintf(sb, "%sColumnDeclaration %s\n", indent, col.Name)
324+
}
289325
if col.Type != nil {
290326
Node(sb, col.Type, depth+1)
291327
}

0 commit comments

Comments
 (0)