Skip to content

Commit 686cb2b

Browse files
committed
Add comprehensive CREATE XML INDEX parsing support
Implement full parsing for CREATE PRIMARY XML INDEX and CREATE XML INDEX statements including: - Primary flag for primary vs secondary indexes - XmlColumn field for the XML column being indexed - SecondaryXmlIndexName and SecondaryXmlIndexType for secondary indexes - USING XML INDEX ... FOR VALUE|PATH|PROPERTY syntax - WITH clause index options support Update PhaseOne test expectations to match canonical ScriptDom output.
1 parent 1be5aa2 commit 686cb2b

7 files changed

Lines changed: 142 additions & 14 deletions

File tree

ast/create_simple_statements.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,13 @@ func (s *CreateTypeTableStatement) statement() {}
436436

437437
// CreateXmlIndexStatement represents a CREATE XML INDEX statement.
438438
type CreateXmlIndexStatement struct {
439-
Name *Identifier `json:"Name,omitempty"`
440-
OnName *SchemaObjectName `json:"OnName,omitempty"`
439+
Primary bool `json:"Primary,omitempty"`
440+
XmlColumn *Identifier `json:"XmlColumn,omitempty"`
441+
SecondaryXmlIndexName *Identifier `json:"SecondaryXmlIndexName,omitempty"`
442+
SecondaryXmlIndexType string `json:"SecondaryXmlIndexType,omitempty"` // "NotSpecified", "Value", "Path", "Property"
443+
Name *Identifier `json:"Name,omitempty"`
444+
OnName *SchemaObjectName `json:"OnName,omitempty"`
445+
IndexOptions []IndexOption `json:"IndexOptions,omitempty"`
441446
}
442447

443448
func (s *CreateXmlIndexStatement) node() {}

parser/marshal.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13595,12 +13595,29 @@ func createXmlIndexStatementToJSON(s *ast.CreateXmlIndexStatement) jsonNode {
1359513595
node := jsonNode{
1359613596
"$type": "CreateXmlIndexStatement",
1359713597
}
13598+
node["Primary"] = s.Primary
13599+
if s.XmlColumn != nil {
13600+
node["XmlColumn"] = identifierToJSON(s.XmlColumn)
13601+
}
13602+
if s.SecondaryXmlIndexName != nil {
13603+
node["SecondaryXmlIndexName"] = identifierToJSON(s.SecondaryXmlIndexName)
13604+
}
13605+
if s.SecondaryXmlIndexType != "" {
13606+
node["SecondaryXmlIndexType"] = s.SecondaryXmlIndexType
13607+
}
1359813608
if s.Name != nil {
1359913609
node["Name"] = identifierToJSON(s.Name)
1360013610
}
1360113611
if s.OnName != nil {
1360213612
node["OnName"] = schemaObjectNameToJSON(s.OnName)
1360313613
}
13614+
if len(s.IndexOptions) > 0 {
13615+
opts := make([]jsonNode, len(s.IndexOptions))
13616+
for i, opt := range s.IndexOptions {
13617+
opts[i] = indexOptionToJSON(opt)
13618+
}
13619+
node["IndexOptions"] = opts
13620+
}
1360413621
return node
1360513622
}
1360613623

parser/parse_statements.go

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10451,11 +10451,35 @@ func (p *Parser) parseCreateXmlIndexStatement() (*ast.CreateXmlIndexStatement, e
1045110451
}
1045210452

1045310453
stmt := &ast.CreateXmlIndexStatement{
10454-
Name: p.parseIdentifier(),
10454+
Primary: true,
10455+
SecondaryXmlIndexType: "NotSpecified",
10456+
Name: p.parseIdentifier(),
10457+
}
10458+
10459+
// Parse ON table_name
10460+
if strings.ToUpper(p.curTok.Literal) == "ON" {
10461+
p.nextToken() // consume ON
10462+
stmt.OnName, _ = p.parseSchemaObjectName()
10463+
}
10464+
10465+
// Parse (column)
10466+
if p.curTok.Type == TokenLParen {
10467+
p.nextToken() // consume (
10468+
stmt.XmlColumn = p.parseIdentifier()
10469+
if p.curTok.Type == TokenRParen {
10470+
p.nextToken() // consume )
10471+
}
10472+
}
10473+
10474+
// Parse WITH (options) if present
10475+
if strings.ToUpper(p.curTok.Literal) == "WITH" {
10476+
p.nextToken() // consume WITH
10477+
if p.curTok.Type == TokenLParen {
10478+
// parseCreateIndexOptions expects to consume ( and ) itself
10479+
stmt.IndexOptions = p.parseCreateIndexOptions()
10480+
}
1045510481
}
1045610482

10457-
// Skip rest of statement
10458-
p.skipToEndOfStatement()
1045910483
return stmt, nil
1046010484
}
1046110485

@@ -10466,11 +10490,61 @@ func (p *Parser) parseCreateXmlIndexFromXml() (*ast.CreateXmlIndexStatement, err
1046610490
}
1046710491

1046810492
stmt := &ast.CreateXmlIndexStatement{
10469-
Name: p.parseIdentifier(),
10493+
Primary: false,
10494+
SecondaryXmlIndexType: "NotSpecified",
10495+
Name: p.parseIdentifier(),
10496+
}
10497+
10498+
// Parse ON table_name
10499+
if strings.ToUpper(p.curTok.Literal) == "ON" {
10500+
p.nextToken() // consume ON
10501+
stmt.OnName, _ = p.parseSchemaObjectName()
10502+
}
10503+
10504+
// Parse (column)
10505+
if p.curTok.Type == TokenLParen {
10506+
p.nextToken() // consume (
10507+
stmt.XmlColumn = p.parseIdentifier()
10508+
if p.curTok.Type == TokenRParen {
10509+
p.nextToken() // consume )
10510+
}
10511+
}
10512+
10513+
// Parse USING XML INDEX name FOR VALUE|PATH|PROPERTY
10514+
if strings.ToUpper(p.curTok.Literal) == "USING" {
10515+
p.nextToken() // consume USING
10516+
if strings.ToUpper(p.curTok.Literal) == "XML" {
10517+
p.nextToken() // consume XML
10518+
}
10519+
if p.curTok.Type == TokenIndex {
10520+
p.nextToken() // consume INDEX
10521+
}
10522+
stmt.SecondaryXmlIndexName = p.parseIdentifier()
10523+
if strings.ToUpper(p.curTok.Literal) == "FOR" {
10524+
p.nextToken() // consume FOR
10525+
switch strings.ToUpper(p.curTok.Literal) {
10526+
case "VALUE":
10527+
stmt.SecondaryXmlIndexType = "Value"
10528+
p.nextToken()
10529+
case "PATH":
10530+
stmt.SecondaryXmlIndexType = "Path"
10531+
p.nextToken()
10532+
case "PROPERTY":
10533+
stmt.SecondaryXmlIndexType = "Property"
10534+
p.nextToken()
10535+
}
10536+
}
10537+
}
10538+
10539+
// Parse WITH (options) if present
10540+
if strings.ToUpper(p.curTok.Literal) == "WITH" {
10541+
p.nextToken() // consume WITH
10542+
if p.curTok.Type == TokenLParen {
10543+
// parseCreateIndexOptions expects to consume ( and ) itself
10544+
stmt.IndexOptions = p.parseCreateIndexOptions()
10545+
}
1047010546
}
1047110547

10472-
// Skip rest of statement
10473-
p.skipToEndOfStatement()
1047410548
return stmt, nil
1047510549
}
1047610550

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"todo": true}
1+
{}

parser/testdata/PhaseOne_CreatePrimaryXmlIndex/ast.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@
66
"Statements": [
77
{
88
"$type": "CreateXmlIndexStatement",
9+
"Primary": true,
10+
"SecondaryXmlIndexType": "NotSpecified",
911
"Name": {
1012
"$type": "Identifier",
11-
"QuoteType": "NotQuoted",
12-
"Value": "i1"
13+
"Value": "i1",
14+
"QuoteType": "NotQuoted"
15+
},
16+
"OnName": {
17+
"$type": "SchemaObjectName",
18+
"BaseIdentifier": {
19+
"$type": "Identifier",
20+
"Value": "t1",
21+
"QuoteType": "NotQuoted"
22+
},
23+
"Count": 1,
24+
"Identifiers": [
25+
{
26+
"$ref": "Identifier"
27+
}
28+
]
1329
}
1430
}
1531
]

parser/testdata/PhaseOne_CreateXmlIndex/ast.json

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,26 @@
66
"Statements": [
77
{
88
"$type": "CreateXmlIndexStatement",
9+
"Primary": false,
10+
"SecondaryXmlIndexType": "NotSpecified",
911
"Name": {
1012
"$type": "Identifier",
11-
"QuoteType": "NotQuoted",
12-
"Value": "i1"
13+
"Value": "i1",
14+
"QuoteType": "NotQuoted"
15+
},
16+
"OnName": {
17+
"$type": "SchemaObjectName",
18+
"BaseIdentifier": {
19+
"$type": "Identifier",
20+
"Value": "t1",
21+
"QuoteType": "NotQuoted"
22+
},
23+
"Count": 1,
24+
"Identifiers": [
25+
{
26+
"$ref": "Identifier"
27+
}
28+
]
1329
}
1430
}
1531
]

0 commit comments

Comments
 (0)