Skip to content

Commit dd42f28

Browse files
kyleconroyclaude
andcommitted
Add WITH clause support for ALTER TABLE ALTER COLUMN
- Add Options field to AlterTableAlterColumnStatement - Parse WITH (ONLINE = ON/OFF) after ADD/DROP ROWGUIDCOL and data type changes - Add ADD/DROP MASKED handling - Skip UTF-16 encoded fulltext index tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent e0d0edc commit dd42f28

5 files changed

Lines changed: 115 additions & 2 deletions

File tree

ast/alter_table_alter_column_statement.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type AlterTableAlterColumnStatement struct {
1212
IsMasked bool
1313
Encryption *ColumnEncryptionDefinition
1414
MaskingFunction ScalarExpression
15+
Options []IndexOption
1516
}
1617

1718
func (a *AlterTableAlterColumnStatement) node() {}

parser/marshal.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,13 @@ func alterTableAlterColumnStatementToJSON(s *ast.AlterTableAlterColumnStatement)
976976
if s.MaskingFunction != nil {
977977
node["MaskingFunction"] = scalarExpressionToJSON(s.MaskingFunction)
978978
}
979+
if len(s.Options) > 0 {
980+
opts := make([]jsonNode, len(s.Options))
981+
for i, opt := range s.Options {
982+
opts[i] = indexOptionToJSON(opt)
983+
}
984+
node["Options"] = opts
985+
}
979986
if s.SchemaObjectName != nil {
980987
node["SchemaObjectName"] = schemaObjectNameToJSON(s.SchemaObjectName)
981988
}

parser/parse_ddl.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5072,6 +5072,30 @@ func (p *Parser) parseAlterTableAlterColumnStatement(tableName *ast.SchemaObject
50725072
} else if nextLit == "HIDDEN" {
50735073
stmt.AlterTableAlterColumnOption = "AddHidden"
50745074
p.nextToken()
5075+
} else if nextLit == "MASKED" {
5076+
stmt.AlterTableAlterColumnOption = "AddMasked"
5077+
stmt.IsMasked = true
5078+
p.nextToken()
5079+
// Parse optional WITH (FUNCTION = '...')
5080+
if p.curTok.Type == TokenWith {
5081+
p.nextToken() // consume WITH
5082+
if p.curTok.Type == TokenLParen {
5083+
p.nextToken() // consume (
5084+
if strings.ToUpper(p.curTok.Literal) == "FUNCTION" {
5085+
p.nextToken() // consume FUNCTION
5086+
if p.curTok.Type == TokenEquals {
5087+
p.nextToken() // consume =
5088+
}
5089+
if p.curTok.Type == TokenString {
5090+
maskFunc, _ := p.parseStringLiteral()
5091+
stmt.MaskingFunction = maskFunc
5092+
}
5093+
}
5094+
if p.curTok.Type == TokenRParen {
5095+
p.nextToken() // consume )
5096+
}
5097+
}
5098+
}
50755099
} else if nextLit == "NOT" {
50765100
p.nextToken() // consume NOT
50775101
if strings.ToUpper(p.curTok.Literal) == "FOR" {
@@ -5082,6 +5106,14 @@ func (p *Parser) parseAlterTableAlterColumnStatement(tableName *ast.SchemaObject
50825106
}
50835107
stmt.AlterTableAlterColumnOption = "AddNotForReplication"
50845108
}
5109+
// Parse optional WITH clause for ONLINE option
5110+
if p.curTok.Type == TokenWith {
5111+
opts, err := p.parseAlterColumnWithOptions()
5112+
if err != nil {
5113+
return nil, err
5114+
}
5115+
stmt.Options = opts
5116+
}
50855117
// Skip optional semicolon
50865118
if p.curTok.Type == TokenSemicolon {
50875119
p.nextToken()
@@ -5102,6 +5134,9 @@ func (p *Parser) parseAlterTableAlterColumnStatement(tableName *ast.SchemaObject
51025134
} else if nextLit == "HIDDEN" {
51035135
stmt.AlterTableAlterColumnOption = "DropHidden"
51045136
p.nextToken()
5137+
} else if nextLit == "MASKED" {
5138+
stmt.AlterTableAlterColumnOption = "DropMasked"
5139+
p.nextToken()
51055140
} else if nextLit == "NOT" {
51065141
p.nextToken() // consume NOT
51075142
if strings.ToUpper(p.curTok.Literal) == "FOR" {
@@ -5112,6 +5147,14 @@ func (p *Parser) parseAlterTableAlterColumnStatement(tableName *ast.SchemaObject
51125147
}
51135148
stmt.AlterTableAlterColumnOption = "DropNotForReplication"
51145149
}
5150+
// Parse optional WITH clause for ONLINE option
5151+
if p.curTok.Type == TokenWith {
5152+
opts, err := p.parseAlterColumnWithOptions()
5153+
if err != nil {
5154+
return nil, err
5155+
}
5156+
stmt.Options = opts
5157+
}
51155158
// Skip optional semicolon
51165159
if p.curTok.Type == TokenSemicolon {
51175160
p.nextToken()
@@ -5221,6 +5264,15 @@ func (p *Parser) parseAlterTableAlterColumnStatement(tableName *ast.SchemaObject
52215264
}
52225265
}
52235266

5267+
// Parse optional WITH clause for ONLINE option (for data type changes)
5268+
if p.curTok.Type == TokenWith {
5269+
opts, err := p.parseAlterColumnWithOptions()
5270+
if err != nil {
5271+
return nil, err
5272+
}
5273+
stmt.Options = opts
5274+
}
5275+
52245276
// Skip optional semicolon
52255277
if p.curTok.Type == TokenSemicolon {
52265278
p.nextToken()
@@ -5288,6 +5340,53 @@ func (p *Parser) parseColumnEncryptionSpecification() (*ast.ColumnEncryptionDefi
52885340
return encDef, nil
52895341
}
52905342

5343+
func (p *Parser) parseAlterColumnWithOptions() ([]ast.IndexOption, error) {
5344+
var options []ast.IndexOption
5345+
5346+
p.nextToken() // consume WITH
5347+
if p.curTok.Type != TokenLParen {
5348+
return nil, nil
5349+
}
5350+
p.nextToken() // consume (
5351+
5352+
for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
5353+
optName := strings.ToUpper(p.curTok.Literal)
5354+
p.nextToken() // consume option name
5355+
5356+
if p.curTok.Type == TokenEquals {
5357+
p.nextToken() // consume =
5358+
}
5359+
5360+
switch optName {
5361+
case "ONLINE":
5362+
opt := &ast.OnlineIndexOption{
5363+
OptionKind: "Online",
5364+
}
5365+
val := strings.ToUpper(p.curTok.Literal)
5366+
if val == "ON" {
5367+
opt.OptionState = "On"
5368+
} else if val == "OFF" {
5369+
opt.OptionState = "Off"
5370+
}
5371+
p.nextToken()
5372+
options = append(options, opt)
5373+
default:
5374+
// Skip unknown option value
5375+
p.nextToken()
5376+
}
5377+
5378+
if p.curTok.Type == TokenComma {
5379+
p.nextToken()
5380+
}
5381+
}
5382+
5383+
if p.curTok.Type == TokenRParen {
5384+
p.nextToken() // consume )
5385+
}
5386+
5387+
return options, nil
5388+
}
5389+
52915390
func (p *Parser) parseAlterTableAddStatement(tableName *ast.SchemaObjectName) (*ast.AlterTableAddTableElementStatement, error) {
52925391
// Consume ADD
52935392
p.nextToken()
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
{"todo": true}
1+
{
2+
"todo": true,
3+
"skip_reason": "UTF-16 encoded query.sql file"
4+
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
{"todo": true}
1+
{
2+
"todo": true,
3+
"skip_reason": "UTF-16 encoded query.sql file"
4+
}

0 commit comments

Comments
 (0)