Skip to content

Commit f5f21dd

Browse files
kyleconroyclaude
andcommitted
Add ALTER MATERIALIZED VIEW and ROUND_ROBIN distribution support
- Add ALTER MATERIALIZED VIEW REBUILD/DISABLE parsing - Add ViewRoundRobinDistributionPolicy type for DISTRIBUTION = ROUND_ROBIN - Update ViewDistributionOption to use interface for Value field - Enable MaterializedViewTests130 and Baselines130_MaterializedViewTests130 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fc5c95b commit f5f21dd

6 files changed

Lines changed: 90 additions & 29 deletions

File tree

ast/create_view_statement.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,15 @@ type ViewStatementOption struct {
5353

5454
func (v *ViewStatementOption) viewOption() {}
5555

56+
// ViewDistributionPolicy is an interface for distribution policy types
57+
type ViewDistributionPolicy interface {
58+
distributionPolicy()
59+
}
60+
5661
// ViewDistributionOption represents a DISTRIBUTION option for materialized views.
5762
type ViewDistributionOption struct {
58-
OptionKind string `json:"OptionKind,omitempty"`
59-
Value *ViewHashDistributionPolicy `json:"Value,omitempty"`
63+
OptionKind string `json:"OptionKind,omitempty"`
64+
Value ViewDistributionPolicy `json:"Value,omitempty"`
6065
}
6166

6267
func (v *ViewDistributionOption) viewOption() {}
@@ -67,6 +72,13 @@ type ViewHashDistributionPolicy struct {
6772
DistributionColumns []*Identifier `json:"DistributionColumns,omitempty"`
6873
}
6974

75+
func (v *ViewHashDistributionPolicy) distributionPolicy() {}
76+
77+
// ViewRoundRobinDistributionPolicy represents the round robin distribution policy for materialized views.
78+
type ViewRoundRobinDistributionPolicy struct{}
79+
80+
func (v *ViewRoundRobinDistributionPolicy) distributionPolicy() {}
81+
7082
// ViewForAppendOption represents the FOR_APPEND option for materialized views.
7183
type ViewForAppendOption struct {
7284
OptionKind string `json:"OptionKind,omitempty"`

parser/marshal.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4570,25 +4570,32 @@ func viewOptionToJSON(opt ast.ViewOption) jsonNode {
45704570
"OptionKind": o.OptionKind,
45714571
}
45724572
if o.Value != nil {
4573-
valueNode := jsonNode{
4574-
"$type": "ViewHashDistributionPolicy",
4575-
}
4576-
if o.Value.DistributionColumn != nil {
4577-
valueNode["DistributionColumn"] = identifierToJSON(o.Value.DistributionColumn)
4578-
}
4579-
if len(o.Value.DistributionColumns) > 0 {
4580-
cols := make([]jsonNode, len(o.Value.DistributionColumns))
4581-
for i, c := range o.Value.DistributionColumns {
4582-
// First column is same as DistributionColumn, use $ref
4583-
if i == 0 && o.Value.DistributionColumn != nil {
4584-
cols[i] = jsonNode{"$ref": "Identifier"}
4585-
} else {
4586-
cols[i] = identifierToJSON(c)
4573+
switch v := o.Value.(type) {
4574+
case *ast.ViewHashDistributionPolicy:
4575+
valueNode := jsonNode{
4576+
"$type": "ViewHashDistributionPolicy",
4577+
}
4578+
if v.DistributionColumn != nil {
4579+
valueNode["DistributionColumn"] = identifierToJSON(v.DistributionColumn)
4580+
}
4581+
if len(v.DistributionColumns) > 0 {
4582+
cols := make([]jsonNode, len(v.DistributionColumns))
4583+
for i, c := range v.DistributionColumns {
4584+
// First column is same as DistributionColumn, use $ref
4585+
if i == 0 && v.DistributionColumn != nil {
4586+
cols[i] = jsonNode{"$ref": "Identifier"}
4587+
} else {
4588+
cols[i] = identifierToJSON(c)
4589+
}
45874590
}
4591+
valueNode["DistributionColumns"] = cols
4592+
}
4593+
node["Value"] = valueNode
4594+
case *ast.ViewRoundRobinDistributionPolicy:
4595+
node["Value"] = jsonNode{
4596+
"$type": "ViewRoundRobinDistributionPolicy",
45884597
}
4589-
valueNode["DistributionColumns"] = cols
45904598
}
4591-
node["Value"] = valueNode
45924599
}
45934600
return node
45944601
case *ast.ViewForAppendOption:

parser/parse_ddl.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,6 +2191,8 @@ func (p *Parser) parseAlterStatement() (ast.Statement, error) {
21912191
return p.parseAlterSearchPropertyListStatement()
21922192
case "AVAILABILITY":
21932193
return p.parseAlterAvailabilityGroupStatement()
2194+
case "MATERIALIZED":
2195+
return p.parseAlterMaterializedViewStatement()
21942196
}
21952197
return nil, fmt.Errorf("unexpected token after ALTER: %s", p.curTok.Literal)
21962198
default:

parser/parse_statements.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4833,25 +4833,22 @@ func (p *Parser) parseCreateMaterializedViewStatement() (*ast.CreateViewStatemen
48334833
p.nextToken()
48344834

48354835
if optionName == "DISTRIBUTION" {
4836-
// Parse DISTRIBUTION = HASH(col1, col2, ...)
4836+
// Parse DISTRIBUTION = HASH(col1, col2, ...) or DISTRIBUTION = ROUND_ROBIN
48374837
if p.curTok.Type == TokenEquals {
48384838
p.nextToken()
48394839
}
48404840
if strings.ToUpper(p.curTok.Literal) == "HASH" {
48414841
p.nextToken()
48424842
if p.curTok.Type == TokenLParen {
48434843
p.nextToken()
4844-
distOpt := &ast.ViewDistributionOption{
4845-
OptionKind: "Distribution",
4846-
Value: &ast.ViewHashDistributionPolicy{},
4847-
}
4844+
hashPolicy := &ast.ViewHashDistributionPolicy{}
48484845
// Parse column list
48494846
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
48504847
col := p.parseIdentifier()
4851-
if distOpt.Value.DistributionColumn == nil {
4852-
distOpt.Value.DistributionColumn = col
4848+
if hashPolicy.DistributionColumn == nil {
4849+
hashPolicy.DistributionColumn = col
48534850
}
4854-
distOpt.Value.DistributionColumns = append(distOpt.Value.DistributionColumns, col)
4851+
hashPolicy.DistributionColumns = append(hashPolicy.DistributionColumns, col)
48554852
if p.curTok.Type == TokenComma {
48564853
p.nextToken()
48574854
} else {
@@ -4861,8 +4858,17 @@ func (p *Parser) parseCreateMaterializedViewStatement() (*ast.CreateViewStatemen
48614858
if p.curTok.Type == TokenRParen {
48624859
p.nextToken()
48634860
}
4864-
stmt.ViewOptions = append(stmt.ViewOptions, distOpt)
4861+
stmt.ViewOptions = append(stmt.ViewOptions, &ast.ViewDistributionOption{
4862+
OptionKind: "Distribution",
4863+
Value: hashPolicy,
4864+
})
48654865
}
4866+
} else if strings.ToUpper(p.curTok.Literal) == "ROUND_ROBIN" {
4867+
p.nextToken() // consume ROUND_ROBIN
4868+
stmt.ViewOptions = append(stmt.ViewOptions, &ast.ViewDistributionOption{
4869+
OptionKind: "Distribution",
4870+
Value: &ast.ViewRoundRobinDistributionPolicy{},
4871+
})
48664872
}
48674873
} else if optionName == "FOR_APPEND" {
48684874
stmt.ViewOptions = append(stmt.ViewOptions, &ast.ViewForAppendOption{
@@ -4900,6 +4906,40 @@ func (p *Parser) parseCreateMaterializedViewStatement() (*ast.CreateViewStatemen
49004906
return stmt, nil
49014907
}
49024908

4909+
func (p *Parser) parseAlterMaterializedViewStatement() (*ast.AlterViewStatement, error) {
4910+
// Consume MATERIALIZED
4911+
p.nextToken()
4912+
4913+
// Expect VIEW
4914+
if p.curTok.Type != TokenView {
4915+
return nil, fmt.Errorf("expected VIEW after MATERIALIZED, got %s", p.curTok.Literal)
4916+
}
4917+
p.nextToken()
4918+
4919+
stmt := &ast.AlterViewStatement{
4920+
IsMaterialized: true,
4921+
}
4922+
4923+
// Parse view name
4924+
son, err := p.parseSchemaObjectName()
4925+
if err != nil {
4926+
return nil, err
4927+
}
4928+
stmt.SchemaObjectName = son
4929+
4930+
// Parse REBUILD or DISABLE
4931+
switch strings.ToUpper(p.curTok.Literal) {
4932+
case "REBUILD":
4933+
stmt.IsRebuild = true
4934+
p.nextToken()
4935+
case "DISABLE":
4936+
stmt.IsDisable = true
4937+
p.nextToken()
4938+
}
4939+
4940+
return stmt, nil
4941+
}
4942+
49034943
func (p *Parser) parseCreateSchemaStatement() (*ast.CreateSchemaStatement, error) {
49044944
// Consume SCHEMA
49054945
p.nextToken()
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)