Skip to content

Commit c5f3dca

Browse files
committed
Add support for NAMED COLLECTION query types
Add CreateNamedCollectionQuery, AlterNamedCollectionQuery, and DropNamedCollectionQuery as separate AST types with their own parsers and explain handlers. This properly parses CREATE/ALTER/DROP NAMED COLLECTION statements. Fixes 6 statements across 3 tests: - 02908_empty_named_collection (3 statements) - 02908_filesystem_cache_as_collection (1 statement) - 02918_fuzzjson_table_function (2 statements)
1 parent 4018703 commit c5f3dca

File tree

6 files changed

+151
-24
lines changed

6 files changed

+151
-24
lines changed

ast/ast.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,6 +1046,37 @@ func (d *DropSettingsProfileQuery) Pos() token.Position { return d.Position }
10461046
func (d *DropSettingsProfileQuery) End() token.Position { return d.Position }
10471047
func (d *DropSettingsProfileQuery) statementNode() {}
10481048

1049+
// CreateNamedCollectionQuery represents a CREATE NAMED COLLECTION statement.
1050+
type CreateNamedCollectionQuery struct {
1051+
Position token.Position `json:"-"`
1052+
Name string `json:"name,omitempty"`
1053+
}
1054+
1055+
func (c *CreateNamedCollectionQuery) Pos() token.Position { return c.Position }
1056+
func (c *CreateNamedCollectionQuery) End() token.Position { return c.Position }
1057+
func (c *CreateNamedCollectionQuery) statementNode() {}
1058+
1059+
// AlterNamedCollectionQuery represents an ALTER NAMED COLLECTION statement.
1060+
type AlterNamedCollectionQuery struct {
1061+
Position token.Position `json:"-"`
1062+
Name string `json:"name,omitempty"`
1063+
}
1064+
1065+
func (a *AlterNamedCollectionQuery) Pos() token.Position { return a.Position }
1066+
func (a *AlterNamedCollectionQuery) End() token.Position { return a.Position }
1067+
func (a *AlterNamedCollectionQuery) statementNode() {}
1068+
1069+
// DropNamedCollectionQuery represents a DROP NAMED COLLECTION statement.
1070+
type DropNamedCollectionQuery struct {
1071+
Position token.Position `json:"-"`
1072+
Name string `json:"name,omitempty"`
1073+
IfExists bool `json:"if_exists,omitempty"`
1074+
}
1075+
1076+
func (d *DropNamedCollectionQuery) Pos() token.Position { return d.Position }
1077+
func (d *DropNamedCollectionQuery) End() token.Position { return d.Position }
1078+
func (d *DropNamedCollectionQuery) statementNode() {}
1079+
10491080
// ShowCreateSettingsProfileQuery represents a SHOW CREATE SETTINGS PROFILE statement.
10501081
type ShowCreateSettingsProfileQuery struct {
10511082
Position token.Position `json:"-"`

internal/explain/explain.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ func Node(sb *strings.Builder, node interface{}, depth int) {
155155
fmt.Fprintf(sb, "%sCreateSettingsProfileQuery\n", indent)
156156
case *ast.DropSettingsProfileQuery:
157157
fmt.Fprintf(sb, "%sDROP SETTINGS PROFILE query\n", indent)
158+
case *ast.CreateNamedCollectionQuery:
159+
fmt.Fprintf(sb, "%sCreateNamedCollectionQuery\n", indent)
160+
case *ast.AlterNamedCollectionQuery:
161+
fmt.Fprintf(sb, "%sAlterNamedCollectionQuery\n", indent)
162+
case *ast.DropNamedCollectionQuery:
163+
fmt.Fprintf(sb, "%sDropNamedCollectionQuery\n", indent)
158164
case *ast.ShowCreateSettingsProfileQuery:
159165
// Use PROFILES (plural) when multiple profiles are specified
160166
queryName := "SHOW CREATE SETTINGS PROFILE query"

parser/parser.go

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ func (p *Parser) parseStatement() ast.Statement {
247247
if p.peek.Token == token.IDENT && strings.ToUpper(p.peek.Value) == "WORKLOAD" {
248248
return p.parseDropWorkload()
249249
}
250+
// Check for DROP NAMED COLLECTION
251+
if p.peek.Token == token.IDENT && strings.ToUpper(p.peek.Value) == "NAMED" {
252+
return p.parseDropNamedCollection()
253+
}
250254
return p.parseDrop()
251255
case token.ALTER:
252256
// Check for ALTER USER
@@ -269,6 +273,10 @@ func (p *Parser) parseStatement() ast.Statement {
269273
if p.peek.Token == token.IDENT && strings.ToUpper(p.peek.Value) == "ROLE" {
270274
return p.parseAlterRole()
271275
}
276+
// Check for ALTER NAMED COLLECTION
277+
if p.peek.Token == token.IDENT && strings.ToUpper(p.peek.Value) == "NAMED" {
278+
return p.parseAlterNamedCollection()
279+
}
272280
return p.parseAlter()
273281
case token.TRUNCATE:
274282
return p.parseTruncate()
@@ -1938,12 +1946,7 @@ func (p *Parser) parseCreate() ast.Statement {
19381946
p.parseCreateDictionary(create)
19391947
case "NAMED":
19401948
// CREATE NAMED COLLECTION name AS key=value, ...
1941-
p.nextToken() // skip NAMED
1942-
// Skip "COLLECTION" if present
1943-
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "COLLECTION" {
1944-
p.nextToken()
1945-
}
1946-
p.parseCreateGeneric(create)
1949+
return p.parseCreateNamedCollection(pos)
19471950
case "PROFILE":
19481951
// CREATE PROFILE (without SETTINGS keyword)
19491952
return p.parseCreateSettingsProfile(pos)
@@ -3207,6 +3210,108 @@ func (p *Parser) parseCreateQuota(pos token.Position) *ast.CreateQuotaQuery {
32073210
return query
32083211
}
32093212

3213+
func (p *Parser) parseCreateNamedCollection(pos token.Position) *ast.CreateNamedCollectionQuery {
3214+
query := &ast.CreateNamedCollectionQuery{
3215+
Position: pos,
3216+
}
3217+
3218+
// Skip NAMED keyword
3219+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "NAMED" {
3220+
p.nextToken()
3221+
}
3222+
3223+
// Skip COLLECTION keyword
3224+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "COLLECTION" {
3225+
p.nextToken()
3226+
}
3227+
3228+
// Parse collection name
3229+
if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() || p.currentIs(token.STRING) {
3230+
query.Name = p.current.Value
3231+
p.nextToken()
3232+
}
3233+
3234+
// Skip the rest of the statement (AS key=value, ...)
3235+
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
3236+
p.nextToken()
3237+
}
3238+
3239+
return query
3240+
}
3241+
3242+
func (p *Parser) parseAlterNamedCollection() *ast.AlterNamedCollectionQuery {
3243+
pos := p.current.Pos
3244+
p.nextToken() // skip ALTER
3245+
3246+
query := &ast.AlterNamedCollectionQuery{
3247+
Position: pos,
3248+
}
3249+
3250+
// Skip NAMED keyword
3251+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "NAMED" {
3252+
p.nextToken()
3253+
}
3254+
3255+
// Skip COLLECTION keyword
3256+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "COLLECTION" {
3257+
p.nextToken()
3258+
}
3259+
3260+
// Parse collection name
3261+
if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() || p.currentIs(token.STRING) {
3262+
query.Name = p.current.Value
3263+
p.nextToken()
3264+
}
3265+
3266+
// Skip the rest of the statement (DELETE key, SET key=value, ...)
3267+
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
3268+
p.nextToken()
3269+
}
3270+
3271+
return query
3272+
}
3273+
3274+
func (p *Parser) parseDropNamedCollection() *ast.DropNamedCollectionQuery {
3275+
pos := p.current.Pos
3276+
p.nextToken() // skip DROP
3277+
3278+
query := &ast.DropNamedCollectionQuery{
3279+
Position: pos,
3280+
}
3281+
3282+
// Skip NAMED keyword
3283+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "NAMED" {
3284+
p.nextToken()
3285+
}
3286+
3287+
// Skip COLLECTION keyword
3288+
if p.currentIs(token.IDENT) && strings.ToUpper(p.current.Value) == "COLLECTION" {
3289+
p.nextToken()
3290+
}
3291+
3292+
// Handle IF EXISTS
3293+
if p.currentIs(token.IF) {
3294+
p.nextToken()
3295+
if p.currentIs(token.EXISTS) {
3296+
query.IfExists = true
3297+
p.nextToken()
3298+
}
3299+
}
3300+
3301+
// Parse collection name
3302+
if p.currentIs(token.IDENT) || p.current.Token.IsKeyword() || p.currentIs(token.STRING) {
3303+
query.Name = p.current.Value
3304+
p.nextToken()
3305+
}
3306+
3307+
// Skip the rest of the statement
3308+
for !p.currentIs(token.EOF) && !p.currentIs(token.SEMICOLON) {
3309+
p.nextToken()
3310+
}
3311+
3312+
return query
3313+
}
3314+
32103315
func (p *Parser) parseShowCreateRole(pos token.Position) *ast.ShowCreateRoleQuery {
32113316
query := &ast.ShowCreateRoleQuery{
32123317
Position: pos,
Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt1": true,
4-
"stmt2": true,
5-
"stmt3": true
6-
}
7-
}
1+
{}
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt1": true
4-
}
5-
}
1+
{}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
1-
{
2-
"explain_todo": {
3-
"stmt1": true,
4-
"stmt2": true
5-
}
6-
}
1+
{}

0 commit comments

Comments
 (0)