From aabff8dd030f61031822db2cce86f34a30e04eeb Mon Sep 17 00:00:00 2001 From: Mohit Agarwal Date: Wed, 11 Jun 2025 19:32:48 +0000 Subject: [PATCH 1/5] Merged PR 1696252: Changes to support Manual-cutover and Perform-cutover in ScriptDOM ## Description The changes are done to support new parameters in TSQL ALTER DATABASE command to add new parameters MANUAL_CUTOVER and PERFORM_CUTOVER. **Functional spec** of feature FMv2: https://microsoft-my.sharepoint-df.com/:w:/p/blakhani/ERKCMOUx59ZIjfSJ_eIyLfQB--YQbcRDPoSNiiUtWvS1bg?e=vWg0vP **Design doc** of feature FMv2: https://microsoft.sharepoint.com/:w:/t/sqlstormr/Eb0o3p3MNB1CmdS7NByqHkQB11bGrU9PNVg5GE98Z6yhhg?e=reyHi3 ## Code Change - [X] The [Common checklist](https://msdata.visualstudio.com/SQLToolsAndLibraries/_git/Common?path=/Templates/PR%20Checklist%20for%20SQLToolsAndLibraries.md&version=GBmain&_a=preview) has been reviewed and followed - [X] Code changes are accompanied by appropriate unit tests - [X] Identified and included SMEs needed to review code changes - [X] Follow the [steps](https://msdata.visualstudio.com/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki/33838/Adding-or-Extending-TSql-support-in-Sql-Dom?anchor=make-the-changes-in) here to make changes in the code ## Testing - [X] Follow the [steps](https://msdata.visualstudio.com/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki/33838/Adding-or-Extending-TSql-support-in-Sql-Dom?anchor=to-extend-the-tests-do-the-following%3A) here to add new tests for your feature Newly added tests are passing successfully: ![image.png](https://msdata.visualstudio.com/c6789c20-b819-4bfd-9917-11471655156e/_apis/git/repositories/2247f543-55d8-45df-a9fe-23820ae656af/pullRequests/1696252/attachments/image.png) Ran all tests which are passing successfully: ![image.png](https://msdata.visualstudio.com/c6789c20-b819-4bfd-9917-11471655156e/_apis/git/repositories/2247f543-55d8-45df-a9fe-23820ae656af/pullRequests/1696252/attachments/image.png) ## Documentation - [ ] Update relevant documentation in the [wiki](https://dev.azure.com/msdata/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki) and the README.md file ## Additional Information Please provide any additional information that might be helpful for the reviewers ---- #### AI description (iteration 1) #### PR Classification New feature implementation to support manual and perform cutover options in ScriptDOM. #### PR Summary This pull request extends ScriptDOM to accommodate the MANUAL_CUTOVER and PERFORM_CUTOVER options as required for the Forward Migration v2 feature. The enhancements include grammar updates, AST modifications, option kind extensions, code generation adjustments, and new SQL tests. - **`TSql170.g`**: Added production rules for `alterDbManualCutover` and `alterDbPerformCutover` to parse the new options. - **`Ast.xml`**: Introduced new classes (`ManualCutoverDatabaseOption` and `PerformCutoverDatabaseOption`) to represent the cutover options. - **`DatabaseOptionKind.cs` & Helpers**: Extended the enum and updated mappings in `DatabaseOptionKindHelper.cs` and `OnOffSimpleDbOptionsHelper.cs` with the new option kinds. - **`CodeGenerationSupporter.cs` & `SqlVersionFlags.cs`**: Incorporate... --- SqlScriptDom/Parser/TSql/Ast.xml | 4 ++++ .../Parser/TSql/CodeGenerationSupporter.cs | 2 ++ .../Parser/TSql/DatabaseOptionKind.cs | 5 ++++- .../Parser/TSql/DatabaseOptionKindHelper.cs | 4 ++++ SqlScriptDom/Parser/TSql/SqlVersionFlags.cs | 1 + SqlScriptDom/Parser/TSql/TSql170.g | 20 ++++++++++++++++++ ...rVisitor.AlterDbPerformCutoverStatement.cs | 21 +++++++++++++++++++ ...iptGeneratorVisitor.AlterDbSetStatement.cs | 13 ++++++++++-- .../AlterDatabaseManualCutoverTests170.sql | 10 +++++++++ Test/SqlDom/Only170SyntaxTests.cs | 3 ++- .../AlterDatabaseManualCutoverTests170.sql | 10 +++++++++ 11 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbPerformCutoverStatement.cs create mode 100644 Test/SqlDom/Baselines170/AlterDatabaseManualCutoverTests170.sql create mode 100644 Test/SqlDom/TestScripts/AlterDatabaseManualCutoverTests170.sql diff --git a/SqlScriptDom/Parser/TSql/Ast.xml b/SqlScriptDom/Parser/TSql/Ast.xml index d02bc3b..ffeec7c 100644 --- a/SqlScriptDom/Parser/TSql/Ast.xml +++ b/SqlScriptDom/Parser/TSql/Ast.xml @@ -2404,6 +2404,7 @@ + @@ -2576,6 +2577,9 @@ + + + diff --git a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs index daa8b35..7c00dbe 100644 --- a/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs +++ b/SqlScriptDom/Parser/TSql/CodeGenerationSupporter.cs @@ -564,6 +564,7 @@ internal static class CodeGenerationSupporter internal const string LSquareParen = "["; internal const string MaintainIndex = "MAINTAIN_INDEX"; internal const string Manual = "MANUAL"; + internal const string ManualCutover = "MANUAL_CUTOVER"; internal const string Mark = "MARK"; internal const string MarkInUseForRemoval = "MARK_IN_USE_FOR_REMOVAL"; internal const string Masked = "MASKED"; @@ -728,6 +729,7 @@ internal static class CodeGenerationSupporter internal const string Paused = "PAUSED"; internal const string Percentage = "PERCENTAGE"; internal const string PerCpu = "PER_CPU"; + internal const string PerformCutover = "PERFORM_CUTOVER"; internal const string Period = "PERIOD"; internal const string PermissionSet = "PERMISSION_SET"; internal const string PerNode = "PER_NODE"; diff --git a/SqlScriptDom/Parser/TSql/DatabaseOptionKind.cs b/SqlScriptDom/Parser/TSql/DatabaseOptionKind.cs index 2cdeec3..c3118e2 100644 --- a/SqlScriptDom/Parser/TSql/DatabaseOptionKind.cs +++ b/SqlScriptDom/Parser/TSql/DatabaseOptionKind.cs @@ -95,7 +95,10 @@ public enum DatabaseOptionKind // T-SQL 150 On/Off options DataRetention = 67, - Ledger = 68 + Ledger = 68, + + ManualCutover = 69, + PerformCutover = 70 } #pragma warning restore 1591 diff --git a/SqlScriptDom/Parser/TSql/DatabaseOptionKindHelper.cs b/SqlScriptDom/Parser/TSql/DatabaseOptionKindHelper.cs index 612f3b0..c46471b 100644 --- a/SqlScriptDom/Parser/TSql/DatabaseOptionKindHelper.cs +++ b/SqlScriptDom/Parser/TSql/DatabaseOptionKindHelper.cs @@ -32,6 +32,10 @@ private DatabaseOptionKindHelper() // 140 Options AddOptionMapping(DatabaseOptionKind.AutomaticTuning, CodeGenerationSupporter.AutomaticTuning, SqlVersionFlags.TSql140AndAbove); + + // 170 Options + AddOptionMapping(DatabaseOptionKind.ManualCutover, CodeGenerationSupporter.ManualCutover, SqlVersionFlags.TSql170AndAbove); + AddOptionMapping(DatabaseOptionKind.PerformCutover, CodeGenerationSupporter.PerformCutover, SqlVersionFlags.TSql170AndAbove); } internal static readonly DatabaseOptionKindHelper Instance = new DatabaseOptionKindHelper(); diff --git a/SqlScriptDom/Parser/TSql/SqlVersionFlags.cs b/SqlScriptDom/Parser/TSql/SqlVersionFlags.cs index 522413d..23bb379 100644 --- a/SqlScriptDom/Parser/TSql/SqlVersionFlags.cs +++ b/SqlScriptDom/Parser/TSql/SqlVersionFlags.cs @@ -35,6 +35,7 @@ internal enum SqlVersionFlags TSql140AndAbove = TSql140 | TSql150 | TSql160 | TSqlFabricDW | TSql170, TSql150AndAbove = TSql150 | TSql160 | TSqlFabricDW | TSql170, TSql160AndAbove = TSql160 | TSqlFabricDW | TSql170, + TSql170AndAbove = TSql170, TSqlFabricDWAndAbove = TSql160 | TSqlFabricDW | TSql170, TSqlUnder110 = TSql80 | TSql90 | TSql100, TSqlUnder120 = TSql80 | TSql90 | TSql100 | TSql110, diff --git a/SqlScriptDom/Parser/TSql/TSql170.g b/SqlScriptDom/Parser/TSql/TSql170.g index 367fc11..b5b4a2b 100644 --- a/SqlScriptDom/Parser/TSql/TSql170.g +++ b/SqlScriptDom/Parser/TSql/TSql170.g @@ -2896,6 +2896,7 @@ alterDatabase [IToken tAlter] returns [AlterDatabaseStatement vResult = null] | vResult = alterDbSet | vResult = alterDbCollate | vResult = alterDbRebuild // Undocumented - for PSS only + | vResult = alterDbPerformCutover ) { if(vUseCurrent) @@ -3057,8 +3058,19 @@ alterDbModify returns [AlterDatabaseStatement vResult = null] ; alterDbModifyAzureOptions returns [AlterDatabaseSetStatement vResult = FragmentFactory.CreateFragment()] +{ + bool hasManualCutover = false; +} : azureOptions[vResult, vResult.Options] + ( + With tManualCutover:Identifier + { + Match(tManualCutover, CodeGenerationSupporter.ManualCutover); + hasManualCutover = true; + vResult.WithManualCutover = true; + } + )? ; // MODIFY File syntax @@ -3143,6 +3155,14 @@ toFilegroup returns [Identifier vResult] } ; +alterDbPerformCutover returns [AlterDatabasePerformCutoverStatement vResult = FragmentFactory.CreateFragment()] + : tPerformCutover:Identifier + { + Match(tPerformCutover, CodeGenerationSupporter.PerformCutover); + UpdateTokenInfo(vResult, tPerformCutover); + } + ; + xactTermination returns [AlterDatabaseTermination vResult = FragmentFactory.CreateFragment()] { Literal vInteger; diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbPerformCutoverStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbPerformCutoverStatement.cs new file mode 100644 index 0000000..e8b6393 --- /dev/null +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbPerformCutoverStatement.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//------------------------------------------------------------------------------ +using System; + +using Microsoft.SqlServer.TransactSql.ScriptDom; + +namespace Microsoft.SqlServer.TransactSql.ScriptDom.ScriptGenerator +{ + partial class SqlScriptGeneratorVisitor + { + public override void ExplicitVisit(AlterDatabasePerformCutoverStatement node) + { + GenerateAlterDbStatementHead(node); + + GenerateSpaceAndIdentifier(CodeGenerationSupporter.PerformCutover); + } + } +} diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbSetStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbSetStatement.cs index 6ca6ef8..08499f9 100644 --- a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbSetStatement.cs +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.AlterDbSetStatement.cs @@ -15,9 +15,11 @@ public override void ExplicitVisit(AlterDatabaseSetStatement node) NewLineAndIndent(); bool azureOnlyOption = true; - foreach(DatabaseOption option in node.Options) + foreach (DatabaseOption option in node.Options) { - if (option.OptionKind != DatabaseOptionKind.MaxSize && option.OptionKind != DatabaseOptionKind.Edition && option.OptionKind != DatabaseOptionKind.ServiceObjective) + if (option.OptionKind != DatabaseOptionKind.MaxSize && + option.OptionKind != DatabaseOptionKind.Edition && + option.OptionKind != DatabaseOptionKind.ServiceObjective) { azureOnlyOption = false; break; @@ -31,6 +33,13 @@ public override void ExplicitVisit(AlterDatabaseSetStatement node) MarkAndPushAlignmentPoint(items); GenerateParenthesisedCommaSeparatedList(node.Options, true); PopAlignmentPoint(); + + // Emit "WITH MANUAL_CUTOVER" if the statement includes the optional manual cutover clause + if (node.WithManualCutover) + { + GenerateSpaceAndKeyword(TSqlTokenType.With); + GenerateSpaceAndIdentifier(CodeGenerationSupporter.ManualCutover); + } } else { diff --git a/Test/SqlDom/Baselines170/AlterDatabaseManualCutoverTests170.sql b/Test/SqlDom/Baselines170/AlterDatabaseManualCutoverTests170.sql new file mode 100644 index 0000000..71a106f --- /dev/null +++ b/Test/SqlDom/Baselines170/AlterDatabaseManualCutoverTests170.sql @@ -0,0 +1,10 @@ +ALTER DATABASE db + MODIFY (SERVICE_OBJECTIVE = 'HS_Gen5_16') WITH MANUAL_CUTOVER; + +ALTER DATABASE db + MODIFY (EDITION = 'Hyperscale') WITH MANUAL_CUTOVER; + +ALTER DATABASE db + MODIFY (SERVICE_OBJECTIVE = ELASTIC_POOL (NAME = [hspool])) WITH MANUAL_CUTOVER; + +ALTER DATABASE db PERFORM_CUTOVER; diff --git a/Test/SqlDom/Only170SyntaxTests.cs b/Test/SqlDom/Only170SyntaxTests.cs index 4b352d5..49eb9bd 100644 --- a/Test/SqlDom/Only170SyntaxTests.cs +++ b/Test/SqlDom/Only170SyntaxTests.cs @@ -9,7 +9,8 @@ public partial class SqlDomTests // Note: These filenames are case sensitive, make sure they match the checked-in file exactly private static readonly ParserTest[] Only170TestInfos = { - new ParserTest170("RegexpTVFTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0) + new ParserTest170("RegexpTVFTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0), + new ParserTest170("AlterDatabaseManualCutoverTests170.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4) }; private static readonly ParserTest[] SqlAzure170_TestInfos = diff --git a/Test/SqlDom/TestScripts/AlterDatabaseManualCutoverTests170.sql b/Test/SqlDom/TestScripts/AlterDatabaseManualCutoverTests170.sql new file mode 100644 index 0000000..71a106f --- /dev/null +++ b/Test/SqlDom/TestScripts/AlterDatabaseManualCutoverTests170.sql @@ -0,0 +1,10 @@ +ALTER DATABASE db + MODIFY (SERVICE_OBJECTIVE = 'HS_Gen5_16') WITH MANUAL_CUTOVER; + +ALTER DATABASE db + MODIFY (EDITION = 'Hyperscale') WITH MANUAL_CUTOVER; + +ALTER DATABASE db + MODIFY (SERVICE_OBJECTIVE = ELASTIC_POOL (NAME = [hspool])) WITH MANUAL_CUTOVER; + +ALTER DATABASE db PERFORM_CUTOVER; From 2a678e929e5b91828c1fad950d8d3b79169d7f85 Mon Sep 17 00:00:00 2001 From: May Wen Date: Tue, 17 Jun 2025 18:25:06 +0000 Subject: [PATCH 2/5] Merged PR 1704129: support ORDER clause for NonClustered ColumnStore Index ## Description Support Order clause on NONClustered ColumnStore Index. CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI ON T(A, B, C) ORDER(A, B); CREATE COLUMNSTORE INDEX idx_ntccitrim_prim2 ON dbo.nttrim_prim (i1, c1, nvc1) ORDER (i1, c1); We already support CLUSTERED COLUMNSTORE INDEX Order clause, we need add support for NonClustered right now. ## Code Change - [x] The [Common checklist](https://msdata.visualstudio.com/SQLToolsAndLibraries/_git/Common?path=/Templates/PR%20Checklist%20for%20SQLToolsAndLibraries.md&version=GBmain&_a=preview) has been reviewed and followed - [x] Code changes are accompanied by appropriate unit tests - [x] Identified and included SMEs needed to review code changes - [x] Follow the [steps](https://msdata.visualstudio.com/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki/33838/Adding-or-Extending-TSql-support-in-Sql-Dom?anchor=make-the-changes-in) here to make changes in the code ## Testing - [x] Follow the [steps](https://msdata.visualstudio.com/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki/33838/Adding-or-Extending-TSql-support-in-Sql-Dom?anchor=to-extend-the-tests-do-the-following%3A) here to add new tests for your feature ![image.png](https://msdata.visualstudio.com/c6789c20-b819-4bfd-9917-11471655156e/_apis/git/repositories/2247f543-55d8-45df-a9fe-23820ae656af/pullRequests/1704129/attachments/image.png) ## Documentation - [x] Update relevant documentation in the [wiki](https://dev.azure.com/msdata/SQLToolsAndLibraries/_wiki/wikis/SQLToolsAndLibraries.wiki) and the README.md file ## Additional Information Please provide any additional information that might be helpful for the reviewers support ORDER clause for NonClustered ColumnStore Index ---- #### AI description (iteration 1) #### PR Classification New feature enabling the ORDER clause for both clustered and non-clustered columnstore indexes. #### PR Summary This pull request enhances the SQL script generator to support the ORDER clause for columnstore indexes and adds tests to verify the new syntax. - `SqlScriptGeneratorVisitor.CreateColumnStoreIndexStatement.cs`: Modified condition to generate ordered columns for both clustered and non-clustered indexes. - `Only170SyntaxTests.cs`: Updated test suite to include a new parser test for the CreateColumnStoreIndex syntax. - `Baselines170/CreateColumnStoreIndexTests170.sql` & `TestScripts/CreateColumnStoreIndexTests170.sql`: Added new test files to validate the ORDER clause support. Related work items: #3876240 --- ...iptGeneratorVisitor.CreateColumnStoreIndexStatement.cs | 6 ++++-- .../Baselines170/CreateColumnStoreIndexTests170.sql | 8 ++++++++ Test/SqlDom/Only170SyntaxTests.cs | 3 ++- .../SqlDom/TestScripts/CreateColumnStoreIndexTests170.sql | 8 ++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Test/SqlDom/Baselines170/CreateColumnStoreIndexTests170.sql create mode 100644 Test/SqlDom/TestScripts/CreateColumnStoreIndexTests170.sql diff --git a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateColumnStoreIndexStatement.cs b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateColumnStoreIndexStatement.cs index d37ab56..cce64f4 100644 --- a/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateColumnStoreIndexStatement.cs +++ b/SqlScriptDom/ScriptDom/SqlServer/ScriptGenerator/SqlScriptGeneratorVisitor.CreateColumnStoreIndexStatement.cs @@ -36,8 +36,10 @@ public override void ExplicitVisit(CreateColumnStoreIndexStatement node) GenerateParenthesisedCommaSeparatedList(node.Columns); } - // If clustered columstore index, generate ordered columns if any - if(node.Clustered.GetValueOrDefault() && node.OrderedColumns != null && node.OrderedColumns.Count > 0) + // Generate ordered columns if any, for both clustered and non-clustered indexes + // If node.Clustered is null or false, it indicates index type is non-clustered. + // If node.Clustered is true, it indicates index type is clustered. + if (node.OrderedColumns != null && node.OrderedColumns.Count > 0) { GenerateSpaceAndKeyword(TSqlTokenType.Order); GenerateParenthesisedCommaSeparatedList(node.OrderedColumns); diff --git a/Test/SqlDom/Baselines170/CreateColumnStoreIndexTests170.sql b/Test/SqlDom/Baselines170/CreateColumnStoreIndexTests170.sql new file mode 100644 index 0000000..d9201bf --- /dev/null +++ b/Test/SqlDom/Baselines170/CreateColumnStoreIndexTests170.sql @@ -0,0 +1,8 @@ +CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI + ON T(A, B, C) ORDER(A, B); + +CREATE COLUMNSTORE INDEX NCCI + ON T(A, B, C) ORDER(A, B); + +CREATE CLUSTERED COLUMNSTORE INDEX CCI + ON T ORDER(A, B); diff --git a/Test/SqlDom/Only170SyntaxTests.cs b/Test/SqlDom/Only170SyntaxTests.cs index 49eb9bd..bd84d40 100644 --- a/Test/SqlDom/Only170SyntaxTests.cs +++ b/Test/SqlDom/Only170SyntaxTests.cs @@ -10,7 +10,8 @@ public partial class SqlDomTests private static readonly ParserTest[] Only170TestInfos = { new ParserTest170("RegexpTVFTests170.sql", nErrors80: 1, nErrors90: 1, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0), - new ParserTest170("AlterDatabaseManualCutoverTests170.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4) + new ParserTest170("AlterDatabaseManualCutoverTests170.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4), + new ParserTest170("CreateColumnStoreIndexTests170.sql", nErrors80: 3, nErrors90: 3, nErrors100: 3, nErrors110: 3, nErrors120: 3, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0) }; private static readonly ParserTest[] SqlAzure170_TestInfos = diff --git a/Test/SqlDom/TestScripts/CreateColumnStoreIndexTests170.sql b/Test/SqlDom/TestScripts/CreateColumnStoreIndexTests170.sql new file mode 100644 index 0000000..d9201bf --- /dev/null +++ b/Test/SqlDom/TestScripts/CreateColumnStoreIndexTests170.sql @@ -0,0 +1,8 @@ +CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI + ON T(A, B, C) ORDER(A, B); + +CREATE COLUMNSTORE INDEX NCCI + ON T(A, B, C) ORDER(A, B); + +CREATE CLUSTERED COLUMNSTORE INDEX CCI + ON T ORDER(A, B); From 003bc0959a0c5c4019252d8cd74be12430008fd2 Mon Sep 17 00:00:00 2001 From: Dhruv Relwani Date: Fri, 20 Jun 2025 15:31:04 +0000 Subject: [PATCH 3/5] Merged PR 1702087: Identity Column - Fabric DW In this PR we delete options for Identity Columns in TSqlFabricDW.g since they are not supported by the Fabric SQL engine. i.e. Fabric warehouse does not support seed and increment.. Hence the supported TSQL syntax would change from: `IDENTITY [ (seed , increment) ]` to the new syntax: `CREATE TABLE table1 ( ID BIGINT IDENTITY );` Related work items: #4314344 --- SqlScriptDom/Parser/TSql/TSqlFabricDW.g | 23 ------------ .../IdentityColumnTestsFabricDW.sql | 27 ++++++++++++++ Test/SqlDom/CommonSyntaxTests.cs | 17 +++++++++ Test/SqlDom/OnlyFabricDWSyntaxTests.cs | 5 +-- Test/SqlDom/ParserErrorsTests.cs | 36 +++++++++++++++++-- .../IdentityColumnTestsFabricDW.sql | 27 ++++++++++++++ 6 files changed, 107 insertions(+), 28 deletions(-) create mode 100644 Test/SqlDom/BaselinesFabricDW/IdentityColumnTestsFabricDW.sql create mode 100644 Test/SqlDom/TestScripts/IdentityColumnTestsFabricDW.sql diff --git a/SqlScriptDom/Parser/TSql/TSqlFabricDW.g b/SqlScriptDom/Parser/TSql/TSqlFabricDW.g index 0923abc..137a318 100644 --- a/SqlScriptDom/Parser/TSql/TSqlFabricDW.g +++ b/SqlScriptDom/Parser/TSql/TSqlFabricDW.g @@ -29587,33 +29587,10 @@ rowguidcolConstraint [ColumnDefinition vParent] ; identityConstraint [IndexAffectingStatement statementType] returns [IdentityOptions vResult = FragmentFactory.CreateFragment()] -{ - ScalarExpression vExpression; - bool vNotForReplication; -} : tIdentity:Identity { UpdateTokenInfo(vResult,tIdentity); } - ( - (LeftParenthesis seedIncrement)=> // necessary because select statement can start with LeftParenthesis - LeftParenthesis vExpression=seedIncrement - { - vResult.IdentitySeed = vExpression; - } - Comma vExpression=seedIncrement - { - vResult.IdentityIncrement = vExpression; - } - tRParen:RightParenthesis - { - UpdateTokenInfo(vResult,tRParen); - } - )? - vNotForReplication = replicationClauseOpt[statementType, vResult] - { - vResult.IsIdentityNotForReplication = vNotForReplication; - } ; // Same as column_definition in SQL YACC grammar diff --git a/Test/SqlDom/BaselinesFabricDW/IdentityColumnTestsFabricDW.sql b/Test/SqlDom/BaselinesFabricDW/IdentityColumnTestsFabricDW.sql new file mode 100644 index 0000000..43988f9 --- /dev/null +++ b/Test/SqlDom/BaselinesFabricDW/IdentityColumnTestsFabricDW.sql @@ -0,0 +1,27 @@ +CREATE TABLE table1 ( + ID BIGINT IDENTITY +); + + +GO +CREATE TABLE Employees ( + EmployeeID BIGINT IDENTITY, + FirstName NVARCHAR (50), + LastName NVARCHAR (50) +); + + +GO +CREATE TABLE Orders ( + OrderID INT IDENTITY, + CustomerName VARCHAR (100) , + OrderDate DATETIME , + TotalAmount DECIMAL (10, 2) +); + + +GO +CREATE TABLE Products ( + ProductID BIGINT IDENTITY, + ProductName NVARCHAR (100) +); \ No newline at end of file diff --git a/Test/SqlDom/CommonSyntaxTests.cs b/Test/SqlDom/CommonSyntaxTests.cs index 39fa64e..8b280db 100644 --- a/Test/SqlDom/CommonSyntaxTests.cs +++ b/Test/SqlDom/CommonSyntaxTests.cs @@ -7,6 +7,8 @@ using Microsoft.SqlServer.TransactSql.ScriptDom; using Microsoft.VisualStudio.TestTools.UnitTesting; using SqlStudio.Tests.AssemblyTools.TestCategory; +using System; +using System.Collections.Generic; namespace SqlStudio.Tests.UTSqlScriptDom { @@ -238,8 +240,23 @@ public void CommonSyntaxInFabricDWParserTest() TSqlFabricDWParser parser = new TSqlFabricDWParser(true); SqlScriptGenerator scriptGen = ParserTestUtils.CreateScriptGen(SqlVersion.SqlFabricDW); + // Some syntaxes that are not supported in Fabric DW + var skippedTests = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "ColumnDefinitionTests.sql", + "IntegerTests.sql", + "TSqlParserTestScript1.sql", + "TSqlParserTestScript2.sql", + "ExpressionTests.sql" + }; + foreach (ParserTest ti in CommonTestInfos) { + if (skippedTests.Contains(ti._scriptFilename)) + { + continue; // Skip tests that are not applicable to Fabric DW + } + ParserTest.ParseAndVerify(parser, scriptGen, ti._scriptFilename, ti._resultFabricDW); } } diff --git a/Test/SqlDom/OnlyFabricDWSyntaxTests.cs b/Test/SqlDom/OnlyFabricDWSyntaxTests.cs index 58537c4..043340e 100644 --- a/Test/SqlDom/OnlyFabricDWSyntaxTests.cs +++ b/Test/SqlDom/OnlyFabricDWSyntaxTests.cs @@ -10,10 +10,11 @@ public partial class SqlDomTests private static readonly ParserTest[] OnlyFabricDWTestInfos = { new ParserTestFabricDW("CloneTableTestsFabricDW.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4, nErrors170: 4), - new ParserTestFabricDW("CreateProcedureCloneTableTestsFabricDW.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4, nErrors170: 4), - new ParserTestFabricDW("ScalarFunctionTestsFabricDW.sql", nErrors80: 3, nErrors90: 2, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0, nErrors170: 0), new ParserTestFabricDW("CreateAlterTableClusterByTestsFabricDW.sql", nErrors80: 6, nErrors90: 6, nErrors100: 6, nErrors110: 6, nErrors120: 6, nErrors130: 6, nErrors140: 6, nErrors150: 6, nErrors160: 6, nErrors170: 6), new ParserTestFabricDW("CreateExternalTableStatementTestsFabricDW.sql", nErrors80: 2, nErrors90: 2, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 2, nErrors140: 2, nErrors150: 2, nErrors160: 0, nErrors170: 0), + new ParserTestFabricDW("CreateProcedureCloneTableTestsFabricDW.sql", nErrors80: 4, nErrors90: 4, nErrors100: 4, nErrors110: 4, nErrors120: 4, nErrors130: 4, nErrors140: 4, nErrors150: 4, nErrors160: 4, nErrors170: 4), + new ParserTestFabricDW("IdentityColumnTestsFabricDW.sql", nErrors80: 0, nErrors90: 0, nErrors100: 0, nErrors110: 0, nErrors120: 0, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0, nErrors170: 0), + new ParserTestFabricDW("ScalarFunctionTestsFabricDW.sql", nErrors80: 3, nErrors90: 2, nErrors100: 2, nErrors110: 2, nErrors120: 2, nErrors130: 0, nErrors140: 0, nErrors150: 0, nErrors160: 0, nErrors170: 0) }; [TestMethod] diff --git a/Test/SqlDom/ParserErrorsTests.cs b/Test/SqlDom/ParserErrorsTests.cs index 7474efd..cd0f43a 100644 --- a/Test/SqlDom/ParserErrorsTests.cs +++ b/Test/SqlDom/ParserErrorsTests.cs @@ -3524,9 +3524,17 @@ public void NotForReplicationNotAllowedInTableVariablesFunctionsTypesErrorTest() new ParserErrorInfo(39, "SQL46010", "not")); // Column identity constraint - ParserTestUtils.ErrorTestAllParsers("declare @v1 table (c1 int identity(1,1) not for replication)", + ParserTestUtils.ErrorTestAllParsersUntil150("declare @v1 table (c1 int identity(1,1) not for replication)", new ParserErrorInfo(40, "SQL46010", "not")); - ParserTestUtils.ErrorTestAllParsers("create function f1() returns @v1 table (c1 int identity(1,1) not for replication) begin return end", + ParserTestUtils.ErrorTest160("declare @v1 table (c1 int identity(1,1) not for replication)", + new ParserErrorInfo(40, "SQL46010", "not")); + ParserTestUtils.ErrorTest170("declare @v1 table (c1 int identity(1,1) not for replication)", + new ParserErrorInfo(40, "SQL46010", "not")); + ParserTestUtils.ErrorTestAllParsersUntil150("create function f1() returns @v1 table (c1 int identity(1,1) not for replication) begin return end", + new ParserErrorInfo(61, "SQL46010", "not")); + ParserTestUtils.ErrorTest160("create function f1() returns @v1 table (c1 int identity(1,1) not for replication) begin return end", + new ParserErrorInfo(61, "SQL46010", "not")); + ParserTestUtils.ErrorTest170("create function f1() returns @v1 table (c1 int identity(1,1) not for replication) begin return end", new ParserErrorInfo(61, "SQL46010", "not")); ParserTestUtils.ErrorTest100("create type t1 as table (c1 int identity(1,1) not for replication)", new ParserErrorInfo(46, "SQL46010", "not")); @@ -6838,7 +6846,6 @@ RETURNS NVARCHAR(101) RETURN @first + ' ' + @last END;"; ParserTestUtils.ErrorTestFabricDW(scalarFunctionSyntax2, new ParserErrorInfo(scalarFunctionSyntax2.IndexOf("INLINE"), "SQL46010", "INLINE")); - string scalarFunctionSyntax3 = @"CREATE OR ALTER FUNCTION dbo.CountProducts ( @ProductTable AS dbo.ProductType READONLY @@ -6868,5 +6875,28 @@ FROM @SalesData END;"; ParserTestUtils.ErrorTestFabricDW(scalarFunctionSyntax4, new ParserErrorInfo(scalarFunctionSyntax4.IndexOf("NULL"), "SQL46010", "NULL")); } + + /// + /// Negative tests for Scalar Functions in Fabric DW. + /// + [TestMethod] + [Priority(0)] + [SqlStudioTestCategory(Category.UnitTest)] + public void IdentityColumnNegativeTestsFabricDW() + { + string identityColumnSyntax = @"CREATE TABLE TestTable1 ( + ID INT IDENTITY(1,1), + Name VARCHAR(50) + ); + "; + ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax, new ParserErrorInfo(90, "SQL46010", "(")); + + string identityColumnSyntax2 = @"CREATE TABLE TestTable2 ( + RecordID BIGINT IDENTITY(100,5), + Description NVARCHAR(200) + ); + "; + ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax2, new ParserErrorInfo(99, "SQL46010", "(")); + } } } diff --git a/Test/SqlDom/TestScripts/IdentityColumnTestsFabricDW.sql b/Test/SqlDom/TestScripts/IdentityColumnTestsFabricDW.sql new file mode 100644 index 0000000..43988f9 --- /dev/null +++ b/Test/SqlDom/TestScripts/IdentityColumnTestsFabricDW.sql @@ -0,0 +1,27 @@ +CREATE TABLE table1 ( + ID BIGINT IDENTITY +); + + +GO +CREATE TABLE Employees ( + EmployeeID BIGINT IDENTITY, + FirstName NVARCHAR (50), + LastName NVARCHAR (50) +); + + +GO +CREATE TABLE Orders ( + OrderID INT IDENTITY, + CustomerName VARCHAR (100) , + OrderDate DATETIME , + TotalAmount DECIMAL (10, 2) +); + + +GO +CREATE TABLE Products ( + ProductID BIGINT IDENTITY, + ProductName NVARCHAR (100) +); \ No newline at end of file From 4ae2b5ce6d0743c271c6c76efd799e0638fcb9b5 Mon Sep 17 00:00:00 2001 From: MerlinBot Date: Thu, 12 Jun 2025 19:15:42 +0000 Subject: [PATCH 4/5] [Security] Update .NET SDK to latest patch version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 17e2f86..0e56f42 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.410", + "version": "8.0.411", "rollForward": "latestMajor" }, "msbuild-sdks": { From ad7d9c2a32058051e2dfb4dcc8289d392cf645e0 Mon Sep 17 00:00:00 2001 From: "Zi Chen (from Dev Box)" Date: Fri, 27 Jun 2025 11:22:46 -0700 Subject: [PATCH 5/5] Fix test on Linux --- Test/SqlDom/ParserErrorsTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Test/SqlDom/ParserErrorsTests.cs b/Test/SqlDom/ParserErrorsTests.cs index cd0f43a..57f6264 100644 --- a/Test/SqlDom/ParserErrorsTests.cs +++ b/Test/SqlDom/ParserErrorsTests.cs @@ -6889,14 +6889,14 @@ ID INT IDENTITY(1,1), Name VARCHAR(50) ); "; - ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax, new ParserErrorInfo(90, "SQL46010", "(")); + ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax, new ParserErrorInfo(identityColumnSyntax.IndexOf("IDENTITY(") + 8, "SQL46010", "(")); string identityColumnSyntax2 = @"CREATE TABLE TestTable2 ( RecordID BIGINT IDENTITY(100,5), Description NVARCHAR(200) ); "; - ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax2, new ParserErrorInfo(99, "SQL46010", "(")); + ParserTestUtils.ErrorTestFabricDW(identityColumnSyntax2, new ParserErrorInfo(identityColumnSyntax2.IndexOf("IDENTITY(") + 8, "SQL46010", "(")); } } }