Skip to content

Commit 6bf8518

Browse files
committed
Add CREATE AVAILABILITY GROUP statement support
- Add CreateAvailabilityGroupStatement AST type with full replica parsing - Support REQUIRED_COPIES_TO_COMMIT option - Parse replica options: AVAILABILITY_MODE, FAILOVER_MODE, ENDPOINT_URL, SESSION_TIMEOUT, APPLY_DELAY - Parse role-based options: PRIMARY_ROLE and SECONDARY_ROLE with ALLOW_CONNECTIONS - Add marshaling functions for all new types - Enable 2 passing tests
1 parent 6c1b76e commit 6bf8518

5 files changed

Lines changed: 468 additions & 2 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package ast
2+
3+
// CreateAvailabilityGroupStatement represents a CREATE AVAILABILITY GROUP statement
4+
type CreateAvailabilityGroupStatement struct {
5+
Name *Identifier
6+
Options []AvailabilityGroupOption
7+
Databases []*Identifier
8+
Replicas []*AvailabilityReplica
9+
}
10+
11+
func (s *CreateAvailabilityGroupStatement) node() {}
12+
func (s *CreateAvailabilityGroupStatement) statement() {}
13+
14+
// AvailabilityGroupOption is an interface for availability group options
15+
type AvailabilityGroupOption interface {
16+
node()
17+
availabilityGroupOption()
18+
}
19+
20+
// LiteralAvailabilityGroupOption represents an availability group option with a literal value
21+
type LiteralAvailabilityGroupOption struct {
22+
OptionKind string // e.g., "RequiredCopiesToCommit"
23+
Value ScalarExpression // The value for the option
24+
}
25+
26+
func (o *LiteralAvailabilityGroupOption) node() {}
27+
func (o *LiteralAvailabilityGroupOption) availabilityGroupOption() {}
28+
29+
// AvailabilityReplica represents a replica in an availability group
30+
type AvailabilityReplica struct {
31+
ServerName *StringLiteral
32+
Options []AvailabilityReplicaOption
33+
}
34+
35+
func (r *AvailabilityReplica) node() {}
36+
37+
// AvailabilityReplicaOption is an interface for availability replica options
38+
type AvailabilityReplicaOption interface {
39+
node()
40+
availabilityReplicaOption()
41+
}
42+
43+
// AvailabilityModeReplicaOption represents AVAILABILITY_MODE option
44+
type AvailabilityModeReplicaOption struct {
45+
OptionKind string // "AvailabilityMode"
46+
Value string // "SynchronousCommit", "AsynchronousCommit"
47+
}
48+
49+
func (o *AvailabilityModeReplicaOption) node() {}
50+
func (o *AvailabilityModeReplicaOption) availabilityReplicaOption() {}
51+
52+
// FailoverModeReplicaOption represents FAILOVER_MODE option
53+
type FailoverModeReplicaOption struct {
54+
OptionKind string // "FailoverMode"
55+
Value string // "Automatic", "Manual"
56+
}
57+
58+
func (o *FailoverModeReplicaOption) node() {}
59+
func (o *FailoverModeReplicaOption) availabilityReplicaOption() {}
60+
61+
// LiteralReplicaOption represents a replica option with a literal value
62+
type LiteralReplicaOption struct {
63+
OptionKind string // e.g., "EndpointUrl", "SessionTimeout", "ApplyDelay"
64+
Value ScalarExpression // The value for the option
65+
}
66+
67+
func (o *LiteralReplicaOption) node() {}
68+
func (o *LiteralReplicaOption) availabilityReplicaOption() {}
69+
70+
// PrimaryRoleReplicaOption represents PRIMARY_ROLE option
71+
type PrimaryRoleReplicaOption struct {
72+
OptionKind string // "PrimaryRole"
73+
AllowConnections string // "All", "ReadWrite"
74+
}
75+
76+
func (o *PrimaryRoleReplicaOption) node() {}
77+
func (o *PrimaryRoleReplicaOption) availabilityReplicaOption() {}
78+
79+
// SecondaryRoleReplicaOption represents SECONDARY_ROLE option
80+
type SecondaryRoleReplicaOption struct {
81+
OptionKind string // "SecondaryRole"
82+
AllowConnections string // "No", "ReadOnly", "All"
83+
}
84+
85+
func (o *SecondaryRoleReplicaOption) node() {}
86+
func (o *SecondaryRoleReplicaOption) availabilityReplicaOption() {}

parser/marshal.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ func statementToJSON(stmt ast.Statement) jsonNode {
344344
return createServerRoleStatementToJSON(s)
345345
case *ast.AlterServerRoleStatement:
346346
return alterServerRoleStatementToJSON(s)
347+
case *ast.CreateAvailabilityGroupStatement:
348+
return createAvailabilityGroupStatementToJSON(s)
347349
case *ast.CreateServerAuditStatement:
348350
return createServerAuditStatementToJSON(s)
349351
case *ast.AlterServerAuditStatement:
@@ -8031,6 +8033,110 @@ func alterServerRoleStatementToJSON(s *ast.AlterServerRoleStatement) jsonNode {
80318033
return node
80328034
}
80338035

8036+
func createAvailabilityGroupStatementToJSON(s *ast.CreateAvailabilityGroupStatement) jsonNode {
8037+
node := jsonNode{
8038+
"$type": "CreateAvailabilityGroupStatement",
8039+
}
8040+
if s.Name != nil {
8041+
node["Name"] = identifierToJSON(s.Name)
8042+
}
8043+
if len(s.Options) > 0 {
8044+
opts := make([]jsonNode, len(s.Options))
8045+
for i, opt := range s.Options {
8046+
opts[i] = availabilityGroupOptionToJSON(opt)
8047+
}
8048+
node["Options"] = opts
8049+
}
8050+
if len(s.Databases) > 0 {
8051+
dbs := make([]jsonNode, len(s.Databases))
8052+
for i, db := range s.Databases {
8053+
dbs[i] = identifierToJSON(db)
8054+
}
8055+
node["Databases"] = dbs
8056+
}
8057+
if len(s.Replicas) > 0 {
8058+
reps := make([]jsonNode, len(s.Replicas))
8059+
for i, rep := range s.Replicas {
8060+
reps[i] = availabilityReplicaToJSON(rep)
8061+
}
8062+
node["Replicas"] = reps
8063+
}
8064+
return node
8065+
}
8066+
8067+
func availabilityGroupOptionToJSON(opt ast.AvailabilityGroupOption) jsonNode {
8068+
switch o := opt.(type) {
8069+
case *ast.LiteralAvailabilityGroupOption:
8070+
node := jsonNode{
8071+
"$type": "LiteralAvailabilityGroupOption",
8072+
}
8073+
if o.Value != nil {
8074+
node["Value"] = scalarExpressionToJSON(o.Value)
8075+
}
8076+
node["OptionKind"] = o.OptionKind
8077+
return node
8078+
default:
8079+
return jsonNode{"$type": "UnknownAvailabilityGroupOption"}
8080+
}
8081+
}
8082+
8083+
func availabilityReplicaToJSON(rep *ast.AvailabilityReplica) jsonNode {
8084+
node := jsonNode{
8085+
"$type": "AvailabilityReplica",
8086+
}
8087+
if rep.ServerName != nil {
8088+
node["ServerName"] = stringLiteralToJSON(rep.ServerName)
8089+
}
8090+
if len(rep.Options) > 0 {
8091+
opts := make([]jsonNode, len(rep.Options))
8092+
for i, opt := range rep.Options {
8093+
opts[i] = availabilityReplicaOptionToJSON(opt)
8094+
}
8095+
node["Options"] = opts
8096+
}
8097+
return node
8098+
}
8099+
8100+
func availabilityReplicaOptionToJSON(opt ast.AvailabilityReplicaOption) jsonNode {
8101+
switch o := opt.(type) {
8102+
case *ast.AvailabilityModeReplicaOption:
8103+
return jsonNode{
8104+
"$type": "AvailabilityModeReplicaOption",
8105+
"Value": o.Value,
8106+
"OptionKind": o.OptionKind,
8107+
}
8108+
case *ast.FailoverModeReplicaOption:
8109+
return jsonNode{
8110+
"$type": "FailoverModeReplicaOption",
8111+
"Value": o.Value,
8112+
"OptionKind": o.OptionKind,
8113+
}
8114+
case *ast.LiteralReplicaOption:
8115+
node := jsonNode{
8116+
"$type": "LiteralReplicaOption",
8117+
}
8118+
if o.Value != nil {
8119+
node["Value"] = scalarExpressionToJSON(o.Value)
8120+
}
8121+
node["OptionKind"] = o.OptionKind
8122+
return node
8123+
case *ast.PrimaryRoleReplicaOption:
8124+
return jsonNode{
8125+
"$type": "PrimaryRoleReplicaOption",
8126+
"AllowConnections": o.AllowConnections,
8127+
"OptionKind": o.OptionKind,
8128+
}
8129+
case *ast.SecondaryRoleReplicaOption:
8130+
return jsonNode{
8131+
"$type": "SecondaryRoleReplicaOption",
8132+
"AllowConnections": o.AllowConnections,
8133+
"OptionKind": o.OptionKind,
8134+
}
8135+
default:
8136+
return jsonNode{"$type": "UnknownReplicaOption"}
8137+
}
8138+
}
8139+
80348140
func createServerAuditStatementToJSON(s *ast.CreateServerAuditStatement) jsonNode {
80358141
node := jsonNode{
80368142
"$type": "CreateServerAuditStatement",

0 commit comments

Comments
 (0)