@@ -2149,7 +2149,7 @@ func (p *Parser) parseAlterTableDropStatement(tableName *ast.SchemaObjectName) (
21492149 }
21502150
21512151 // Parse multiple elements separated by commas
2152- // Format: DROP [COLUMN] name, [CONSTRAINT] name, [INDEX] name , ...
2152+ // Format: DROP [COLUMN] name [WITH (options)] , [CONSTRAINT] name [WITH (options)] , ...
21532153 var currentElementType string = "NotSpecified"
21542154
21552155 for {
@@ -2179,6 +2179,16 @@ func (p *Parser) parseAlterTableDropStatement(tableName *ast.SchemaObjectName) (
21792179 Name : p .parseIdentifier (),
21802180 IsIfExists : false ,
21812181 }
2182+
2183+ // Check for WITH clause
2184+ if p .curTok .Type == TokenWith {
2185+ options , err := p .parseDropClusteredConstraintOptions ()
2186+ if err != nil {
2187+ return nil , err
2188+ }
2189+ element .DropClusteredConstraintOptions = options
2190+ }
2191+
21822192 stmt .AlterTableDropTableElements = append (stmt .AlterTableDropTableElements , element )
21832193
21842194 // After adding an element, reset type to NotSpecified for next element
@@ -2201,6 +2211,126 @@ func (p *Parser) parseAlterTableDropStatement(tableName *ast.SchemaObjectName) (
22012211 return stmt , nil
22022212}
22032213
2214+ func (p * Parser ) parseDropClusteredConstraintOptions () ([]ast.DropClusteredConstraintOption , error ) {
2215+ // Consume WITH
2216+ p .nextToken ()
2217+
2218+ if p .curTok .Type != TokenLParen {
2219+ return nil , fmt .Errorf ("expected ( after WITH, got %s" , p .curTok .Literal )
2220+ }
2221+ p .nextToken () // consume (
2222+
2223+ var options []ast.DropClusteredConstraintOption
2224+
2225+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
2226+ optionName := strings .ToUpper (p .curTok .Literal )
2227+
2228+ switch optionName {
2229+ case "ONLINE" :
2230+ p .nextToken () // consume ONLINE
2231+ if p .curTok .Type != TokenEquals {
2232+ return nil , fmt .Errorf ("expected = after ONLINE, got %s" , p .curTok .Literal )
2233+ }
2234+ p .nextToken () // consume =
2235+ state := strings .ToUpper (p .curTok .Literal )
2236+ var optionState string
2237+ if state == "ON" {
2238+ optionState = "On"
2239+ } else if state == "OFF" {
2240+ optionState = "Off"
2241+ } else {
2242+ return nil , fmt .Errorf ("expected ON or OFF after ONLINE =, got %s" , p .curTok .Literal )
2243+ }
2244+ p .nextToken () // consume ON/OFF
2245+ options = append (options , & ast.DropClusteredConstraintStateOption {
2246+ OptionKind : "Online" ,
2247+ OptionState : optionState ,
2248+ })
2249+
2250+ case "MOVE" :
2251+ p .nextToken () // consume MOVE
2252+ if strings .ToUpper (p .curTok .Literal ) != "TO" {
2253+ return nil , fmt .Errorf ("expected TO after MOVE, got %s" , p .curTok .Literal )
2254+ }
2255+ p .nextToken () // consume TO
2256+
2257+ fg , err := p .parseFileGroupOrPartitionScheme ()
2258+ if err != nil {
2259+ return nil , err
2260+ }
2261+ options = append (options , & ast.DropClusteredConstraintMoveOption {
2262+ OptionKind : "MoveTo" ,
2263+ OptionValue : fg ,
2264+ })
2265+
2266+ case "MAXDOP" :
2267+ p .nextToken () // consume MAXDOP
2268+ if p .curTok .Type != TokenEquals {
2269+ return nil , fmt .Errorf ("expected = after MAXDOP, got %s" , p .curTok .Literal )
2270+ }
2271+ p .nextToken () // consume =
2272+ if p .curTok .Type != TokenNumber {
2273+ return nil , fmt .Errorf ("expected number after MAXDOP =, got %s" , p .curTok .Literal )
2274+ }
2275+ options = append (options , & ast.DropClusteredConstraintValueOption {
2276+ OptionKind : "MaxDop" ,
2277+ OptionValue : & ast.IntegerLiteral {
2278+ LiteralType : "Integer" ,
2279+ Value : p .curTok .Literal ,
2280+ },
2281+ })
2282+ p .nextToken () // consume number
2283+
2284+ default :
2285+ return nil , fmt .Errorf ("unexpected option in DROP WITH clause: %s" , p .curTok .Literal )
2286+ }
2287+
2288+ // Check for comma or end of options
2289+ if p .curTok .Type == TokenComma {
2290+ p .nextToken () // consume comma
2291+ }
2292+ }
2293+
2294+ if p .curTok .Type != TokenRParen {
2295+ return nil , fmt .Errorf ("expected ) to close WITH options, got %s" , p .curTok .Literal )
2296+ }
2297+ p .nextToken () // consume )
2298+
2299+ return options , nil
2300+ }
2301+
2302+ func (p * Parser ) parseFileGroupOrPartitionScheme () (* ast.FileGroupOrPartitionScheme , error ) {
2303+ fg := & ast.FileGroupOrPartitionScheme {}
2304+
2305+ // Parse filegroup/partition scheme name (can be identifier or string literal)
2306+ iove , err := p .parseIdentifierOrValueExpression ()
2307+ if err != nil {
2308+ return nil , err
2309+ }
2310+ fg .Name = iove
2311+
2312+ // Check for partition scheme columns (column1, column2, ...)
2313+ if p .curTok .Type == TokenLParen {
2314+ p .nextToken () // consume (
2315+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
2316+ if p .curTok .Type != TokenIdent && p .curTok .Type != TokenLBracket {
2317+ return nil , fmt .Errorf ("expected column identifier in partition scheme, got %s" , p .curTok .Literal )
2318+ }
2319+ fg .PartitionSchemeColumns = append (fg .PartitionSchemeColumns , p .parseIdentifier ())
2320+
2321+ if p .curTok .Type == TokenComma {
2322+ p .nextToken () // consume comma
2323+ }
2324+ }
2325+ if p .curTok .Type != TokenRParen {
2326+ return nil , fmt .Errorf ("expected ) to close partition scheme columns, got %s" , p .curTok .Literal )
2327+ }
2328+ p .nextToken () // consume )
2329+ }
2330+
2331+ return fg , nil
2332+ }
2333+
22042334func (p * Parser ) parseAlterTableAlterIndexStatement (tableName * ast.SchemaObjectName ) (* ast.AlterTableAlterIndexStatement , error ) {
22052335 // Consume ALTER
22062336 p .nextToken ()
0 commit comments