@@ -2056,9 +2056,13 @@ func (p *Parser) parseDropServiceStatement() (*ast.DropServiceStatement, error)
20562056 return stmt , nil
20572057}
20582058
2059- func (p * Parser ) parseDropEventNotificationStatement () (* ast.DropEventNotificationStatement , error ) {
2059+ func (p * Parser ) parseDropEventNotificationStatement () (ast.Statement , error ) {
20602060 // Consume EVENT
20612061 p .nextToken ()
2062+ // Check if this is DROP EVENT SESSION or DROP EVENT NOTIFICATION
2063+ if strings .ToUpper (p .curTok .Literal ) == "SESSION" {
2064+ return p .parseDropEventSessionStatement ()
2065+ }
20622066 // Consume NOTIFICATION
20632067 if strings .ToUpper (p .curTok .Literal ) == "NOTIFICATION" {
20642068 p .nextToken ()
@@ -2107,6 +2111,44 @@ func (p *Parser) parseDropEventNotificationStatement() (*ast.DropEventNotificati
21072111 return stmt , nil
21082112}
21092113
2114+ func (p * Parser ) parseDropEventSessionStatement () (* ast.DropEventSessionStatement , error ) {
2115+ // Consume SESSION
2116+ p .nextToken ()
2117+
2118+ stmt := & ast.DropEventSessionStatement {}
2119+
2120+ // Check for IF EXISTS
2121+ if strings .ToUpper (p .curTok .Literal ) == "IF" {
2122+ p .nextToken ()
2123+ if strings .ToUpper (p .curTok .Literal ) == "EXISTS" {
2124+ stmt .IsIfExists = true
2125+ p .nextToken ()
2126+ }
2127+ }
2128+
2129+ // Parse session name
2130+ stmt .Name = p .parseIdentifier ()
2131+
2132+ // ON SERVER/DATABASE
2133+ if p .curTok .Type == TokenOn {
2134+ p .nextToken ()
2135+ scopeUpper := strings .ToUpper (p .curTok .Literal )
2136+ if scopeUpper == "SERVER" {
2137+ stmt .SessionScope = "Server"
2138+ p .nextToken ()
2139+ } else if scopeUpper == "DATABASE" {
2140+ stmt .SessionScope = "Database"
2141+ p .nextToken ()
2142+ }
2143+ }
2144+
2145+ if p .curTok .Type == TokenSemicolon {
2146+ p .nextToken ()
2147+ }
2148+
2149+ return stmt , nil
2150+ }
2151+
21102152func (p * Parser ) parseAlterStatement () (ast.Statement , error ) {
21112153 // Consume ALTER
21122154 p .nextToken ()
@@ -2204,6 +2246,8 @@ func (p *Parser) parseAlterStatement() (ast.Statement, error) {
22042246 return p .parseAlterAvailabilityGroupStatement ()
22052247 case "MATERIALIZED" :
22062248 return p .parseAlterMaterializedViewStatement ()
2249+ case "EVENT" :
2250+ return p .parseAlterEventSessionStatement ()
22072251 }
22082252 return nil , fmt .Errorf ("unexpected token after ALTER: %s" , p .curTok .Literal )
22092253 default :
@@ -11575,3 +11619,128 @@ func (p *Parser) parseAvailabilityReplicasServerOnly() []*ast.AvailabilityReplic
1157511619 }
1157611620 return replicas
1157711621}
11622+
11623+ func (p * Parser ) parseAlterEventSessionStatement () (* ast.AlterEventSessionStatement , error ) {
11624+ p .nextToken () // consume EVENT
11625+ if strings .ToUpper (p .curTok .Literal ) != "SESSION" {
11626+ return nil , fmt .Errorf ("expected SESSION after EVENT, got %s" , p .curTok .Literal )
11627+ }
11628+ p .nextToken () // consume SESSION
11629+
11630+ stmt := & ast.AlterEventSessionStatement {
11631+ Name : p .parseIdentifier (),
11632+ }
11633+
11634+ // ON SERVER/DATABASE
11635+ if p .curTok .Type == TokenOn {
11636+ p .nextToken ()
11637+ scopeUpper := strings .ToUpper (p .curTok .Literal )
11638+ if scopeUpper == "SERVER" {
11639+ stmt .SessionScope = "Server"
11640+ p .nextToken ()
11641+ } else if scopeUpper == "DATABASE" {
11642+ stmt .SessionScope = "Database"
11643+ p .nextToken ()
11644+ }
11645+ }
11646+
11647+ // Parse action: ADD/DROP EVENT/TARGET, WITH, STATE
11648+ // Note: Don't use isStatementTerminator here because DROP is a statement terminator
11649+ // but we need to handle DROP EVENT/TARGET inside ALTER EVENT SESSION
11650+ for p .curTok .Type != TokenSemicolon && p .curTok .Type != TokenEOF {
11651+ // Check for GO batch separator
11652+ if p .curTok .Type == TokenIdent && strings .ToUpper (p .curTok .Literal ) == "GO" {
11653+ break
11654+ }
11655+ // Check for other statement starters that would indicate end of this statement
11656+ switch p .curTok .Type {
11657+ case TokenSelect , TokenInsert , TokenUpdate , TokenDelete , TokenDeclare ,
11658+ TokenIf , TokenWhile , TokenBegin , TokenEnd , TokenCreate , TokenAlter ,
11659+ TokenExec , TokenExecute , TokenPrint , TokenThrow :
11660+ // These tokens indicate start of a new statement
11661+ goto done
11662+ }
11663+ upperLit := strings .ToUpper (p .curTok .Literal )
11664+
11665+ if upperLit == "ADD" || p .curTok .Type == TokenAdd {
11666+ p .nextToken ()
11667+ addType := strings .ToUpper (p .curTok .Literal )
11668+ p .nextToken ()
11669+
11670+ if addType == "EVENT" {
11671+ if stmt .StatementType == "" {
11672+ stmt .StatementType = "AddEventDeclarationOptionalSessionOptions"
11673+ }
11674+ event := p .parseEventDeclaration ()
11675+ stmt .EventDeclarations = append (stmt .EventDeclarations , event )
11676+ } else if addType == "TARGET" {
11677+ if stmt .StatementType == "" {
11678+ stmt .StatementType = "AddTargetDeclarationOptionalSessionOptions"
11679+ }
11680+ target := p .parseTargetDeclaration ()
11681+ stmt .TargetDeclarations = append (stmt .TargetDeclarations , target )
11682+ }
11683+ } else if upperLit == "DROP" || p .curTok .Type == TokenDrop {
11684+ p .nextToken ()
11685+ dropType := strings .ToUpper (p .curTok .Literal )
11686+ p .nextToken ()
11687+
11688+ if dropType == "EVENT" {
11689+ if stmt .StatementType == "" {
11690+ stmt .StatementType = "DropEventSpecificationOptionalSessionOptions"
11691+ }
11692+ objName := p .parseEventSessionObjectName ()
11693+ stmt .DropEventDeclarations = append (stmt .DropEventDeclarations , objName )
11694+ } else if dropType == "TARGET" {
11695+ if stmt .StatementType == "" {
11696+ stmt .StatementType = "DropTargetSpecificationOptionalSessionOptions"
11697+ }
11698+ objName := p .parseEventSessionObjectName ()
11699+ stmt .DropTargetDeclarations = append (stmt .DropTargetDeclarations , objName )
11700+ }
11701+ } else if upperLit == "WITH" || p .curTok .Type == TokenWith {
11702+ p .nextToken ()
11703+ if p .curTok .Type == TokenLParen {
11704+ p .nextToken ()
11705+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
11706+ opt := p .parseSessionOption ()
11707+ if opt != nil {
11708+ stmt .SessionOptions = append (stmt .SessionOptions , opt )
11709+ }
11710+ if p .curTok .Type == TokenComma {
11711+ p .nextToken ()
11712+ } else {
11713+ break
11714+ }
11715+ }
11716+ if p .curTok .Type == TokenRParen {
11717+ p .nextToken ()
11718+ }
11719+ }
11720+ if stmt .StatementType == "" {
11721+ stmt .StatementType = "RequiredSessionOptions"
11722+ }
11723+ } else if upperLit == "STATE" {
11724+ p .nextToken () // consume STATE
11725+ if p .curTok .Type == TokenEquals {
11726+ p .nextToken () // consume =
11727+ }
11728+ stateVal := strings .ToUpper (p .curTok .Literal )
11729+ if stateVal == "START" {
11730+ stmt .StatementType = "AlterStateIsStart"
11731+ } else if stateVal == "STOP" {
11732+ stmt .StatementType = "AlterStateIsStop"
11733+ }
11734+ p .nextToken ()
11735+ } else if p .curTok .Type == TokenComma {
11736+ p .nextToken ()
11737+ } else {
11738+ p .nextToken ()
11739+ }
11740+ }
11741+ done:
11742+ if p .curTok .Type == TokenSemicolon {
11743+ p .nextToken ()
11744+ }
11745+ return stmt , nil
11746+ }
0 commit comments