Skip to content

Commit e08d5e9

Browse files
committed
Add CREATE/ALTER SERVICE full parsing support
Add support for: - CREATE SERVICE with AUTHORIZATION, ON QUEUE, and contract list - ALTER SERVICE with ON QUEUE and ADD/DROP CONTRACT operations - ServiceContract type with Name and Action fields Enabled tests: - AlterCreateServiceStatementTests - Baselines90_AlterCreateServiceStatementTests
1 parent 4fbe2ea commit e08d5e9

7 files changed

Lines changed: 128 additions & 4 deletions

File tree

ast/alter_simple_statements.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ func (s *AlterEndpointStatement) statement() {}
2626

2727
// AlterServiceStatement represents an ALTER SERVICE statement.
2828
type AlterServiceStatement struct {
29-
Name *Identifier `json:"Name,omitempty"`
29+
Name *Identifier `json:"Name,omitempty"`
30+
QueueName *SchemaObjectName `json:"QueueName,omitempty"`
31+
ServiceContracts []*ServiceContract `json:"ServiceContracts,omitempty"`
3032
}
3133

3234
func (s *AlterServiceStatement) node() {}

ast/create_simple_statements.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,20 @@ type CreateLoginStatement struct {
3232
func (s *CreateLoginStatement) node() {}
3333
func (s *CreateLoginStatement) statement() {}
3434

35+
// ServiceContract represents a contract in CREATE/ALTER SERVICE.
36+
type ServiceContract struct {
37+
Name *Identifier `json:"Name,omitempty"`
38+
Action string `json:"Action,omitempty"` // "Add", "Drop", "None"
39+
}
40+
41+
func (s *ServiceContract) node() {}
42+
3543
// CreateServiceStatement represents a CREATE SERVICE statement.
3644
type CreateServiceStatement struct {
37-
Name *Identifier `json:"Name,omitempty"`
45+
Owner *Identifier `json:"Owner,omitempty"`
46+
Name *Identifier `json:"Name,omitempty"`
47+
QueueName *SchemaObjectName `json:"QueueName,omitempty"`
48+
ServiceContracts []*ServiceContract `json:"ServiceContracts,omitempty"`
3849
}
3950

4051
func (s *CreateServiceStatement) node() {}

parser/marshal.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8764,6 +8764,16 @@ func alterServiceStatementToJSON(s *ast.AlterServiceStatement) jsonNode {
87648764
if s.Name != nil {
87658765
node["Name"] = identifierToJSON(s.Name)
87668766
}
8767+
if s.QueueName != nil {
8768+
node["QueueName"] = schemaObjectNameToJSON(s.QueueName)
8769+
}
8770+
if len(s.ServiceContracts) > 0 {
8771+
contracts := make([]jsonNode, len(s.ServiceContracts))
8772+
for i, c := range s.ServiceContracts {
8773+
contracts[i] = serviceContractToJSON(c)
8774+
}
8775+
node["ServiceContracts"] = contracts
8776+
}
87678777
return node
87688778
}
87698779

@@ -9331,9 +9341,33 @@ func createServiceStatementToJSON(s *ast.CreateServiceStatement) jsonNode {
93319341
node := jsonNode{
93329342
"$type": "CreateServiceStatement",
93339343
}
9344+
if s.Owner != nil {
9345+
node["Owner"] = identifierToJSON(s.Owner)
9346+
}
93349347
if s.Name != nil {
93359348
node["Name"] = identifierToJSON(s.Name)
93369349
}
9350+
if s.QueueName != nil {
9351+
node["QueueName"] = schemaObjectNameToJSON(s.QueueName)
9352+
}
9353+
if len(s.ServiceContracts) > 0 {
9354+
contracts := make([]jsonNode, len(s.ServiceContracts))
9355+
for i, c := range s.ServiceContracts {
9356+
contracts[i] = serviceContractToJSON(c)
9357+
}
9358+
node["ServiceContracts"] = contracts
9359+
}
9360+
return node
9361+
}
9362+
9363+
func serviceContractToJSON(c *ast.ServiceContract) jsonNode {
9364+
node := jsonNode{
9365+
"$type": "ServiceContract",
9366+
}
9367+
if c.Name != nil {
9368+
node["Name"] = identifierToJSON(c.Name)
9369+
}
9370+
node["Action"] = c.Action
93379371
return node
93389372
}
93399373

parser/parse_ddl.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3790,6 +3790,49 @@ func (p *Parser) parseAlterServiceStatement() (ast.Statement, error) {
37903790
// Parse service name
37913791
stmt.Name = p.parseIdentifier()
37923792

3793+
// Check for ON QUEUE clause
3794+
if p.curTok.Type == TokenOn && strings.ToUpper(p.peekTok.Literal) == "QUEUE" {
3795+
p.nextToken() // consume ON
3796+
p.nextToken() // consume QUEUE
3797+
queueName, _ := p.parseSchemaObjectName()
3798+
stmt.QueueName = queueName
3799+
}
3800+
3801+
// Check for contract modifications (ADD CONTRACT, DROP CONTRACT)
3802+
if p.curTok.Type == TokenLParen {
3803+
p.nextToken() // consume (
3804+
var contracts []*ast.ServiceContract
3805+
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
3806+
action := "None"
3807+
upperLit := strings.ToUpper(p.curTok.Literal)
3808+
if upperLit == "ADD" {
3809+
action = "Add"
3810+
p.nextToken() // consume ADD
3811+
if strings.ToUpper(p.curTok.Literal) == "CONTRACT" {
3812+
p.nextToken() // consume CONTRACT
3813+
}
3814+
} else if upperLit == "DROP" {
3815+
action = "Drop"
3816+
p.nextToken() // consume DROP
3817+
if strings.ToUpper(p.curTok.Literal) == "CONTRACT" {
3818+
p.nextToken() // consume CONTRACT
3819+
}
3820+
}
3821+
contract := &ast.ServiceContract{
3822+
Name: p.parseIdentifier(),
3823+
Action: action,
3824+
}
3825+
contracts = append(contracts, contract)
3826+
if p.curTok.Type == TokenComma {
3827+
p.nextToken() // consume ,
3828+
}
3829+
}
3830+
if p.curTok.Type == TokenRParen {
3831+
p.nextToken() // consume )
3832+
}
3833+
stmt.ServiceContracts = contracts
3834+
}
3835+
37933836
// Skip rest of statement
37943837
p.skipToEndOfStatement()
37953838

parser/parse_statements.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6855,6 +6855,40 @@ func (p *Parser) parseCreateServiceStatement() (*ast.CreateServiceStatement, err
68556855
Name: p.parseIdentifier(),
68566856
}
68576857

6858+
// Check for AUTHORIZATION clause
6859+
if strings.ToUpper(p.curTok.Literal) == "AUTHORIZATION" {
6860+
p.nextToken() // consume AUTHORIZATION
6861+
stmt.Owner = p.parseIdentifier()
6862+
}
6863+
6864+
// Check for ON QUEUE clause
6865+
if p.curTok.Type == TokenOn && strings.ToUpper(p.peekTok.Literal) == "QUEUE" {
6866+
p.nextToken() // consume ON
6867+
p.nextToken() // consume QUEUE
6868+
queueName, _ := p.parseSchemaObjectName()
6869+
stmt.QueueName = queueName
6870+
}
6871+
6872+
// Check for contract list (c1, c2, ...)
6873+
if p.curTok.Type == TokenLParen {
6874+
p.nextToken() // consume (
6875+
var contracts []*ast.ServiceContract
6876+
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
6877+
contract := &ast.ServiceContract{
6878+
Name: p.parseIdentifier(),
6879+
Action: "None",
6880+
}
6881+
contracts = append(contracts, contract)
6882+
if p.curTok.Type == TokenComma {
6883+
p.nextToken() // consume ,
6884+
}
6885+
}
6886+
if p.curTok.Type == TokenRParen {
6887+
p.nextToken() // consume )
6888+
}
6889+
stmt.ServiceContracts = contracts
6890+
}
6891+
68586892
// Skip rest of statement
68596893
p.skipToEndOfStatement()
68606894
return stmt, nil
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+
{}

0 commit comments

Comments
 (0)