From 7632c2978368f7eef744ee2f50b37cc27a939f2a Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 19 Aug 2026 00:26:37 +0530 Subject: [PATCH] Fix BACKUP_PRIORITY and GRANT/DENY CREATE ANY DATABASE for availability groups (#222) Two independent ALTER AVAILABILITY GROUP syntax gaps, both documented and valid T-SQL, failed to parse: 1. BACKUP_PRIORITY replica option In ADD REPLICA ON ... WITH (...) / MODIFY REPLICA ON ..., the literalReplicaOption rule only accepted an integer-valued option when it was SESSION_TIMEOUT, otherwise forcing a match on APPLY_DELAY. So BACKUP_PRIORITY = n produced "Expected APPLY_DELAY but encountered BACKUP_PRIORITY". Add a BackupPriority branch to the integer path, AvailabilityReplicaOptionKind.BackupPriority (appended), the BACKUP_PRIORITY keyword constant, and the option-helper mapping. Applied to all grammars that have the rule: TSql110 through TSql180 and TSqlFabricDW (SQL 2012+). 2. GRANT / DENY CREATE ANY DATABASE ALTER AVAILABILITY GROUP had no branch for this clause, so GRANT/CREATE/ANY all errored. Add the grammar branch plus two appended AlterAvailabilityGroupStatementType values (GrantCreateAnyDatabase, DenyCreateAnyDatabase) and the corresponding script-generator cases. Applied to TSql130 through TSql180 and TSqlFabricDW (SQL 2016+); earlier parsers correctly continue to reject it. Both changes are additive to the public AST (new appended enum members, no renumbering or retyping), so they are non-breaking for downstream consumers. Tests: - Positive round-trip: AlterAvailabilityGroupBackupPriorityTests.sql (110) and AlterAvailabilityGroupCreateAnyDatabaseTests130.sql (130), with baselines, wired through Only110SyntaxTests.cs / Only130SyntaxTests.cs. Error counts version-gate the syntax (BACKUP_PRIORITY rejected pre-110, GRANT/DENY CREATE ANY DATABASE rejected pre-130). - Negative: AlterAvailabilityGroupCreateAnyDatabaseNegativeTest in ParserErrorsTests.cs asserts only CREATE ANY DATABASE is accepted. --- .../TSql/AlterAvailabilityGroupStatementType.cs | 8 ++++++++ .../Parser/TSql/AvailabilityReplicaOptionKind.cs | 4 ++++ .../TSql/AvailabilityReplicaOptionsHelper.cs | 1 + .../Parser/TSql/CodeGenerationSupporter.cs | 1 + SqlScriptDom/Parser/TSql/TSql110.g | 4 ++++ SqlScriptDom/Parser/TSql/TSql120.g | 4 ++++ SqlScriptDom/Parser/TSql/TSql130.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSql140.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSql150.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSql160.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSql170.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSql180.g | 14 ++++++++++++++ SqlScriptDom/Parser/TSql/TSqlFabricDW.g | 14 ++++++++++++++ ...ratorVisitor.AlterAvailabilityGroupStatement.cs | 12 ++++++++++++ .../AlterAvailabilityGroupBackupPriorityTests.sql | 9 +++++++++ ...rAvailabilityGroupCreateAnyDatabaseTests130.sql | 5 +++++ Test/SqlDom/Only110SyntaxTests.cs | 1 + Test/SqlDom/Only130SyntaxTests.cs | 3 ++- Test/SqlDom/ParserErrorsTests.cs | 13 +++++++++++++ .../AlterAvailabilityGroupBackupPriorityTests.sql | 8 ++++++++ ...rAvailabilityGroupCreateAnyDatabaseTests130.sql | 5 +++++ 21 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 Test/SqlDom/Baselines110/AlterAvailabilityGroupBackupPriorityTests.sql create mode 100644 Test/SqlDom/Baselines130/AlterAvailabilityGroupCreateAnyDatabaseTests130.sql create mode 100644 Test/SqlDom/TestScripts/AlterAvailabilityGroupBackupPriorityTests.sql create mode 100644 Test/SqlDom/TestScripts/AlterAvailabilityGroupCreateAnyDatabaseTests130.sql diff --git a/SqlScriptDom/Parser/TSql/AlterAvailabilityGroupStatementType.cs b/SqlScriptDom/Parser/TSql/AlterAvailabilityGroupStatementType.cs index 6787ba02..aa77ba99 100644 --- a/SqlScriptDom/Parser/TSql/AlterAvailabilityGroupStatementType.cs +++ b/SqlScriptDom/Parser/TSql/AlterAvailabilityGroupStatementType.cs @@ -41,5 +41,13 @@ public enum AlterAvailabilityGroupStatementType /// Take an action /// Action = 6, + /// + /// Grant CREATE ANY DATABASE + /// + GrantCreateAnyDatabase = 7, + /// + /// Deny CREATE ANY DATABASE + /// + DenyCreateAnyDatabase = 8, } } diff --git a/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionKind.cs b/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionKind.cs index 3e181b44..7f88774c 100644 --- a/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionKind.cs +++ b/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionKind.cs @@ -41,6 +41,10 @@ public enum AvailabilityReplicaOptionKind /// Primary role /// PrimaryRole = 6, + /// + /// Backup priority + /// + BackupPriority = 7, } } diff --git a/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionsHelper.cs b/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionsHelper.cs index 9bfff922..bd9174b2 100644 --- a/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionsHelper.cs +++ b/SqlScriptDom/Parser/TSql/AvailabilityReplicaOptionsHelper.cs @@ -14,6 +14,7 @@ internal class AvailabilityReplicaOptionsHelper : OptionsHelper + /// Negative test for GitHub issue #222: ALTER AVAILABILITY GROUP ... GRANT/DENY only + /// accepts CREATE ANY DATABASE; any other permission phrase must be rejected. + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void AlterAvailabilityGroupCreateAnyDatabaseNegativeTest() + { + ParserTestUtils.ErrorTest130("ALTER AVAILABILITY GROUP [ag] GRANT CREATE ANY TABLE", + new ParserErrorInfo(47, "SQL46010", "TABLE")); + } + /// /// Negative tests for create table with generated always /// as user id/name start/end columns diff --git a/Test/SqlDom/TestScripts/AlterAvailabilityGroupBackupPriorityTests.sql b/Test/SqlDom/TestScripts/AlterAvailabilityGroupBackupPriorityTests.sql new file mode 100644 index 00000000..7a8a0cee --- /dev/null +++ b/Test/SqlDom/TestScripts/AlterAvailabilityGroupBackupPriorityTests.sql @@ -0,0 +1,8 @@ +-- Regression tests for GitHub issue #222: BACKUP_PRIORITY must be accepted as an integer-valued +-- replica option in ADD REPLICA ON / MODIFY REPLICA ON. +ALTER AVAILABILITY GROUP [SalesAG] ADD REPLICA ON 'node1' WITH (BACKUP_PRIORITY = 50) +GO +ALTER AVAILABILITY GROUP [SalesAG] ADD REPLICA ON 'node2' WITH (ENDPOINT_URL = 'TCP://node2:5022', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50) +GO +ALTER AVAILABILITY GROUP [SalesAG] MODIFY REPLICA ON 'node1' WITH (BACKUP_PRIORITY = 100) +GO diff --git a/Test/SqlDom/TestScripts/AlterAvailabilityGroupCreateAnyDatabaseTests130.sql b/Test/SqlDom/TestScripts/AlterAvailabilityGroupCreateAnyDatabaseTests130.sql new file mode 100644 index 00000000..276afd20 --- /dev/null +++ b/Test/SqlDom/TestScripts/AlterAvailabilityGroupCreateAnyDatabaseTests130.sql @@ -0,0 +1,5 @@ +-- Regression tests for GitHub issue #222: ALTER AVAILABILITY GROUP ... { GRANT | DENY } CREATE ANY DATABASE. +ALTER AVAILABILITY GROUP [SalesAG] GRANT CREATE ANY DATABASE +GO +ALTER AVAILABILITY GROUP [SalesAG] DENY CREATE ANY DATABASE +GO