Skip to content

Commit 98179f2

Browse files
committed
Add FileGroupDefinition parsing for CREATE DATABASE ON clause
Implements support for parsing CREATE DATABASE with ON clause including: - FileGroupDefinition with FILEGROUP, PRIMARY, CONTAINS FILESTREAM/MEMORY_OPTIMIZED_DATA - FileDeclaration with NAME, FILENAME, SIZE, MAXSIZE, FILEGROWTH options - LOG ON clause for log file declarations - COLLATE clause - FOR ATTACH mode Enables 2 previously failing tests: - AlterCreateDatabaseStatementTests120 - Baselines120_AlterCreateDatabaseStatementTests120
1 parent 9c21ac5 commit 98179f2

6 files changed

Lines changed: 526 additions & 8 deletions

File tree

ast/create_simple_statements.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ package ast
22

33
// CreateDatabaseStatement represents a CREATE DATABASE statement.
44
type CreateDatabaseStatement struct {
5-
DatabaseName *Identifier `json:"DatabaseName,omitempty"`
6-
Options []CreateDatabaseOption `json:"Options,omitempty"`
7-
AttachMode string `json:"AttachMode,omitempty"` // "None", "Attach", "AttachRebuildLog"
8-
CopyOf *MultiPartIdentifier `json:"CopyOf,omitempty"` // For AS COPY OF syntax
5+
DatabaseName *Identifier `json:"DatabaseName,omitempty"`
6+
Options []CreateDatabaseOption `json:"Options,omitempty"`
7+
AttachMode string `json:"AttachMode,omitempty"` // "None", "Attach", "AttachRebuildLog"
8+
CopyOf *MultiPartIdentifier `json:"CopyOf,omitempty"` // For AS COPY OF syntax
9+
FileGroups []*FileGroupDefinition `json:"FileGroups,omitempty"`
10+
LogOn []*FileDeclaration `json:"LogOn,omitempty"`
11+
Collation *Identifier `json:"Collation,omitempty"`
912
}
1013

1114
func (s *CreateDatabaseStatement) node() {}

ast/file_declaration.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package ast
2+
3+
// FileGroupDefinition represents a FILEGROUP definition in CREATE DATABASE
4+
type FileGroupDefinition struct {
5+
Name *Identifier
6+
FileDeclarations []*FileDeclaration
7+
IsDefault bool
8+
ContainsFileStream bool
9+
ContainsMemoryOptimizedData bool
10+
}
11+
12+
func (f *FileGroupDefinition) node() {}
13+
14+
// FileDeclaration represents a file declaration within a filegroup
15+
type FileDeclaration struct {
16+
Options []FileDeclarationOption
17+
IsPrimary bool
18+
}
19+
20+
func (f *FileDeclaration) node() {}
21+
22+
// FileDeclarationOption is an interface for file declaration options
23+
type FileDeclarationOption interface {
24+
Node
25+
fileDeclarationOption()
26+
}
27+
28+
// NameFileDeclarationOption represents the NAME option for a file
29+
type NameFileDeclarationOption struct {
30+
LogicalFileName *IdentifierOrValueExpression
31+
IsNewName bool
32+
OptionKind string // "Name" or "NewName"
33+
}
34+
35+
func (n *NameFileDeclarationOption) node() {}
36+
func (n *NameFileDeclarationOption) fileDeclarationOption() {}
37+
38+
// FileNameFileDeclarationOption represents the FILENAME option for a file
39+
type FileNameFileDeclarationOption struct {
40+
OSFileName *StringLiteral
41+
OptionKind string // "FileName"
42+
}
43+
44+
func (f *FileNameFileDeclarationOption) node() {}
45+
func (f *FileNameFileDeclarationOption) fileDeclarationOption() {}
46+
47+
// SizeFileDeclarationOption represents the SIZE option for a file
48+
type SizeFileDeclarationOption struct {
49+
Size ScalarExpression
50+
Units string // "KB", "MB", "GB", "TB", "Unspecified"
51+
OptionKind string // "Size"
52+
}
53+
54+
func (s *SizeFileDeclarationOption) node() {}
55+
func (s *SizeFileDeclarationOption) fileDeclarationOption() {}
56+
57+
// MaxSizeFileDeclarationOption represents the MAXSIZE option for a file
58+
type MaxSizeFileDeclarationOption struct {
59+
MaxSize ScalarExpression
60+
Units string // "KB", "MB", "GB", "TB", "Unspecified"
61+
Unlimited bool
62+
OptionKind string // "MaxSize"
63+
}
64+
65+
func (m *MaxSizeFileDeclarationOption) node() {}
66+
func (m *MaxSizeFileDeclarationOption) fileDeclarationOption() {}
67+
68+
// FileGrowthFileDeclarationOption represents the FILEGROWTH option for a file
69+
type FileGrowthFileDeclarationOption struct {
70+
GrowthIncrement ScalarExpression
71+
Units string // "KB", "MB", "GB", "TB", "Percent", "Unspecified"
72+
OptionKind string // "FileGrowth"
73+
}
74+
75+
func (f *FileGrowthFileDeclarationOption) node() {}
76+
func (f *FileGrowthFileDeclarationOption) fileDeclarationOption() {}

parser/marshal.go

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8985,16 +8985,125 @@ func createDatabaseStatementToJSON(s *ast.CreateDatabaseStatement) jsonNode {
89858985
}
89868986
node["Options"] = opts
89878987
}
8988-
// AttachMode is output when there are Options or CopyOf
8989-
if (len(s.Options) > 0 || s.CopyOf != nil) && s.AttachMode != "" {
8988+
if len(s.FileGroups) > 0 {
8989+
fgs := make([]jsonNode, len(s.FileGroups))
8990+
for i, fg := range s.FileGroups {
8991+
fgs[i] = fileGroupDefinitionToJSON(fg)
8992+
}
8993+
node["FileGroups"] = fgs
8994+
}
8995+
if len(s.LogOn) > 0 {
8996+
logs := make([]jsonNode, len(s.LogOn))
8997+
for i, fd := range s.LogOn {
8998+
logs[i] = fileDeclarationToJSON(fd)
8999+
}
9000+
node["LogOn"] = logs
9001+
}
9002+
// AttachMode is output when there are FileGroups, Options, Collation, or CopyOf
9003+
if len(s.FileGroups) > 0 || len(s.Options) > 0 || s.Collation != nil || s.CopyOf != nil {
89909004
node["AttachMode"] = s.AttachMode
89919005
}
89929006
if s.CopyOf != nil {
89939007
node["CopyOf"] = multiPartIdentifierToJSON(s.CopyOf)
89949008
}
9009+
if s.Collation != nil {
9010+
node["Collation"] = identifierToJSON(s.Collation)
9011+
}
89959012
return node
89969013
}
89979014

9015+
func fileGroupDefinitionToJSON(fg *ast.FileGroupDefinition) jsonNode {
9016+
node := jsonNode{
9017+
"$type": "FileGroupDefinition",
9018+
}
9019+
if fg.Name != nil {
9020+
node["Name"] = identifierToJSON(fg.Name)
9021+
}
9022+
if len(fg.FileDeclarations) > 0 {
9023+
decls := make([]jsonNode, len(fg.FileDeclarations))
9024+
for i, fd := range fg.FileDeclarations {
9025+
decls[i] = fileDeclarationToJSON(fd)
9026+
}
9027+
node["FileDeclarations"] = decls
9028+
}
9029+
node["IsDefault"] = fg.IsDefault
9030+
node["ContainsFileStream"] = fg.ContainsFileStream
9031+
node["ContainsMemoryOptimizedData"] = fg.ContainsMemoryOptimizedData
9032+
return node
9033+
}
9034+
9035+
func fileDeclarationToJSON(fd *ast.FileDeclaration) jsonNode {
9036+
node := jsonNode{
9037+
"$type": "FileDeclaration",
9038+
}
9039+
if len(fd.Options) > 0 {
9040+
opts := make([]jsonNode, len(fd.Options))
9041+
for i, opt := range fd.Options {
9042+
opts[i] = fileDeclarationOptionToJSON(opt)
9043+
}
9044+
node["Options"] = opts
9045+
}
9046+
node["IsPrimary"] = fd.IsPrimary
9047+
return node
9048+
}
9049+
9050+
func fileDeclarationOptionToJSON(opt ast.FileDeclarationOption) jsonNode {
9051+
switch o := opt.(type) {
9052+
case *ast.NameFileDeclarationOption:
9053+
node := jsonNode{
9054+
"$type": "NameFileDeclarationOption",
9055+
"IsNewName": o.IsNewName,
9056+
"OptionKind": o.OptionKind,
9057+
}
9058+
if o.LogicalFileName != nil {
9059+
node["LogicalFileName"] = identifierOrValueExpressionToJSON(o.LogicalFileName)
9060+
}
9061+
return node
9062+
case *ast.FileNameFileDeclarationOption:
9063+
node := jsonNode{
9064+
"$type": "FileNameFileDeclarationOption",
9065+
"OptionKind": o.OptionKind,
9066+
}
9067+
if o.OSFileName != nil {
9068+
node["OSFileName"] = stringLiteralToJSON(o.OSFileName)
9069+
}
9070+
return node
9071+
case *ast.SizeFileDeclarationOption:
9072+
node := jsonNode{
9073+
"$type": "SizeFileDeclarationOption",
9074+
"Units": o.Units,
9075+
"OptionKind": o.OptionKind,
9076+
}
9077+
if o.Size != nil {
9078+
node["Size"] = scalarExpressionToJSON(o.Size)
9079+
}
9080+
return node
9081+
case *ast.MaxSizeFileDeclarationOption:
9082+
node := jsonNode{
9083+
"$type": "MaxSizeFileDeclarationOption",
9084+
"Units": o.Units,
9085+
"Unlimited": o.Unlimited,
9086+
"OptionKind": o.OptionKind,
9087+
}
9088+
if o.MaxSize != nil {
9089+
node["MaxSize"] = scalarExpressionToJSON(o.MaxSize)
9090+
}
9091+
return node
9092+
case *ast.FileGrowthFileDeclarationOption:
9093+
node := jsonNode{
9094+
"$type": "FileGrowthFileDeclarationOption",
9095+
"Units": o.Units,
9096+
"OptionKind": o.OptionKind,
9097+
}
9098+
if o.GrowthIncrement != nil {
9099+
node["GrowthIncrement"] = scalarExpressionToJSON(o.GrowthIncrement)
9100+
}
9101+
return node
9102+
default:
9103+
return jsonNode{"$type": "FileDeclarationOption"}
9104+
}
9105+
}
9106+
89989107
func createDatabaseOptionToJSON(opt ast.CreateDatabaseOption) jsonNode {
89999108
switch o := opt.(type) {
90009109
case *ast.OnOffDatabaseOption:

0 commit comments

Comments
 (0)