@@ -4263,6 +4263,12 @@ func (p *Parser) parseCreateTableStatement() (*ast.CreateTableStatement, error)
42634263 OptionKind : "Durability" ,
42644264 DurabilityTableOptionKind : durabilityKind ,
42654265 })
4266+ } else if optionName == "REMOTE_DATA_ARCHIVE" {
4267+ opt , err := p .parseRemoteDataArchiveTableOption (false )
4268+ if err != nil {
4269+ return nil , err
4270+ }
4271+ stmt .Options = append (stmt .Options , opt )
42664272 } else {
42674273 // Skip unknown option value
42684274 if p .curTok .Type == TokenEquals {
@@ -4511,6 +4517,12 @@ func (p *Parser) parseCreateTableOptions(stmt *ast.CreateTableStatement) (*ast.C
45114517 OptionKind : "FileTableFullPathUniqueConstraintName" ,
45124518 Value : constraintName ,
45134519 })
4520+ } else if optionName == "REMOTE_DATA_ARCHIVE" {
4521+ opt , err := p .parseRemoteDataArchiveTableOption (false )
4522+ if err != nil {
4523+ return nil , err
4524+ }
4525+ stmt .Options = append (stmt .Options , opt )
45144526 } else {
45154527 // Skip unknown option value
45164528 if p .curTok .Type == TokenEquals {
@@ -4540,6 +4552,101 @@ func (p *Parser) parseCreateTableOptions(stmt *ast.CreateTableStatement) (*ast.C
45404552 return stmt , nil
45414553}
45424554
4555+ // parseRemoteDataArchiveTableOption parses REMOTE_DATA_ARCHIVE = ON/OFF (options...) for tables
4556+ // isAlterTable indicates if this is for ALTER TABLE SET (which uses RemoteDataArchiveAlterTableOption)
4557+ func (p * Parser ) parseRemoteDataArchiveTableOption (isAlterTable bool ) (ast.TableOption , error ) {
4558+ // curTok should be = or (
4559+ if p .curTok .Type == TokenEquals {
4560+ p .nextToken () // consume =
4561+ }
4562+
4563+ // Parse ON, OFF, or OFF_WITHOUT_DATA_RECOVERY
4564+ rdaOption := "Enable"
4565+ stateUpper := strings .ToUpper (p .curTok .Literal )
4566+ if stateUpper == "ON" {
4567+ rdaOption = "Enable"
4568+ p .nextToken ()
4569+ } else if stateUpper == "OFF" {
4570+ rdaOption = "Disable"
4571+ p .nextToken ()
4572+ } else if stateUpper == "OFF_WITHOUT_DATA_RECOVERY" {
4573+ rdaOption = "OffWithoutDataRecovery"
4574+ p .nextToken ()
4575+ }
4576+
4577+ var migrationState string
4578+ var filterPredicate ast.ScalarExpression
4579+ isMigrationStateSpecified := false
4580+ isFilterPredicateSpecified := false
4581+
4582+ // Parse options in parentheses
4583+ if p .curTok .Type == TokenLParen {
4584+ p .nextToken () // consume (
4585+
4586+ for p .curTok .Type != TokenRParen && p .curTok .Type != TokenEOF {
4587+ optName := strings .ToUpper (p .curTok .Literal )
4588+ p .nextToken () // consume option name
4589+
4590+ if p .curTok .Type == TokenEquals {
4591+ p .nextToken () // consume =
4592+ }
4593+
4594+ switch optName {
4595+ case "MIGRATION_STATE" :
4596+ isMigrationStateSpecified = true
4597+ msUpper := strings .ToUpper (p .curTok .Literal )
4598+ if msUpper == "PAUSED" {
4599+ migrationState = "Paused"
4600+ } else if msUpper == "OUTBOUND" {
4601+ migrationState = "Outbound"
4602+ } else if msUpper == "INBOUND" {
4603+ migrationState = "Inbound"
4604+ }
4605+ p .nextToken ()
4606+ case "FILTER_PREDICATE" :
4607+ isFilterPredicateSpecified = true
4608+ if strings .ToUpper (p .curTok .Literal ) == "NULL" {
4609+ // When FILTER_PREDICATE = NULL, filterPredicate stays nil
4610+ p .nextToken ()
4611+ } else {
4612+ // Parse function call like dbo.f1(c1)
4613+ expr , err := p .parseScalarExpression ()
4614+ if err != nil {
4615+ return nil , err
4616+ }
4617+ filterPredicate = expr
4618+ }
4619+ }
4620+
4621+ if p .curTok .Type == TokenComma {
4622+ p .nextToken ()
4623+ }
4624+ }
4625+
4626+ if p .curTok .Type == TokenRParen {
4627+ p .nextToken () // consume )
4628+ }
4629+ }
4630+
4631+ if isAlterTable {
4632+ return & ast.RemoteDataArchiveAlterTableOption {
4633+ RdaTableOption : rdaOption ,
4634+ MigrationState : migrationState ,
4635+ IsMigrationStateSpecified : isMigrationStateSpecified ,
4636+ FilterPredicate : filterPredicate ,
4637+ IsFilterPredicateSpecified : isFilterPredicateSpecified ,
4638+ OptionKind : "RemoteDataArchive" ,
4639+ }, nil
4640+ }
4641+
4642+ return & ast.RemoteDataArchiveTableOption {
4643+ RdaTableOption : rdaOption ,
4644+ MigrationState : migrationState ,
4645+ FilterPredicate : filterPredicate ,
4646+ OptionKind : "RemoteDataArchive" ,
4647+ }, nil
4648+ }
4649+
45434650// parseMergeStatement parses a MERGE statement
45444651func (p * Parser ) parseMergeStatement () (* ast.MergeStatement , error ) {
45454652 // Consume MERGE
@@ -6926,6 +7033,30 @@ func tableOptionToJSON(opt ast.TableOption) jsonNode {
69267033 node ["Value" ] = identifierOrValueExpressionToJSON (o .Value )
69277034 }
69287035 return node
7036+ case * ast.RemoteDataArchiveTableOption :
7037+ node := jsonNode {
7038+ "$type" : "RemoteDataArchiveTableOption" ,
7039+ "RdaTableOption" : o .RdaTableOption ,
7040+ "MigrationState" : o .MigrationState ,
7041+ "OptionKind" : o .OptionKind ,
7042+ }
7043+ if o .FilterPredicate != nil {
7044+ node ["FilterPredicate" ] = scalarExpressionToJSON (o .FilterPredicate )
7045+ }
7046+ return node
7047+ case * ast.RemoteDataArchiveAlterTableOption :
7048+ node := jsonNode {
7049+ "$type" : "RemoteDataArchiveAlterTableOption" ,
7050+ "RdaTableOption" : o .RdaTableOption ,
7051+ "MigrationState" : o .MigrationState ,
7052+ "IsMigrationStateSpecified" : o .IsMigrationStateSpecified ,
7053+ "IsFilterPredicateSpecified" : o .IsFilterPredicateSpecified ,
7054+ "OptionKind" : o .OptionKind ,
7055+ }
7056+ if o .FilterPredicate != nil {
7057+ node ["FilterPredicate" ] = scalarExpressionToJSON (o .FilterPredicate )
7058+ }
7059+ return node
69297060 default :
69307061 return jsonNode {"$type" : "UnknownTableOption" }
69317062 }
0 commit comments