@@ -12,6 +12,11 @@ import (
1212// jsonNode represents a generic JSON node from the AST JSON format.
1313type jsonNode map[string]any
1414
15+ // boolPtr returns a pointer to a bool value.
16+ func boolPtr(b bool) *bool {
17+ return &b
18+ }
19+
1520// MarshalScript marshals a Script to JSON in the expected format.
1621func MarshalScript(s *ast.Script) ([]byte, error) {
1722 node := scriptToJSON(s)
@@ -12038,6 +12043,26 @@ func (p *Parser) parseAlterIndexStatement() (*ast.AlterIndexStatement, error) {
1203812043 OptionKind: "IgnoreDupKey",
1203912044 OptionState: p.capitalizeFirst(strings.ToLower(valueUpper)),
1204012045 }
12046+ // Check for (SUPPRESS_MESSAGES = ON/OFF)
12047+ if p.curTok.Type == TokenLParen {
12048+ p.nextToken() // consume (
12049+ if strings.ToUpper(p.curTok.Literal) == "SUPPRESS_MESSAGES" {
12050+ p.nextToken() // consume SUPPRESS_MESSAGES
12051+ if p.curTok.Type == TokenEquals {
12052+ p.nextToken() // consume =
12053+ }
12054+ suppressVal := strings.ToUpper(p.curTok.Literal)
12055+ if suppressVal == "ON" {
12056+ opt.SuppressMessagesOption = boolPtr(true)
12057+ } else if suppressVal == "OFF" {
12058+ opt.SuppressMessagesOption = boolPtr(false)
12059+ }
12060+ p.nextToken()
12061+ }
12062+ if p.curTok.Type == TokenRParen {
12063+ p.nextToken() // consume )
12064+ }
12065+ }
1204112066 stmt.IndexOptions = append(stmt.IndexOptions, opt)
1204212067 } else {
1204312068 opt := &ast.IndexStateOption{
@@ -12109,13 +12134,80 @@ func (p *Parser) parseAlterIndexStatement() (*ast.AlterIndexStatement, error) {
1210912134 optionName := strings.ToUpper(p.curTok.Literal)
1211012135 p.nextToken()
1211112136
12112- if p.curTok.Type == TokenEquals {
12137+ // Handle WAIT_AT_LOW_PRIORITY (...) - no equals sign
12138+ if optionName == "WAIT_AT_LOW_PRIORITY" && p.curTok.Type == TokenLParen {
12139+ p.nextToken() // consume (
12140+ waitOpt := &ast.WaitAtLowPriorityOption{
12141+ OptionKind: "WaitAtLowPriority",
12142+ }
12143+ for p.curTok.Type != TokenRParen && p.curTok.Type != TokenEOF {
12144+ subOptName := strings.ToUpper(p.curTok.Literal)
12145+ if subOptName == "MAX_DURATION" {
12146+ p.nextToken() // consume MAX_DURATION
12147+ if p.curTok.Type == TokenEquals {
12148+ p.nextToken() // consume =
12149+ }
12150+ durVal, _ := p.parsePrimaryExpression()
12151+ unit := ""
12152+ if strings.ToUpper(p.curTok.Literal) == "MINUTES" {
12153+ unit = "Minutes"
12154+ p.nextToken()
12155+ }
12156+ waitOpt.Options = append(waitOpt.Options, &ast.LowPriorityLockWaitMaxDurationOption{
12157+ MaxDuration: durVal,
12158+ Unit: unit,
12159+ OptionKind: "MaxDuration",
12160+ })
12161+ } else if subOptName == "ABORT_AFTER_WAIT" {
12162+ p.nextToken() // consume ABORT_AFTER_WAIT
12163+ if p.curTok.Type == TokenEquals {
12164+ p.nextToken() // consume =
12165+ }
12166+ abortType := "None"
12167+ switch strings.ToUpper(p.curTok.Literal) {
12168+ case "NONE":
12169+ abortType = "None"
12170+ case "SELF":
12171+ abortType = "Self"
12172+ case "BLOCKERS":
12173+ abortType = "Blockers"
12174+ }
12175+ p.nextToken()
12176+ waitOpt.Options = append(waitOpt.Options, &ast.LowPriorityLockWaitAbortAfterWaitOption{
12177+ AbortAfterWait: abortType,
12178+ OptionKind: "AbortAfterWait",
12179+ })
12180+ } else {
12181+ break
12182+ }
12183+ if p.curTok.Type == TokenComma {
12184+ p.nextToken()
12185+ }
12186+ }
12187+ if p.curTok.Type == TokenRParen {
12188+ p.nextToken() // consume )
12189+ }
12190+ stmt.IndexOptions = append(stmt.IndexOptions, waitOpt)
12191+ } else if p.curTok.Type == TokenEquals {
1211312192 p.nextToken()
1211412193 valueStr := strings.ToUpper(p.curTok.Literal)
1211512194 p.nextToken()
1211612195
12117- // Determine if it's a state option (ON/OFF) or expression option
12118- if valueStr == "ON" || valueStr == "OFF" {
12196+ // Handle MAX_DURATION = value [MINUTES] as top-level option
12197+ if optionName == "MAX_DURATION" {
12198+ unit := ""
12199+ if strings.ToUpper(p.curTok.Literal) == "MINUTES" {
12200+ unit = "Minutes"
12201+ p.nextToken()
12202+ }
12203+ opt := &ast.MaxDurationOption{
12204+ MaxDuration: &ast.IntegerLiteral{LiteralType: "Integer", Value: valueStr},
12205+ Unit: unit,
12206+ OptionKind: "MaxDuration",
12207+ }
12208+ stmt.IndexOptions = append(stmt.IndexOptions, opt)
12209+ } else if valueStr == "ON" || valueStr == "OFF" {
12210+ // Determine if it's a state option (ON/OFF) or expression option
1211912211 if optionName == "IGNORE_DUP_KEY" {
1212012212 opt := &ast.IgnoreDupKeyIndexOption{
1212112213 OptionKind: "IgnoreDupKey",
@@ -14646,6 +14738,19 @@ func indexOptionToJSON(opt ast.IndexOption) jsonNode {
1464614738 node["PartitionRanges"] = ranges
1464714739 }
1464814740 return node
14741+ case *ast.WaitAtLowPriorityOption:
14742+ node := jsonNode{
14743+ "$type": "WaitAtLowPriorityOption",
14744+ "OptionKind": o.OptionKind,
14745+ }
14746+ if len(o.Options) > 0 {
14747+ options := make([]jsonNode, len(o.Options))
14748+ for i, opt := range o.Options {
14749+ options[i] = lowPriorityLockWaitOptionToJSON(opt)
14750+ }
14751+ node["Options"] = options
14752+ }
14753+ return node
1464914754 default:
1465014755 return jsonNode{"$type": "UnknownIndexOption"}
1465114756 }
0 commit comments