From 417d1e9f3a733290445c4a458a77a9f7336c20b7 Mon Sep 17 00:00:00 2001 From: David Shiflet Date: Mon, 8 Aug 2022 15:29:24 -0400 Subject: [PATCH] Update to v161.47027.0 --- Nuget/CHANGELOG.md | 84 ++- docs/media/certsettings.png | Bin 0 -> 136894 bytes init.cmd | 1 - src/Codegen/cfg.xml | 1 + src/Directory.Build.props | 2 +- .../Smo/Agent/JobServerTests.cs | 10 +- .../Smo/GeneralFunctionality/AuditSmoTests.cs | 2 +- .../GeneralFunctionality/DatabaseSmoTests.cs | 34 +- .../Smo/GeneralFunctionality/DwSmoTests.cs | 1 - .../PermissionsEnumTests.cs | 84 +++ .../ScriptingTests/Database_SmoTestSuite.cs | 19 +- .../ExternalFileFormat_SmoTestSuite.cs | 577 +++++++----------- .../Smo/ToolsConnectionInfo.xml | 1 - .../Smo/XEvent/TargetColumnInfoUnitTest.cs | 2 +- .../Smo/XEvent/TargetUnitTest.cs | 2 +- .../ConnectionInfo/ConnectionEnums.cs | 5 + .../StringConnectionInfo.strings | 1 + .../Management/Sdk/Sfc/Enumerator/XmlRead.cs | 10 +- .../SqlServer/Management/Smo/DatabaseBase.cs | 91 ++- .../Management/Smo/ExternalFileFormatBase.cs | 180 +----- .../Smo/Microsoft.SqlServer.Smo.csproj | 1 - .../SqlServer/Management/Smo/SqlSmoObject.cs | 7 +- .../SqlServer/Management/Smo/enumerations.cs | 4 +- .../SqlServer/Management/Smo/serverbase.cs | 13 +- .../SqlServer/Management/Smo/tablebase.cs | 36 +- .../SqlEnum/SqlConditionedStatement.cs | 25 + .../SqlServer/Management/SqlEnum/SqlObject.cs | 14 +- .../SqlServer/Management/SqlEnum/XmlRead.CS | 32 +- .../Management/SqlEnum/enumstructs.cs | 15 +- .../SqlServer/Management/SqlEnum/permenum.cs | 95 ++- .../Management/SqlEnum/xml/Database.xml | 73 ++- .../SqlEnum/xml/ExternalFileFormat.xml | 4 +- .../Management/SqlEnum/xml/README.md | 5 + .../Management/SqlEnum/xml/inc_server.xml | 2 +- .../Management/SqlEnum/xml/table.xml | 4 +- .../SqlScriptPublish/SqlScriptOptions.cs | 6 +- .../SqlScriptOptionsSR.strings | 1 + .../SqlScriptPublish/SqlScriptOptionsTests.cs | 3 +- 38 files changed, 785 insertions(+), 662 deletions(-) create mode 100644 docs/media/certsettings.png create mode 100644 src/FunctionalTest/Smo/GeneralFunctionality/PermissionsEnumTests.cs diff --git a/Nuget/CHANGELOG.md b/Nuget/CHANGELOG.md index 1b5ba99d..7c728d75 100644 --- a/Nuget/CHANGELOG.md +++ b/Nuget/CHANGELOG.md @@ -1,8 +1,16 @@ - # Introduction This file will log substantial changes made to SMO between public releases to nuget.org. +## 161.47027.0 + +- Fix distribution columns on scripting for taking into consideration more than one distribution column +- Add new EXTGOV_OPERATION_GROUP audit action type +- Force [quoted identifier on](https://github.com/microsoft/sqlmanagementobjects/issues/96) for table scripts +- Fix EnumObjects sort by Schema +- Add new enumeration values for SQL Server 2022 permissions +- Script FIRST_ROW support for serverless Synapse + ## 161.47021.0 - Add `LedgerViewSchema` property to table objects @@ -24,10 +32,10 @@ This file will log substantial changes made to SMO between public releases to nu - Add `LoginType` property to `ILoginOptions` interface. - `Login.PasswordPolicyEnforced` now returns `false` for Windows logins instead of throwing an exception - Remove net461 binaries from nuget packages -- Added Scripting Support for Ledger tables for SQL 2022+ +- Added Scripting Support for Ledger tables for Sql 2022+ - Change the `Size` property on `Server/Drive` objects to `System.Int64`. These objects don't have a C# wrapper class so it's not breaking any compilation. -- Add support for SQL Server version 16 -- Add new permissions for SQL 2019+ to SMO enumerations +- Add support for Sql Server version 16 +- Add new permissions for Sql 2019+ to SMO enumerations - Added External Stream object and External Streaming Jobs object for scripting - Add support for XML compression @@ -43,7 +51,7 @@ This file will log substantial changes made to SMO between public releases to nu ## 161.46437.65 - Update Microsoft.Data.SqlClient dependency to version 3.0.0 -- Added Scripting Support for Ledger table in Azure SQLDB +- Added Scripting Support for Ledger table in Azure Sql db - Change `Server.MasterDBPath` and `Server.MasterDBLogPath` properties to use `file_id` instead of `name` from `sys.database_files` - Enable Index creation for memory optimized tables in Azure - Fix Server/Logins to show external Logins for Azure SQLDB as they are now supported @@ -122,7 +130,65 @@ This file will log substantial changes made to SMO between public releases to nu - Enabled Server.EnumServerAttributes API on Azure SQL Database - Enabled Lock enumeration APIs on Azure SQL Database - Deleted the Database.CheckIdentityValues API -- Added new property "RequestMaximumMemoryGrantPercentageAsDouble" in WorkloadGroup to accept decimal values in Resource Governor (SQL 2019+). -- Changed the netfx binaries in Microsoft.SqlServer.SqlManagementObjects package to use Microsoft.Data.SqlClient -- Added a new package, Microsoft.SqlServer.SqlManagementObjects.SSMS, which only has netfx binaries and that uses System.Data.SqlClient - +- Added new property "RequestMaximumMemoryGrantPercentageAsDouble" in WorkloadGroup to accept decimal values in Resource Governor (SQL2019 and above). +- Fixed a scripting issue with statistics on filtered indexes where the filter from the index would be scripted with the UPDATE STATISTICS TSQL. +- Enabled Security Policy and Security Predicate objects on Azure SQL DataWarehouse + +## 160.2004021.0 + +- First non-preview 160 release, aligned with [SQL Server Management Studio](https://aka.ms/ssmsfullsetup) 18.5 +- Script extended properties for Azure SQL Database objects +- Enable Jupyter Notebook output for SqlScriptPublishModel. SSMS 18.5 can output a Notebook for Azure Data Studio in Generate Scripts now. +- Fix issue where Table.EnableAllIndexes(Recreate) did nothing +- Fix Database.EnumObjectPermissions usage in NetStandard binaries +- Remove FORCE ORDER hint from table enumeration that was causing major performance issues +- Fix Transfer with PrefetchAllObjects == false for pre-Sql 2014 versions so it doesn't throw an exception +- Extend value range for platform, name, and engineEdition JSON properties of SQL Assessment targets with arrays of strings: + + ```JSON + "target": { + "platform": ["Windows", "Linux"], + "name": ["master", "temp"] + } + ``` + +- Add 13 new [SQL Assessment rules](https://github.com/microsoft/sql-server-samples/blob/master/samples/manage/sql-assessment-api/release-notes.md) +- Fix help link in XTPHashAvgChainBuckets SQL Assessment rule +- Units for threshold parameter of FullBackup SQL Assessment rule changed from hours to days + +## 160.201141.0-preview + +- Remove unneeded "using" TSQL statements from Database.CheckTables method implementations +- Enable ColumnMasterKey properties Signature and AllowEnclaveComputations for Azure SQL DB +- Fix Database.EncryptionEnabled and Database.DatabaseEncryptionKey behavior during Database.Alter(). Now, this code will correctly create a new key using the server certificate named MyCertificate: + + ```C# + db.EncryptionEnabled = true; + db.DatabaseEncryptionKey.EncryptorName = "MyCertificate"; + db.DatabaseEncryptionKey.EncryptionAlgorithm = DatabaseEncryptionAlgorithm.Aes256; + db.DatabaseEncryptionKey.EncryptionType = DatabaseEncryptionType.ServerCertificate; + db.Alter() + ``` + +- Fixed the "like" and "contains" URN filter functions to work with parameters containing single quotes. These operators can be used to optimally initialize collections: + + ```C# + // populate the collection with databases that have Name starting with "RDA" + var server = Server(new ServerConnection(sqlConnection)); + server.Databases.ClearAndInitialize("[like(@Name, 'RDA%')]", new string[] { }); + ``` + +- Make Table.Location property optional for creating or scripting external tables. +- Enable scripting of ANSI_PADDING settings for Azure SQL Database tables. +- Remove obsolete types ServerActiveDirectory and DatabaseActiveDirectory +- Added BLOB_STORAGE scripting support for external data sources +- Fixed [error scripting external tables](https://feedback.azure.com/forums/908035-sql-server/suggestions/38267746-cannot-script-external-table-in-ssms-18-2) for Azure SQL Database +- Replace Microsoft.SqlServer.Management.SqlParser.dll with a dependency to its Nuget package + +## 160.1911221.0-preview + +- Increase major version from 15 to 16 +- Remove dependency on native batch parser from NetFx components +- Change NetStandard client driver to Microsoft.Data.SqlClient +- Add distribution property for DW materialized views +- Script FILLFACTOR for indexes on Azure SQL Database diff --git a/docs/media/certsettings.png b/docs/media/certsettings.png new file mode 100644 index 0000000000000000000000000000000000000000..1832b767de68f7c934c9db90aadc59a9d4215218 GIT binary patch literal 136894 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�ehT)@?(|?U1Exy1I)dhfVp?KEm?ao$*O+ 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%0A{gT?lj3 z7)5#->&x-rRvor@)BIDUH^(pDnVWUJ-{DRQuv3QB!QFL$pFXBx2>n-5 zjLPNr%IXRNW;ri_%L-HWw}Hv4vNfvH^t_8K)<%*(K5oNLm~C~cYk2aFe9f2t+#qZa zVjyBRk8!$dWS<2(WTFcm7=3i>UdPETx^@6^#atwXyC`tBi$?_tw_39`=NMe4mw4Iafjo5s6UTs{Cx)5G^r(CV5a|nLSo=lQ5y*f@v>a3GvMPr zjfCwj0X5nwrt?Mp;qMo+ch2>n?u?g@NTjTTn;NoqN4W3Rr0%fuNqeYyG7|sKb_n+E5b04J^9x zb;o!fyxQ;u+LQfQYh!;}?Zncf*2k=Kvoy7eZ%S34W~ho^C#Nb)L`t}`MMZ1J&|~9@ zVRdzp`hClq0a*su90_u+wfX1ucex@e%a{5m2Ry$;Kz^#FmzQf5NDQIF;ip#%lKmSt zi7g){(D2Oi=xsUxK;3fzSwD#o`kC(7;fs;?nh0p$qPfq}^Au2u@>0;-==m~!b^D+u z^kP5`m5KY@Sg6J1b2dnF?Kp#)(eIF)cyX4iXPleJ*}d%n>0{udo73zX|KA$%p|o>S z^gwXQJOH_n_~I);KHnp=Wo*S~zJG0@VK$7KM6uQRYC%0M{P?DzwEPZbSUtZtB0~?<2G1{^yv^95I zD0nr%9r?cOj%}m3Zsk2}W;kGli@=LLALBkQ8`Hhis#uf*GOD_nPSe1h%7C)1+QP+R zL>$}x1=P0C1+vA`Sxtb`y1eRoe2RBj|zwkua-tadm z6-2s?8@t+8sV!HjV>>ZII}C>#UswDv@CUO)(VIcMI**=FZY_60n1n=FfY&H&9ByLO z!_)y;RMd0ylh*UmMyf=3zgyTA`fkiUH%`=v$IlJRwWN}j7Hc71{$?g;D_Q0W-WS@z zN)#p@*EE^fZMGG@Hxx>}1l%sum{f(j$!2o?A^lUdRUrUKFO{S2R8?04s)_P?w{_p; zjG(~@&rP4eM>EHbcU^mT15d662R^!gDT`v?yHWQ-&7+%^l74L9?fVYx#E`oE5d|F( zQ@hJi^%#a()M-}(Ps0e${Z@TT%fx1k_fcPWtpdPy4wtHa#Y zf~nUy+RI4}E7;kdtC7(NlRPz6jO2fp0#i))0E^9I!TMrV)xXsfI|k!KI_yoz<99+i z?F^an!gC1IZJWuV2QV?7$Fynli9|8D^=PVPLJh*p=Xs)#!BVkj92@3BYds(5&(FVd zyY?X%0owVC6PRK&AttQw!w1Lf=kHA&Gxk61iN9F^iT)1({{gPxoCYdgM ze%A(Qy#tW&z@AS9Vu5UBIjLmJi_3?{-tY+^Z882ZGW$Wtmm1RI=q{K_?sNH!GyF+Q z;rPbXXw^f6q s4sNN?z@q@%$&GX4mUDLc7I3_SxV|t7Iy78r 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 bDx0(_Np?l{><= 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 vLVCvyT@rD~x4wlgqDIZlpg0AfG3@^VW^ + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index c851e54a..14e21075 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -89,7 +89,7 @@ - 160.22504.0 + 160.22510.0 Microsoft.Data.SqlClient 3.1.0 diff --git a/src/FunctionalTest/Smo/Agent/JobServerTests.cs b/src/FunctionalTest/Smo/Agent/JobServerTests.cs index 0f70369d..cc2f00e8 100644 --- a/src/FunctionalTest/Smo/Agent/JobServerTests.cs +++ b/src/FunctionalTest/Smo/Agent/JobServerTests.cs @@ -3,7 +3,6 @@ using System; using System.Data; -using System.Diagnostics; using System.Linq; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Sdk.Sfc; @@ -18,10 +17,10 @@ namespace Microsoft.SqlServer.Test.SMO.Agent { [TestClass] - [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] public class JobServerTests : SqlTestBase { [TestMethod] + [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] public void JobServer_PurgeJobHistory_generates_correct_query() { ExecuteTest(() => @@ -49,6 +48,7 @@ public void JobServer_PurgeJobHistory_generates_correct_query() [TestMethod] [UnsupportedHostPlatform(SqlHostPlatforms.Linux)] + [SupportedServerVersionRange(MinMajor = 16, Edition = DatabaseEngineEdition.Enterprise)] public void JobServer_EnumPerformanceCounters_returns_agent_counters() { ExecuteTest(() => @@ -70,6 +70,7 @@ public void JobServer_EnumPerformanceCounters_returns_agent_counters() } [TestMethod] + [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] public void JobServer_Msx_methods_generate_correct_queries() { ExecuteTest(() => @@ -92,6 +93,8 @@ public void JobServer_Msx_methods_generate_correct_queries() } [TestMethod] + [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] + public void JobServer_ErrorLog_methods_generate_correct_queries() { ExecuteTest(() => @@ -135,7 +138,9 @@ private Job CreateJob(string loginName = null) job.Refresh(); return job; } + [TestMethod] + [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] public void JobServer_Job_methods() { ExecuteTest(() => @@ -180,6 +185,7 @@ public void JobServer_Job_methods() } [TestMethod] + [SupportedServerVersionRange(Edition = Management.Common.DatabaseEngineEdition.Enterprise)] public void JobServer_miscellaneous_methods_generate_correct_queries() { ExecuteTest(() => diff --git a/src/FunctionalTest/Smo/GeneralFunctionality/AuditSmoTests.cs b/src/FunctionalTest/Smo/GeneralFunctionality/AuditSmoTests.cs index 214a6f99..7b61094b 100644 --- a/src/FunctionalTest/Smo/GeneralFunctionality/AuditSmoTests.cs +++ b/src/FunctionalTest/Smo/GeneralFunctionality/AuditSmoTests.cs @@ -433,7 +433,7 @@ public void ServerAuditspecifications_Audit_Action_Types_In_DB_Should_Match_Enum UNION ALL SELECT name FROM (VALUES ('SELECT'),('UPDATE'),('INSERT'),('DELETE'),('EXECUTE'),('RECEIVE'),('REFERENCES')) actions(name)"; var dbAuditList = ServerContext.ConnectionContext.ExecuteWithResults(query).Tables[0].Rows.Cast().Select(row => row["name"].ToString()); - + System.Diagnostics.Trace.TraceInformation("Missing audit action types: {0}", string.Join(",", dbAuditList.Except(enumAttributeNames))); // enumAttributeNames is a superset of dbAuditList. Assert.That(enumAttributeNames, Is.SupersetOf(dbAuditList), @"Some types are missing in AuditActionType enum. Please, update enum AuditActionType in /src/Microsoft/SqlServer/Management/SqlEnum/enumstructs.cs"); diff --git a/src/FunctionalTest/Smo/GeneralFunctionality/DatabaseSmoTests.cs b/src/FunctionalTest/Smo/GeneralFunctionality/DatabaseSmoTests.cs index 215ef749..d2e328e9 100644 --- a/src/FunctionalTest/Smo/GeneralFunctionality/DatabaseSmoTests.cs +++ b/src/FunctionalTest/Smo/GeneralFunctionality/DatabaseSmoTests.cs @@ -119,19 +119,31 @@ public void EnumObjects_Sets_Synonym_Schema_And_Other_Properties() }; syn.Create(); + var script = database.ExecutionManager.RecordQueryText(() => + { + // Now, we retrieve the same object we just created by calling EnumObjects() + var objs = database.EnumObjects(DatabaseObjectTypes.Synonym, _SMO.SortOrder.Schema); + var synobj = objs.Rows.Cast().Where(r => (string)r["Name"] == expectedSynName).Single(); - // Now, we retrieve the same object we just created by calling EnumObjects() - var objs = database.EnumObjects(DatabaseObjectTypes.Synonym); - var synobj = objs.Rows.Cast().Where(r => (string)r["Name"] == expectedSynName).Single(); - - // The original bug was that Schema was coming back as blank, because there was an assumption - // that synonyms did not have a schema (which was incorrect) - Assert.That(synobj["Schema"], Is.EqualTo(expectedSynSchema), "Unexpected value for Schema"); + // The original bug was that Schema was coming back as blank, because there was an assumption + // that synonyms did not have a schema (which was incorrect) + Assert.That(synobj["Schema"], Is.EqualTo(expectedSynSchema), "Unexpected value for Schema"); - // While we are at it, let's also check the other properties... - Assert.That(synobj["DatabaseObjectTypes"], Is.EqualTo("Synonym"), "Unexpected value for DatabaseObjectTypes"); - Assert.That(synobj["Name"], Is.EqualTo(expectedSynName), "Unexpected value for Name"); - Assert.That(synobj["Urn"], Is.EqualTo(syn.Urn.ToString()), "Unexpected value for Urn"); + // While we are at it, let's also check the other properties... + Assert.That(synobj["DatabaseObjectTypes"], Is.EqualTo("Synonym"), "Unexpected value for DatabaseObjectTypes"); + Assert.That(synobj["Name"], Is.EqualTo(expectedSynName), "Unexpected value for Name"); + Assert.That(synobj["Urn"], Is.EqualTo(syn.Urn.ToString()), "Unexpected value for Urn"); + }, alsoExecute: true); + Assert.That(script.ToSingleString(), Contains.Substring("ORDER BY [Schema]"), "EnumObjects (SortOrder.Schema)"); + if (database.DatabaseEngineType == DatabaseEngineType.Standalone) + { + script = database.ExecutionManager.RecordQueryText(() => database.EnumObjects(), alsoExecute: true); + Assert.That(script.ToSingleString(), Contains.Substring("ORDER BY [DatabaseObjectTypes]"), "EnumObjects()"); + } + script = database.ExecutionManager.RecordQueryText(() => database.EnumObjects(DatabaseObjectTypes.Table, _SMO.SortOrder.Name), alsoExecute: true); + Assert.That(script.ToSingleString(), Contains.Substring("ORDER BY [Name]"), "EnumObjects()"); + script = database.ExecutionManager.RecordQueryText(() => database.EnumObjects(DatabaseObjectTypes.View, _SMO.SortOrder.Urn), alsoExecute: true); + Assert.That(script.ToSingleString(), Contains.Substring("ORDER BY [Urn]"), "EnumObjects()"); }); } diff --git a/src/FunctionalTest/Smo/GeneralFunctionality/DwSmoTests.cs b/src/FunctionalTest/Smo/GeneralFunctionality/DwSmoTests.cs index 1b847df3..fa507f56 100644 --- a/src/FunctionalTest/Smo/GeneralFunctionality/DwSmoTests.cs +++ b/src/FunctionalTest/Smo/GeneralFunctionality/DwSmoTests.cs @@ -65,7 +65,6 @@ public void Server_Databases_collection_enumerates_without_exception() } }); - Assert.That(databases.FirstOrDefault(d => d.EndsWith("Unknown")), Is.Not.Null, "Expected at least one Unknown engine edition. Make sure the test server has a paused DW instance. " + String.Join(",", databases)); }); } } diff --git a/src/FunctionalTest/Smo/GeneralFunctionality/PermissionsEnumTests.cs b/src/FunctionalTest/Smo/GeneralFunctionality/PermissionsEnumTests.cs new file mode 100644 index 00000000..5dea7719 --- /dev/null +++ b/src/FunctionalTest/Smo/GeneralFunctionality/PermissionsEnumTests.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft. +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Linq; +using System.Text; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlServer.Test.Manageability.Utils.TestFramework; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NUnit.Framework; +using Assert = NUnit.Framework.Assert; + +namespace Microsoft.SqlServer.Test.SMO.GeneralFunctionality +{ + [TestClass] + [UnsupportedDatabaseEngineEdition(DatabaseEngineEdition.SqlOnDemand)] + public class PermissionsEnumTests : SqlTestBase + { + [TestMethod] + public void PermEnum_DatabasePermissionSetValue_enum_is_complete() + { + ExecuteTest(() => + { + CompareEnumToServerPermissions(typeof(DatabasePermissionSetValue), @"select type, permission_name from sys.fn_builtin_permissions('DATABASE')"); + }); + } + + [TestMethod] + public void PermEnum_ServerPermissionSetValue_enum_is_complete() + { + ExecuteTest(() => + { + CompareEnumToServerPermissions(typeof(ServerPermissionSetValue), @"select type, permission_name from sys.fn_builtin_permissions('SERVER')"); + }); + } + + [TestMethod] + public void PermEnum_ObjectPermissionSetValue_enum_is_complete() + { + ExecuteTest(() => + { + CompareEnumToServerPermissions(typeof(ObjectPermissionSetValue), @"select type, permission_name from sys.fn_builtin_permissions(DEFAULT) where class_desc <> 'SERVER' and class_desc <> 'DATABASE'"); + }); + } + private void CompareEnumToServerPermissions(Type enumType, string permissionQuery) + { + var permissionTypes = GetAttributeValues(enumType); + var permissionNames = GetAttributeValues(enumType); + var permissionList = ServerContext.ConnectionContext.ExecuteWithResults(permissionQuery).Tables[0].Rows.Cast(); + var maxValue = Enum.GetValues(enumType).Cast().Max(); + var textInfo = new CultureInfo("en-US", false).TextInfo; + var missingValues = new StringBuilder(); + foreach (var row in permissionList) + { + var name = row["permission_name"].ToString().Trim(); + var type = row["type"].ToString().Trim(); + if (!permissionNames.Contains(name) || !permissionTypes.Contains(type)) + { + var enumName = new StringBuilder(); + foreach (var s in name.Split(' ')) + { + enumName.Append(textInfo.ToTitleCase(s.ToLowerInvariant())); + } + enumName.Append($" = {++maxValue},"); + missingValues.Append($"{Environment.NewLine}[PermissionType(\"{type}\")]{Environment.NewLine}[PermissionName(\"{name}\")]{Environment.NewLine}{enumName}{Environment.NewLine}"); + } + } + Assert.That(missingValues.ToString(), Is.Empty, $"{ enumType.Name} is incomplete. Add the missing values."); + } + ///

+ /// Returns the set of string attribute values associated with the given enumeration. + /// + /// + /// + /// + static internal IEnumerable GetAttributeValues(Type enumType) where T: StringValueAttribute { + return new HashSet(Enum.GetNames(enumType).Select(n => enumType.GetMember(n).Single().GetCustomAttributes(typeof(T), false).Cast().Single().Value)); + } + } +} diff --git a/src/FunctionalTest/Smo/ScriptingTests/Database_SmoTestSuite.cs b/src/FunctionalTest/Smo/ScriptingTests/Database_SmoTestSuite.cs index cc5c4421..9bc660dd 100644 --- a/src/FunctionalTest/Smo/ScriptingTests/Database_SmoTestSuite.cs +++ b/src/FunctionalTest/Smo/ScriptingTests/Database_SmoTestSuite.cs @@ -143,16 +143,17 @@ public void Trying_To_Access_AzureDB_With_DBManager_Role_Only_Does_Not_Throw() try { var pwd = SqlTestRandom.GeneratePassword(); - _SMO.Login login = null; + Login login = null; + User user = null; SqlConnection sqlConn = null; try { // Here we creata a login/user... login = master.Parent.CreateLogin(GenerateUniqueSmoObjectName("login_low_priv", maxLength: 128), _SMO.LoginType.SqlLogin, pwd); - var user = master.CreateUser(login.Name, login.Name); + user = master.CreateUser(login.Name, login.Name); - // ... and we grant it limite permissions (certainly a lot less than "cloudsa"). + // ... and we grant it limited permissions (certainly a lot less than "cloudsa"). // Note: the "dbmanager" role seems to only exist in SQL Azure, so for this reason // this test is restricted to that EngineType. master.ExecutionManager.ExecuteNonQuery( @@ -175,12 +176,10 @@ public void Trying_To_Access_AzureDB_With_DBManager_Role_Only_Does_Not_Throw() sqlConn.Open(); var dbScopedConn = new ServerConnection(sqlConn); var server = new _SMO.Server(dbScopedConn); - - // Before the fix, trying to do this would cause an exception. - Assert.DoesNotThrow(() => - { - var dbee = server.Databases.Count; - }, "Unexpected exception."); + server.SetDefaultInitFields(typeof(Database), nameof(Database.AzureEdition)); + Assert.That(server.Databases.Cast().Select(d => d.DatabaseEngineEdition), Has.None.EqualTo(DatabaseEngineEdition.Unknown), "Low privileged user should get DatabaseEngineEdition of all databases"); + Assert.That(server.Databases.Cast().Where(d => d.DatabaseEngineEdition == DatabaseEngineEdition.SqlDatabase).Select(d => d.AzureEdition), Has.None.EqualTo(""), "Low privileged user should get AzureEdition of all Azure DB databases"); + Assert.Throws(() => { var x = server.Databases[db.Name].Size; }, "Accessing other properties of inaccessible Database should throw"); } } finally @@ -195,7 +194,7 @@ public void Trying_To_Access_AzureDB_With_DBManager_Role_Only_Does_Not_Throw() master.ExecutionManager.ExecuteNonQuery( string.Format("ALTER ROLE dbmanager DROP member {0}", SmoObjectHelpers.SqlBracketQuoteString(login.Name))); - + user?.Drop(); login.Drop(); } } diff --git a/src/FunctionalTest/Smo/ScriptingTests/ExternalFileFormat_SmoTestSuite.cs b/src/FunctionalTest/Smo/ScriptingTests/ExternalFileFormat_SmoTestSuite.cs index 7a54c750..3126ee47 100644 --- a/src/FunctionalTest/Smo/ScriptingTests/ExternalFileFormat_SmoTestSuite.cs +++ b/src/FunctionalTest/Smo/ScriptingTests/ExternalFileFormat_SmoTestSuite.cs @@ -40,7 +40,7 @@ public void VerifyPositiveExternalFileFormatCreateDrop_AzureSterlingV12_SqlDW() /// server have the same values for their properties/scripts as expected. /// [VSTest.TestMethod] - [SupportedServerVersionRange(DatabaseEngineType = DatabaseEngineType.Standalone, MinMajor = 13, MaxMajor =15)] + [SupportedServerVersionRange(DatabaseEngineType = DatabaseEngineType.Standalone, MinMajor = 13, MaxMajor = 15)] [UnsupportedHostPlatform(SqlHostPlatforms.Linux)] [SqlTestArea(SqlTestArea.Polybase)] [UnsupportedDatabaseEngineEdition(DatabaseEngineEdition.SqlOnDemand)] @@ -49,6 +49,51 @@ public void VerifyPositiveExternalFileFormatCreateDrop_2016AndAfterOnPrem() VerifyPositiveExternalFileFormatCreateDrop(); } + /// + /// Verifies that SQL database objects created using SMO from a SQL On Demand + /// server have the same values for their properties/scripts as expected. + /// + [VSTest.DataTestMethod] + // positive unit tests for the DELIMITEDTEXT file format type + // supported DDL options are: (1) no optional properties; (2) any of the format properties (field terminator, string delimiter and use type default; + // NOTE: The serde method is not supported with the format type being DELIMITEDTEXT. + // 1. no optional properties + // 2. any of the format options + // 3. data compression + // 4. format options and data compression + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "", "", null, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "|", "", "", null, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "#", "", null, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "", "", false, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "", "", true, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "", "", null, "", 41)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "", "", "", null, "", 1)] + [VSTest.DataRow("eff1", ExternalFileFormatType.DelimitedText, "", "|", "#", "", false, "", 41)] + // positive unit tests for PARQUET file format type + // supported DDL options are: (1) no optional properties; (2) data compression property + // NOTE: The serde method and the format options are not supported with the format type being PARQUET. + // 1. no optional properties + // 2. data compression + [VSTest.DataRow("eff1", ExternalFileFormatType.Parquet, "", "", "", "", null, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.Parquet, "", "", "", "", null, "org.apache.hadoop.io.compress.GzipCodec", null)] + // positive unit tests for DELTA file format type + // supported DDL options are: (1) no optional properties; (2) data compression property + // NOTE: The serde method and the format options are not supported with the format type being DELTA. + // 1. no optional properties + // 2. data compression + [VSTest.DataRow("eff1", ExternalFileFormatType.Delta, "", "", "", "", null, "", null)] + [VSTest.DataRow("eff1", ExternalFileFormatType.Delta, "", "", "", "", null, "org.apache.hadoop.io.compress.GzipCodec", null)] + [SupportedServerVersionRange(Edition = DatabaseEngineEdition.SqlOnDemand)] + public void VerifyPositiveExternalFileFormatCreateDrop_SqlOnDemand(string name, ExternalFileFormatType type, string serDeMethod, string stringTerminator, string stringDelimiter, string dateFormat, bool? useTypeDefaultOption, string dataCompression, int? firstRow) + { + this.ExecuteWithDbDrop( + database => + { + VerifyPositiveExternalFileFormatCreateDropHelper(database, name, type, serDeMethod, stringTerminator, stringDelimiter, dateFormat, useTypeDefaultOption, dataCompression, firstRow); + } + ); + } + /// Tests creating, dropping and scripting of the external file format objects via SMO. /// Positive test steps: /// 1. Create an external file format with the format type property. @@ -132,6 +177,22 @@ private void VerifyPositiveExternalFileFormatCreateDrop(AzureDatabaseEdition azu azureDatabaseEdition); } + private void VerifyPositiveDeltaExternalFileFormatCreateDrop(string externalFileFormatName, string dataCompression) + { + this.ExecuteWithDbDrop( + database => + { + // positive unit tests for DELTA file format type + // supported DDL options are: (1) no optional properties; + // NOTE: The serde method and the format options are not supported with the format type being DELTA. + // 1. no optional properties + // 2. data compression + VerifyPositiveExternalFileFormatCreateDropHelper(database, externalFileFormatName, ExternalFileFormatType.Delta, string.Empty, string.Empty, string.Empty, string.Empty, null, dataCompression); + }, + AzureDatabaseEdition.NotApplicable + ); + } + /// /// Tests dropping an external file format with IF EXISTS option through SMO on SQL16 and later. /// @@ -284,7 +345,7 @@ private void VerifyPositiveExternalFileFormatCreateDropHelper( scriptTemplate.Append(string.Format(ExternalFileFormatScriptCreateTemplate, fullyFormatedNameForScripting, this.GetSqlKeywordForFileFormatType(externalFileFormat.FormatType))); // process optional parameters for each file format type and add them to the T-SQL script - ProcessOptionalProperties(externalFileFormat, scriptTemplate, db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse); + ProcessOptionalProperties(externalFileFormat, scriptTemplate, db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse || db.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand); TraceHelper.TraceInformation(createExternalFileFormatScripts); TraceHelper.TraceInformation(scriptTemplate.ToString()); Assert.That(createExternalFileFormatScripts, Does.Contain(scriptTemplate.ToString())); @@ -474,12 +535,6 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, string errorMessage = string.Empty; var ex = Assert.Throws(externalFileFormat.Create, "verify the external file format was not created due to unset FormatType"); - var innerEx = ex.GetBaseException(); - Assert.Multiple(() => - { - Assert.That(innerEx, Is.InstanceOf(), "innermost exception"); - Assert.That(innerEx.Message, Does.Contain(nameof(externalFileFormat.FormatType)), "innermost exception message"); - }); // // Step 2. Create external file format with conflicting properties - format type is DelimitedText and SerDeMethod. @@ -487,24 +542,8 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FormatType = externalFileFormatType; externalFileFormat.SerDeMethod = externalFileFormatSerDeMethod; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "SerDeMethod", externalFileFormat.SerDeMethod, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); + Assert.Throws(externalFileFormat.Create); - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } // // Step 3. Create external file format with conflicting properties - format type is RcFile and FieldTerminator. @@ -512,24 +551,8 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FormatType = ExternalFileFormatType.RcFile; externalFileFormat.FieldTerminator = externalFileFormatFieldTerminator; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FieldTerminator", externalFileFormat.FieldTerminator, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); + Assert.Throws(externalFileFormat.Create); - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } // // Step 4. Create external file format with conflicting properties - format type is RcFile and StringDelimiter. @@ -538,24 +561,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FieldTerminator = string.Empty; externalFileFormat.StringDelimiter = externalFileFormatStringDelimiter; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "StringDelimiter", externalFileFormat.StringDelimiter, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 5. Create external file format with conflicting properties - format type is RcFile and DateFormat. @@ -565,24 +571,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.StringDelimiter = string.Empty; externalFileFormat.DateFormat = externalFileFormatDateFormat; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "DateFormat", externalFileFormat.DateFormat, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 6. Create external file format with conflicting properties - format type is RcFile and UseTypeDefault. @@ -593,26 +582,9 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.DateFormat = string.Empty; externalFileFormat.UseTypeDefault = true; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "UseTypeDefault", externalFileFormat.UseTypeDefault.ToString(), externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); - if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse) + if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse || db.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand) { // // Step 7. Create external file format with conflicting properties - format type is RcFile and FirstRow. @@ -624,24 +596,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.UseTypeDefault = false; externalFileFormat.FirstRow = 10; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FirstRow", externalFileFormat.FirstRow, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); } // @@ -650,24 +605,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FormatType = ExternalFileFormatType.Orc; externalFileFormat.SerDeMethod = externalFileFormatSerDeMethod; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "SerDeMethod", externalFileFormat.SerDeMethod, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 9. Create external file format with conflicting properties - format type is Orc and FieldTerminator. @@ -676,24 +614,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.SerDeMethod = string.Empty; externalFileFormat.FieldTerminator = externalFileFormatFieldTerminator; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FieldTerminator", externalFileFormat.FieldTerminator, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 10. Create external file format with conflicting properties - format type is Orc and StringDelimiter. @@ -703,24 +624,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FieldTerminator = string.Empty; externalFileFormat.StringDelimiter = externalFileFormatStringDelimiter; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "StringDelimiter", externalFileFormat.StringDelimiter, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 11. Create external file format with conflicting properties - format type is Orc and DateFormat. @@ -731,24 +635,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.StringDelimiter = string.Empty; externalFileFormat.DateFormat = externalFileFormatDateFormat; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "DateFormat", externalFileFormat.DateFormat, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 12. Create external file format with conflicting properties - format type is Orc and UseTypeDefault. @@ -760,26 +647,9 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.DateFormat = string.Empty; externalFileFormat.UseTypeDefault = true; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "UseTypeDefault", externalFileFormat.UseTypeDefault, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); - if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse) + if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse || db.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand) { // // Step 13. Create external file format with conflicting properties - format type is Orc and FirstRow. @@ -792,24 +662,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.UseTypeDefault = false; externalFileFormat.FirstRow = 10; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FirstRow", externalFileFormat.FirstRow, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); } // @@ -818,24 +671,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FormatType = ExternalFileFormatType.Parquet; externalFileFormat.SerDeMethod = externalFileFormatSerDeMethod; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "SerDeMethod", externalFileFormat.SerDeMethod, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 15. Create external file format with conflicting properties - format type is Parquet and FieldTerminator. @@ -844,24 +680,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.SerDeMethod = string.Empty; externalFileFormat.FieldTerminator = externalFileFormatFieldTerminator; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FieldTerminator", externalFileFormat.FieldTerminator, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 16. Create external file format with conflicting properties - format type is Parquet and StringDelimiter. @@ -871,24 +690,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FieldTerminator = string.Empty; externalFileFormat.StringDelimiter = externalFileFormatStringDelimiter; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "StringDelimiter", externalFileFormat.StringDelimiter, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 17. Create external file format with conflicting properties - format type Parquet and DateFormat. @@ -899,24 +701,7 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.StringDelimiter = string.Empty; externalFileFormat.DateFormat = externalFileFormatDateFormat; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "DateFormat", externalFileFormat.DateFormat, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); // // Step 18. Create external file format with conflicting properties - format type is Parquet and UseTypeDefault. @@ -928,26 +713,9 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.DateFormat = string.Empty; externalFileFormat.UseTypeDefault = true; - // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "UseTypeDefault", externalFileFormat.UseTypeDefault, externalFileFormat.FormatType.ToString()); - - externalFileFormat.Create(); - - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) - { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } + Assert.Throws(externalFileFormat.Create); - if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse) + if (db.DatabaseEngineEdition == DatabaseEngineEdition.SqlDataWarehouse || db.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand) { // // Step 19. Create external file format with conflicting properties - format type is Parquet and FirstRow. @@ -961,24 +729,137 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, externalFileFormat.FirstRow = 10; // verify the external file format was not created - try - { - // attempt to create an external file format - errorMessage = string.Format("Cannot set the property '{0}' to '{1}' because the property '{0}' is not supported for external file format type '{2}'.", "FirstRow", externalFileFormat.FirstRow, externalFileFormat.FormatType.ToString()); + errorMessage = $"Cannot set the property 'FirstRow' to '{externalFileFormat.FirstRow}' because the property 'FirstRow' is not supported for external file format type '{externalFileFormat.FormatType.ToString()}'."; + + // attempt to create an external file format + Assert.Throws(externalFileFormat.Create); + } + } + + /// + /// Tests negative scenarios for serverless database objects created using SMO from a SQL On Prem + /// server. + /// + [VSTest.TestMethod] + [SupportedServerVersionRange(Edition = DatabaseEngineEdition.SqlOnDemand)] + public void VerifyNegativeExternalFileFormatCreateDrop_SqlOnDemand() + { + VerifyNegativeDeltaExternalFileFormatCreateDrop(); + VerifyNegativeExternalFileFormatCreateDrop(); + } + + /// Tests creating, dropping and scripting of the Delta external file format objects via SMO. + /// Negative test steps: + /// 1. Create external file format with no required properties. + /// 2. Create external file format with conflicting properties - format type is Delta and SerDeMethod. + /// 3. Create external file format with conflicting properties - format type is Delta and FieldTerminator. + /// 4. Create external file format with conflicting properties - format type is Delta and StringDelimiter. + /// 5. Create external file format with conflicting properties - format type Delta and DateFormat. + /// 6. Create external file format with conflicting properties - format type is Delta and UseTypeDefault. + /// 7. Create external file format with conflicting properties - format type is Delta and FirstRow. + private void VerifyNegativeDeltaExternalFileFormatCreateDrop() + { + // const definitions + const string ExternalFileFormatSerdeMethod = @"org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe"; + const string FieldTerminator = "|"; + const string StringDelimiter = "#"; + const string DateFormat = "MM-dd-yyyy"; - externalFileFormat.Create(); + string externalFileFormatName = "eff1"; - // validate expected exception and error message - Assert.Fail(errorMessage, externalFileFormat.Name); - } - catch (SmoException e) + this.ExecuteWithDbDrop( + database => { - if (!ExceptionHelpers.IsExpectedException(e, errorMessage)) - { - throw; - } - } - } + // negative unit tests for the DELTA file format type + // unsupported DDL options are: serde method, + VerifyNegativeDeltaExternalFileFormatCreateDropHelper(database, externalFileFormatName, ExternalFileFormatSerdeMethod, FieldTerminator, StringDelimiter, DateFormat); + }, + AzureDatabaseEdition.NotApplicable); + } + + /// + /// Executes negative tests for the create delta external file format object. + /// + /// The database name. + /// The external file format name. + /// The external file format serialize/deserialize method property value. + /// The external file format field terminator property value. + /// The external file format string delimiter property value. + /// The external file format date format property value. + private void VerifyNegativeDeltaExternalFileFormatCreateDropHelper(Database db, + string externalFileFormatName, + string externalFileFormatSerDeMethod, + string externalFileFormatFieldTerminator, + string externalFileFormatStringDelimiter, + string externalFileFormatDateFormat) + { + + const string ExternalFileFormatTestName = "Delta External File Format Testing"; + + // + // Step 1. Create external file format with no required properties. + // + TraceHelper.TraceInformation("Step 1: {0} - Creating external file format {1} with no required properties.", ExternalFileFormatTestName, externalFileFormatName); + ExternalFileFormat externalFileFormat = new ExternalFileFormat(db, externalFileFormatName); + + string errorMessage = string.Empty; + + var ex = Assert.Throws(externalFileFormat.Create, "verify the external file format was not created due to unset FormatType"); + + // + // Step 2. Create external file format with conflicting properties - format type is Delta and SerDeMethod. + // + externalFileFormat.FormatType = ExternalFileFormatType.Delta; + externalFileFormat.SerDeMethod = externalFileFormatSerDeMethod; + + // attempt to create an external file format + ex = Assert.Throws(externalFileFormat.Create); + + // + // Step 3. Create external file format with conflicting properties - format type is Delta and FieldTerminator. + // + externalFileFormat.FormatType = ExternalFileFormatType.Delta; + externalFileFormat.SerDeMethod = string.Empty; + externalFileFormat.FieldTerminator = externalFileFormatFieldTerminator; + + // attempt to create an external file format + ex = Assert.Throws(externalFileFormat.Create); + + // + // Step 4. Create external file format with conflicting properties - format type is Delta and StringDelimiter. + // + externalFileFormat.FormatType = ExternalFileFormatType.Delta; + externalFileFormat.SerDeMethod = string.Empty; + externalFileFormat.FieldTerminator = string.Empty; + externalFileFormat.StringDelimiter = externalFileFormatStringDelimiter; + + // attempt to create an external file format + ex = Assert.Throws(externalFileFormat.Create); + + // + // Step 5. Create external file format with conflicting properties - format type Delta and DateFormat. + // + externalFileFormat.FormatType = ExternalFileFormatType.Delta; + externalFileFormat.SerDeMethod = string.Empty; + externalFileFormat.FieldTerminator = string.Empty; + externalFileFormat.StringDelimiter = string.Empty; + externalFileFormat.DateFormat = externalFileFormatDateFormat; + + // attempt to create an external file format + ex = Assert.Throws(externalFileFormat.Create); + + // + // Step 6. Create external file format with conflicting properties - format type is Delta and UseTypeDefault. + // + externalFileFormat.FormatType = ExternalFileFormatType.Delta; + externalFileFormat.SerDeMethod = string.Empty; + externalFileFormat.FieldTerminator = string.Empty; + externalFileFormat.StringDelimiter = string.Empty; + externalFileFormat.DateFormat = string.Empty; + externalFileFormat.UseTypeDefault = true; + + // attempt to create an external file format + ex = Assert.Throws(externalFileFormat.Create); } /// @@ -987,17 +868,18 @@ private void VerifyNegativeExternalFileFormatCreateDropHelper(Database db, /// /// /// - /// /// True if SQL DW DB. - private void ProcessOptionalProperties(ExternalFileFormat externalFileFormat, StringBuilder script, bool isSqlDw) + /// /// True if SQL DW or Serverless DB. + private void ProcessOptionalProperties(ExternalFileFormat externalFileFormat, StringBuilder script, bool isSqlDwOrServerless) { switch (externalFileFormat.FormatType) { case ExternalFileFormatType.DelimitedText: - ValidateDelimitedTextProperties(externalFileFormat, script, isSqlDw); + ValidateDelimitedTextProperties(externalFileFormat, script, isSqlDwOrServerless); break; case ExternalFileFormatType.Orc: case ExternalFileFormatType.Parquet: - ValidateOrcOrParquetProperties(externalFileFormat, script); + case ExternalFileFormatType.Delta: + ValidateOrcParquetOrDeltaProperties(externalFileFormat, script); break; case ExternalFileFormatType.RcFile: ValidateRcFileProperties(externalFileFormat, script); @@ -1014,18 +896,18 @@ private void ProcessOptionalProperties(ExternalFileFormat externalFileFormat, St /// /// External file format. /// The external file format T-SQL script. - /// True if SQL DW DB. - private void ValidateDelimitedTextProperties(ExternalFileFormat externalFileFormat, StringBuilder script, bool isSqlDw) + /// True if SQL DW or Serverless DB. + private void ValidateDelimitedTextProperties(ExternalFileFormat externalFileFormat, StringBuilder script, bool isSqlDwOrServerless) { // check for optional properties StringBuilder formatOptions = new StringBuilder(); // if format options optional properties are specified, they need to be enclosed in FORMAT_OPTIONS() - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.FieldTerminator, "FIELD_TERMINATOR = N'{0}'", formatOptions); - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.StringDelimiter, "STRING_DELIMITER = N'{0}'", formatOptions); - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.DateFormat, "DATE_FORMAT = N'{0}'", formatOptions); + VerifyOptionalFormatParameters(externalFileFormat.FieldTerminator, "FIELD_TERMINATOR = N'{0}'", formatOptions); + VerifyOptionalFormatParameters(externalFileFormat.StringDelimiter, "STRING_DELIMITER = N'{0}'", formatOptions); + VerifyOptionalFormatParameters(externalFileFormat.DateFormat, "DATE_FORMAT = N'{0}'", formatOptions); - if (isSqlDw && externalFileFormat.FirstRow > 1) + if (isSqlDwOrServerless && externalFileFormat.FirstRow > 1) { if (formatOptions.Length > 0) { @@ -1048,7 +930,7 @@ private void ValidateDelimitedTextProperties(ExternalFileFormat externalFileForm script.Append(string.Format(", FORMAT_OPTIONS ({0})", fileFormatOptions)); } - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); + VerifyOptionalFormatParameters(externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); } /// @@ -1057,10 +939,10 @@ private void ValidateDelimitedTextProperties(ExternalFileFormat externalFileForm /// /// External file format. /// The external file format T-SQL script. - private void ValidateOrcOrParquetProperties(ExternalFileFormat externalFileFormat, StringBuilder script) + private void ValidateOrcParquetOrDeltaProperties(ExternalFileFormat externalFileFormat, StringBuilder script) { // check for optional properties - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); + VerifyOptionalFormatParameters(externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); } /// @@ -1072,20 +954,19 @@ private void ValidateOrcOrParquetProperties(ExternalFileFormat externalFileForma private void ValidateRcFileProperties(ExternalFileFormat externalFileFormat, StringBuilder script) { // check for optional properties - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.SerDeMethod, "SERDE_METHOD = N'{0}'", script); + VerifyOptionalFormatParameters(externalFileFormat.SerDeMethod, "SERDE_METHOD = N'{0}'", script); - VerifyOptionalFormatParameters(externalFileFormat, externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); + VerifyOptionalFormatParameters(externalFileFormat.DataCompression, "DATA_COMPRESSION = N'{0}'", script); } /// /// Verifies format options optional properties and adds a comma to the generated script /// when more than one optional format properties exist. /// - /// External file format. /// The format options property value. /// The T-SQL script to add to the format options script. /// The T-SQL format options script. - private void VerifyOptionalFormatParameters(ExternalFileFormat externalFileFormat, string propertyValue, string sqlScript, StringBuilder formatOptions) + private void VerifyOptionalFormatParameters(string propertyValue, string sqlScript, StringBuilder formatOptions) { if (!string.IsNullOrEmpty(propertyValue)) { @@ -1114,6 +995,8 @@ private string GetSqlKeywordForFileFormatType(ExternalFileFormatType fileFormatT return "PARQUET"; case ExternalFileFormatType.RcFile: return "RCFILE"; + case ExternalFileFormatType.Delta: + return "DELTA"; default: Assert.AreEqual(ExternalFileFormatType.DelimitedText, fileFormatType); return "DELIMITEDTEXT"; diff --git a/src/FunctionalTest/Smo/ToolsConnectionInfo.xml b/src/FunctionalTest/Smo/ToolsConnectionInfo.xml index 0d5a7b54..0921c638 100644 --- a/src/FunctionalTest/Smo/ToolsConnectionInfo.xml +++ b/src/FunctionalTest/Smo/ToolsConnectionInfo.xml @@ -178,4 +178,3 @@ Sql2012;Sql2017;SQL2017Linux passwordCredential='saPassword-2017Linux' db_engine_edition="Enterprise"/> - diff --git a/src/FunctionalTest/Smo/XEvent/TargetColumnInfoUnitTest.cs b/src/FunctionalTest/Smo/XEvent/TargetColumnInfoUnitTest.cs index cbb5e314..e89461a8 100644 --- a/src/FunctionalTest/Smo/XEvent/TargetColumnInfoUnitTest.cs +++ b/src/FunctionalTest/Smo/XEvent/TargetColumnInfoUnitTest.cs @@ -115,7 +115,7 @@ public void TestTargetColumnCollectionContains() public void TestTargetColumnInfoSet() { var columns = store.EventFileTargetInfo.TargetColumnInfoSet.OfType().Select(c => c.Name); - Assert.That(columns, Is.EquivalentTo(new string[] { "external_telemetry_query", "filename", "increment", "is_indexed_file_target", "lazy_create_blob", "max_file_size", "max_rollover_files", "metadatafile"}), + Assert.That(columns, Is.EquivalentTo(new string[] { "add_app_name, external_telemetry_query", "filename", "increment", "is_indexed_file_target", "lazy_create_blob", "max_file_size", "max_rollover_files", "metadatafile"}), "Unexpected columns for file target"); } } diff --git a/src/FunctionalTest/Smo/XEvent/TargetUnitTest.cs b/src/FunctionalTest/Smo/XEvent/TargetUnitTest.cs index 1625ca15..eb872dde 100644 --- a/src/FunctionalTest/Smo/XEvent/TargetUnitTest.cs +++ b/src/FunctionalTest/Smo/XEvent/TargetUnitTest.cs @@ -244,7 +244,7 @@ public void TestTargetGetTargetFields() Assert.IsNotNull(target.TargetFields); //package0.event_file has 5 customizable fields //filename is set to "file" in this session - Assert.That(target.TargetFields.Count, Is.EqualTo(8), "TestTargetGetTargetFields event_file TargetFields.Count" ); // metadatafile is removed + Assert.That(target.TargetFields.Count, Is.EqualTo(9), "TestTargetGetTargetFields event_file TargetFields.Count" ); Assert.AreEqual("https://account.blob.core.windows.net/container/filename.xel", target.TargetFields["filename"].Value); //other fields are all in default value diff --git a/src/Microsoft/SqlServer/Management/ConnectionInfo/ConnectionEnums.cs b/src/Microsoft/SqlServer/Management/ConnectionInfo/ConnectionEnums.cs index c9d16552..56cef8e9 100644 --- a/src/Microsoft/SqlServer/Management/ConnectionInfo/ConnectionEnums.cs +++ b/src/Microsoft/SqlServer/Management/ConnectionInfo/ConnectionEnums.cs @@ -119,6 +119,10 @@ make sure to update both enums with any changes [CommonDisplayNameKey("SqlDatabaseEdgeEdition")] SqlDatabaseEdge = 0x000009, + ///The server is an Azure Arc Managed SQL Instance Edition + [CommonDisplayNameKey("SqlAzureArcManagedInstanceEdition")] + SqlAzureArcManagedInstance = 0x00000A, + ///The server is Sql SqlOnDemand [CommonDisplayNameKey("SqlOnDemandEdition")] SqlOnDemand = 0x00000B, @@ -373,6 +377,7 @@ public static IEnumerable GetSupportedDatabaseEngineEditi yield return DatabaseEngineEdition.Standard; yield return DatabaseEngineEdition.SqlStretchDatabase; yield return DatabaseEngineEdition.SqlManagedInstance; + yield return DatabaseEngineEdition.SqlAzureArcManagedInstance; yield return DatabaseEngineEdition.SqlDatabaseEdge; break; default: diff --git a/src/Microsoft/SqlServer/Management/ConnectionInfo/StringConnectionInfo.strings b/src/Microsoft/SqlServer/Management/ConnectionInfo/StringConnectionInfo.strings index b6153b08..acaef538 100644 --- a/src/Microsoft/SqlServer/Management/ConnectionInfo/StringConnectionInfo.strings +++ b/src/Microsoft/SqlServer/Management/ConnectionInfo/StringConnectionInfo.strings @@ -53,6 +53,7 @@ StretchEdition = Microsoft SQL Server Stretch Database Edition SqlManagedInstanceEdition = Microsoft Azure SQL Database Managed Instance Edition SqlOnDemandEdition = Microsoft Azure Synapse SQL Analytics on-demand Edition SqlDatabaseEdgeEdition = Microsoft Azure SQL Edge Edition +SqlAzureArcManagedInstanceEdition = Microsoft Azure Arc SQL Managed Instance Edition # # Database Engine Type Names diff --git a/src/Microsoft/SqlServer/Management/Sdk/Sfc/Enumerator/XmlRead.cs b/src/Microsoft/SqlServer/Management/Sdk/Sfc/Enumerator/XmlRead.cs index 23f95a5c..5249e8f8 100644 --- a/src/Microsoft/SqlServer/Management/Sdk/Sfc/Enumerator/XmlRead.cs +++ b/src/Microsoft/SqlServer/Management/Sdk/Sfc/Enumerator/XmlRead.cs @@ -1644,7 +1644,7 @@ override public bool Next() /// ///class to read a special query [ComVisible(false)] - public class XmlReadSpecialQuery : XmlRead + public class XmlReadSpecialQuery : XmlReadConditionedStatement { /// ///initialize with reader @@ -1661,9 +1661,13 @@ public string Database /// ///get attribute - query - public String Query + public string Query { - get { return this.Reader["query"]; } + get { return Sql; } + } + public override bool Next() + { + return Next("special_query"); } } } diff --git a/src/Microsoft/SqlServer/Management/Smo/DatabaseBase.cs b/src/Microsoft/SqlServer/Management/Smo/DatabaseBase.cs index cb7ba288..fcec4e2f 100644 --- a/src/Microsoft/SqlServer/Management/Smo/DatabaseBase.cs +++ b/src/Microsoft/SqlServer/Management/Smo/DatabaseBase.cs @@ -27,9 +27,9 @@ namespace Microsoft.SqlServer.Management.Smo { [Facets.EvaluationMode(Dmf.AutomatedPolicyEvaluationMode.CheckOnSchedule)] - [Microsoft.SqlServer.Management.Sdk.Sfc.PhysicalFacet] - public partial class Database : ScriptNameObjectBase, Cmn.ICreatable, Cmn.IAlterable, Cmn.IDroppable, Cmn.IDropIfExists, - Cmn.ISafeRenamable, IExtendedProperties, IScriptable, IDatabaseOptions + [PhysicalFacet] + public partial class Database : ScriptNameObjectBase, ICreatable, IAlterable, IDroppable, IDropIfExists, + ISafeRenamable, IExtendedProperties, IScriptable, IDatabaseOptions { internal Database(AbstractCollectionBase parentColl, ObjectKeyBase key, SqlSmoState state) : base(parentColl, key, state) @@ -419,7 +419,9 @@ internal override void ScriptCreate(StringCollection createQuery, ScriptingPrefe var emptyFileGroups = new StringCollection(); var isAzureDb = Cmn.DatabaseEngineType.SqlAzureDatabase == sp.TargetDatabaseEngineType; var bSuppressDirtyCheck = sp.SuppressDirtyCheck; - var targetEditionIsManagedServer = !isAzureDb && sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlManagedInstance; + var targetEditionIsManagedServer = !isAzureDb && + (sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlManagedInstance || + sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlAzureArcManagedInstance); if (IsSupportedProperty("DatabaseSnapshotBaseName")) { @@ -1102,8 +1104,9 @@ private void AddCompatibilityLevel(StringCollection query, ScriptingPreferences Property propCompat = Properties.Get("CompatibilityLevel"); if (null != propCompat.Value && (propCompat.Dirty || !sp.ScriptForAlter)) { - bool isTargetSqlAzureOrMI = (sp.TargetDatabaseEngineType == DatabaseEngineType.SqlAzureDatabase) || - (sp.TargetDatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance); + bool isTargetSqlAzureOrMIOrMIAA = (sp.TargetDatabaseEngineType == DatabaseEngineType.SqlAzureDatabase) || + (sp.TargetDatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance) || + (sp.TargetDatabaseEngineEdition == DatabaseEngineEdition.SqlAzureArcManagedInstance); bool isVersion160WithCompatLevelLessThan160 = (sp.TargetServerVersionInternal == SqlServerVersionInternal.Version160) && @@ -1156,11 +1159,11 @@ private void AddCompatibilityLevel(StringCollection query, ScriptingPreferences isVersion140WithCompatLevelLessThan140 || isVersion150WithCompatLevelLessThan150 || isVersion160WithCompatLevelLessThan160 || - isTargetSqlAzureOrMI; + isTargetSqlAzureOrMIOrMIAA; //script only if compatibility level is less than the target server // on Alter() we just script it and let the server fail if it is not correct - if (IsSupportedProperty("CompatibilityLevel", sp) && (sp.ScriptForAlter || isVersionWithLowerCompatLevel || isVersion80Or90WithLowerCompatLevel || isTargetSqlAzureOrMI)) + if (IsSupportedProperty("CompatibilityLevel", sp) && (sp.ScriptForAlter || isVersionWithLowerCompatLevel || isVersion80Or90WithLowerCompatLevel)) { CompatibilityLevel upgradedCompatLevel = UpgradeCompatibilityValueIfRequired(sp, (CompatibilityLevel)propCompat.Value); if (isVersionWithLowerCompatLevel) @@ -1863,7 +1866,7 @@ private void ContainmentRelatedValidation(ScriptingPreferences sp) //If containment supported on source database, check the version and enginetype of target. if (this.IsSupportedProperty("ContainmentType")) { - ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); + ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); if (cType == ContainmentType.None) { @@ -2529,11 +2532,11 @@ public System.Boolean DatabaseOwnershipChaining /// Gets or sets the MD Catalog Collation type. Only valid during creation, and we cannot specify ContainedDatabaseCollation explicitly /// [SfcProperty(SfcPropertyFlags.ReadOnlyAfterCreation | SfcPropertyFlags.SqlAzureDatabase)] - public Microsoft.SqlServer.Management.Smo.CatalogCollationType CatalogCollation + public CatalogCollationType CatalogCollation { get { - return (Microsoft.SqlServer.Management.Smo.CatalogCollationType)this.Properties.GetValueWithNullReplacement("CatalogCollation"); + return (CatalogCollationType)this.Properties.GetValueWithNullReplacement("CatalogCollation"); } set { @@ -5809,7 +5812,7 @@ public UrnInfo(string urnType, bool hasSchema, bool hasName, DatabaseObjectTypes } /// - /// The ListObjects method returns a SQLObjectList object that enumerates the system and user-defined objects defining the database referenced. + /// The EnumObjects method returns a DataTable that enumerates the system and user-defined objects defining the database referenced. /// /// /// @@ -5931,10 +5934,10 @@ public DataTable EnumObjects(DatabaseObjectTypes types, SortOrder order) finalQuery.Append(" ORDER BY "); switch (order) { - case SortOrder.Name: finalQuery.Append("Name"); break; - case SortOrder.Schema: finalQuery.Append("Schema"); break; - case SortOrder.Type: finalQuery.Append("DatabaseObjectTypes"); break; - default: finalQuery.Append("Urn"); break; + case SortOrder.Name: finalQuery.Append("[Name]"); break; + case SortOrder.Schema: finalQuery.Append("[Schema]"); break; + case SortOrder.Type: finalQuery.Append("[DatabaseObjectTypes]"); break; + default: finalQuery.Append("[Urn]"); break; } finalQuery.Append("\ndrop table #t"); @@ -5996,9 +5999,9 @@ public void TruncateLog() /// If true this means only header and body are needed, otherwise all properties /// internal static string[] GetScriptFields(Type parentType, - Cmn.ServerVersion version, - Cmn.DatabaseEngineType databaseEngineType, - Cmn.DatabaseEngineEdition databaseEngineEdition, + ServerVersion version, + DatabaseEngineType databaseEngineType, + DatabaseEngineEdition databaseEngineEdition, bool defaultTextMode) { string[] fields = @@ -6012,12 +6015,12 @@ internal static string[] GetScriptFields(Type parentType, nameof(IsLedger), nameof(PersistentVersionStoreFileGroup) }; - List list = GetSupportedScriptFields(typeof(Database.PropertyMetadataProvider),fields, version, databaseEngineType, databaseEngineEdition); + List list = GetSupportedScriptFields(typeof(PropertyMetadataProvider),fields, version, databaseEngineType, databaseEngineEdition); return list.ToArray(); } - internal static string[] GetScriptFields2(Type parentType, Cmn.ServerVersion version, - Cmn.DatabaseEngineType databaseEngineType, Cmn.DatabaseEngineEdition databaseEngineEdition, + internal static string[] GetScriptFields2(Type parentType, ServerVersion version, + DatabaseEngineType databaseEngineType, DatabaseEngineEdition databaseEngineEdition, bool defaultTextMode, ScriptingPreferences sp) { string[] fields = @@ -6026,7 +6029,7 @@ internal static string[] GetScriptFields2(Type parentType, Cmn.ServerVersion ver "IsMirroringEnabled", "IsVarDecimalStorageFormatEnabled", }; - List list = GetSupportedScriptFields(typeof(Database.PropertyMetadataProvider), fields, version, databaseEngineType, databaseEngineEdition); + List list = GetSupportedScriptFields(typeof(PropertyMetadataProvider), fields, version, databaseEngineType, databaseEngineEdition); return list.ToArray(); } @@ -6039,9 +6042,9 @@ public System.Boolean IsVarDecimalStorageFormatSupported { // vardecimal is supported in SQL Server 2005, SP2 and later, for Enterprise Edition only. // vardecimal will be replaced by a different compression feature in Katmai - System.Version yukonSp2 = new System.Version(9, 0, 3003); + Version yukonSp2 = new Version(9, 0, 3003); - System.Version thisversion = new System.Version( + Version thisversion = new Version( this.Parent.ConnectionContext.ServerVersion.Major, this.Parent.ConnectionContext.ServerVersion.Minor, this.Parent.ConnectionContext.ServerVersion.BuildNumber); @@ -6056,6 +6059,7 @@ public System.Boolean IsVarDecimalStorageFormatSupported return (thisversion > yukonSp2) && (this.Parent.Information.EngineEdition == Edition.EnterpriseOrDeveloper || this.Parent.Information.EngineEdition == Edition.SqlManagedInstance || + this.Parent.Information.EngineEdition == Edition.SqlAzureArcManagedInstance || this.Parent.Information.EngineEdition == Edition.SqlDatabaseEdge); } } @@ -6386,7 +6390,9 @@ public void InitTableColumns() } private void ScriptDbOptionsProps(StringCollection query, ScriptingPreferences sp, bool isAzureDb) { - var targetEditionIsManagedServer = sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlManagedInstance; + var targetEditionIsManagedServer = + ((sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlManagedInstance) || + (sp.TargetDatabaseEngineEdition == Cmn.DatabaseEngineEdition.SqlAzureArcManagedInstance)); ScriptAlterPropBool("AnsiNullDefault", "ANSI_NULL_DEFAULT", sp, query); ScriptAlterPropBool("AnsiNullsEnabled", "ANSI_NULLS", sp, query); @@ -6546,7 +6552,7 @@ private void ScriptDbOptionsProps(StringCollection query, ScriptingPreferences s if (this.IsSupportedProperty("ContainmentType", sp) && !targetEditionIsManagedServer) { - ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); + ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); if (cType != ContainmentType.None) { this.AddDefaultLanguageOption("DefaultFullTextLanguageName", "DefaultFullTextLanguageLcid", @@ -6737,7 +6743,8 @@ internal void ScriptAlterPropReadonly(StringCollection query, ScriptingPreferenc if (IsSupportedProperty(nameof(ReadOnly)) && IsSupportedProperty(nameof(ReadOnly), sp) && sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlDataWarehouse && - sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlManagedInstance) + sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlManagedInstance && + sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlAzureArcManagedInstance) { // Specify READONLY or READWRITE based on the readonlyMode passed in, ignoring alters for dirty-only, etc. ScriptAlterPropBool("ReadOnly", "", sp, query, readonlyMode ? "READ_ONLY" : "READ_WRITE"); @@ -6775,7 +6782,7 @@ void ScriptAlterContainmentDDL(ScriptingPreferences sp, StringCollection queries { if (this.IsSupportedProperty("ContainmentType", sp)) { - ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); + ContainmentType cType = this.GetPropValueOptional("ContainmentType", ContainmentType.None); switch (cType) { case ContainmentType.None: @@ -7071,5 +7078,31 @@ public void CleanupPersistentVersionStore() { ExecuteNonQuery($"exec sys.sp_persistent_version_cleanup {MakeSqlBraket(Name)}"); } + + /// + /// Populates the object's property bag from the current row of the DataReader + /// + /// + /// If true do not initialize the property if it has + /// been changed by the user + /// Index of the first column + /// Index of the last column. If -1 then go to the end. + internal override void AddObjectPropsFromDataReader(IDataReader reader, bool skipIfDirty, + int startColIdx, int endColIdx) + { + // We need the DatabaseEngineEdition for initializing the properties list for a Database, but this + // can cause problems on Azure servers since getting the EngineEdition requires logging into the + // database itself which is something we want to avoid for serverless databases or inaccessible + // databases. So to avoid that we prepopulate the edition by checking if it's DW beforehand (which + // doesn't require connecting to the database to retrieve) + if (m_edition == null && this.Parent.DatabaseEngineType == DatabaseEngineType.SqlAzureDatabase) + { + if (reader.GetSchemaTable().Rows.Cast().FirstOrDefault(r=> (string)r["ColumnName"] == "RealEngineEdition") != null) + { + this.m_edition = (DatabaseEngineEdition)reader["RealEngineEdition"]; + } + } + base.AddObjectPropsFromDataReader(reader, skipIfDirty, startColIdx, endColIdx); + } } } diff --git a/src/Microsoft/SqlServer/Management/Smo/ExternalFileFormatBase.cs b/src/Microsoft/SqlServer/Management/Smo/ExternalFileFormatBase.cs index d3f6908e..6b201347 100644 --- a/src/Microsoft/SqlServer/Management/Smo/ExternalFileFormatBase.cs +++ b/src/Microsoft/SqlServer/Management/Smo/ExternalFileFormatBase.cs @@ -164,7 +164,7 @@ internal override void ScriptCreate(StringCollection createQuery, ScriptingPrefe this.ThrowIfNotSupported(typeof(ExternalFileFormat), sp); /* CREATE EXTERNAL FILE FORMAT external_file_format_name WITH - * (FORMAT_TYPE = { DELIMITEDTEXT | RCFILE | ORC | PARQUET | JSON } + * (FORMAT_TYPE = { DELIMITEDTEXT | RCFILE | ORC | PARQUET | JSON | DELTA } * ,[SERDE_METHOD = 'Serialization/Deserialization method'] * ,[FORMAT_OPTIONS ( [ ,...n ] )] * ,[DATA_COMPRESSION = 'data_compression_method'] @@ -219,9 +219,6 @@ internal override void ScriptCreate(StringCollection createQuery, ScriptingPrefe sb.Append(Globals.LParen); sb.AppendFormat(SmoApplication.DefaultCulture, "FORMAT_TYPE = {0}", typeConverter.ConvertToInvariantString(externalFileFormatType)); - // check for conflicting properties - CheckConflictingProperties(sp); - // add any optional properties if they are set ProcessOptionalProperties(externalFileFormatType, sb, sp); @@ -257,122 +254,6 @@ private void AddPropertyToScript(string propertyValue, string sqlString, StringB fileFormatOptions.AppendFormat(SmoApplication.DefaultCulture, sqlString, propertyValue); } - /// - /// Checks for conflicting properties for the specified external file format type. - /// If a conflicting configuration is detected, throws an exception. - /// - private void CheckConflictingProperties(ScriptingPreferences sp) - { - const string FormatTypePropertyName = "FormatType"; - const string SerDeMethodPropertyName = "SerDeMethod"; - const string FieldTerminatorPropertyName = "FieldTerminator"; - const string StringDelimiterPropertyName = "StringDelimiter"; - const string DateFormatPropertyName = "DateFormat"; - const string UseTypeDefaultPropertyName = "UseTypeDefault"; - - // confirm that for each of the file format types, - // correct optional properties are specified, if any - // ensure that the format type property has a value - if (IsSupportedProperty(FormatTypePropertyName, sp)) - { - Property formatTypeProp = this.GetPropertyOptional(FormatTypePropertyName); - if (!formatTypeProp.IsNull) - { - Property prop = null; - - // if the format type is either delimited text, orc, parquet, or json then the serde method property is not supported - if ((ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.DelimitedText || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.Orc || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.Parquet || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.JSON) - { - // check the serde method property - // if it is specified and not a default, throw an exception - if (IsSupportedProperty(SerDeMethodPropertyName, sp)) - { - prop = this.GetPropertyOptional(SerDeMethodPropertyName); - if (!prop.IsNull) - { - // if the property is set to something other than its default value, throw an exception - if (!IsPropertyDefaultValue(prop, (string)prop.Value, new List { null, string.Empty })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - } - - // if the format type is rcfile, orc, parquet or json then the format options properties are not supported - if ((ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.RcFile || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.Orc || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.Parquet || - (ExternalFileFormatType)formatTypeProp.Value == ExternalFileFormatType.JSON) - { - // check the format options properties - // if any of them are specified, throw an exception - if (IsSupportedProperty(FieldTerminatorPropertyName, sp)) - { - prop = this.GetPropertyOptional(FieldTerminatorPropertyName); - if (!prop.IsNull) - { - if (!IsPropertyDefaultValue(prop, (string)prop.Value, new List { null, string.Empty })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - - if (IsSupportedProperty(StringDelimiterPropertyName, sp)) - { - prop = this.GetPropertyOptional(StringDelimiterPropertyName); - if (!prop.IsNull) - { - if (!IsPropertyDefaultValue(prop, (string)prop.Value, new List { null, string.Empty })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - - if (IsSupportedProperty(DateFormatPropertyName, sp)) - { - prop = this.GetPropertyOptional(DateFormatPropertyName); - if (!prop.IsNull) - { - if (!IsPropertyDefaultValue(prop, (string)prop.Value, new List { null, string.Empty })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - - if (IsSupportedProperty(UseTypeDefaultPropertyName, sp)) - { - prop = this.GetPropertyOptional(UseTypeDefaultPropertyName); - if (!prop.IsNull) - { - if (!IsPropertyDefaultValue(prop, (bool)prop.Value, new List { false })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - - if (IsSupportedProperty(FirstRowName, sp)) - { - prop = this.GetPropertyOptional(FirstRowName); - if (!prop.IsNull) - { - if (!IsPropertyDefaultValue(prop, (int)prop.Value, new List { 0 })) - { - throw new SmoException(string.Format(SmoApplication.DefaultCulture, ExceptionTemplates.ConflictingExternalFileFormatProperties, prop.Name, prop.Value.ToString(), formatTypeProp.Value.ToString())); - } - } - } - } - } - } - } /// /// Check the specified property if it has the default value. @@ -409,42 +290,19 @@ private bool IsPropertyDefaultValue(Property prop, T value, List defaultVa /// The scripting preferences. private void ProcessOptionalProperties(ExternalFileFormatType externalFileFormatType, StringBuilder script, ScriptingPreferences sp) { - // check the optional properties are supported by the specified format type - switch (externalFileFormatType) - { - case ExternalFileFormatType.DelimitedText: - ValidateDelimitedTextProperties(script, sp); - break; - case ExternalFileFormatType.JSON: - case ExternalFileFormatType.Orc: - case ExternalFileFormatType.Parquet: - ValidateOrcOrParquetProperties(script, sp); - break; - case ExternalFileFormatType.RcFile: - ValidateRcFileProperties(script, sp); - break; - default: - // if the format type set to any other value throw an exception - throw new WrongPropertyValueException(ExceptionTemplates.UnknownEnumeration(externalFileFormatType.ToString())); - } - } - - /// - /// Validates optional properties for the DelimtedText file format - /// and adds them to the T-SQL script. - /// - /// The external file format T-SQL script. - /// The scripting preferences. - private void ValidateDelimitedTextProperties(StringBuilder script, ScriptingPreferences sp) - { - const string UseTypeDefaultPropertyName = "UseTypeDefault"; - // check for the DelimitedText supported optional properties - FormatOptions and DataCompression // check for any format options optinal parameters - FieldTerminator, StringDelimiter, DateFormat and UseTypeDefault // if any are found, add them to the T-SQL script StringBuilder formatOptions = new StringBuilder(Globals.INIT_BUFFER_SIZE); List defaultValues = new List { null, string.Empty }; + const string UseTypeDefaultPropertyName = "UseTypeDefault"; + + + // check if the serde method property was set + // if yes, add it to the script + ValidateOptionalProperty("SerDeMethod", "SERDE_METHOD = {0}", defaultValues, script, sp); + // validate and process the field terminator file format option ValidateOptionalProperty("FieldTerminator", "FIELD_TERMINATOR = {0}", defaultValues, formatOptions, sp); @@ -455,23 +313,31 @@ private void ValidateDelimitedTextProperties(StringBuilder script, ScriptingPref ValidateOptionalProperty("DateFormat", "DATE_FORMAT = {0}", defaultValues, formatOptions, sp); // validate and process the first row optional file format property - ValidateOptionalProperty(FirstRowName, "FIRST_ROW = {0}", new List { 1 }, formatOptions, sp, quotePropertyValue: false); + // for delimited text default value is 1, and for the rest the default value is 0. + if (externalFileFormatType == ExternalFileFormatType.DelimitedText) + { + ValidateOptionalProperty(FirstRowName, "FIRST_ROW = {0}", new List { 1 }, formatOptions, sp, quotePropertyValue: false); + } else + { + ValidateOptionalProperty(FirstRowName, "FIRST_ROW = {0}", new List { 0 }, formatOptions, sp, quotePropertyValue: false); + } // validate and process the use type default file format option if (IsSupportedProperty(UseTypeDefaultPropertyName, sp)) { - if (!this.GetPropertyOptional(UseTypeDefaultPropertyName).IsNull) + var prop = this.GetPropertyOptional(UseTypeDefaultPropertyName); + // property is ignored if it's null or has default value + if(!prop.IsNull && (externalFileFormatType == ExternalFileFormatType.DelimitedText || !IsPropertyDefaultValue(prop, (bool)prop.Value, new List { false }))) { bool externalFileFormatUseTypeDefault = (bool)this.GetPropValueOptional(UseTypeDefaultPropertyName); - if (formatOptions.Length > 0) { formatOptions.Append(", "); } - - formatOptions.AppendFormat(SmoApplication.DefaultCulture, "USE_TYPE_DEFAULT = {0}", externalFileFormatUseTypeDefault); + formatOptions.AppendFormat(SmoApplication.DefaultCulture, "USE_TYPE_DEFAULT = {0}", externalFileFormatUseTypeDefault); } } + // if any format options were specified, add the FORMAT_OPTIONS and enclose them in the parenthesis string fileFormatOptions = formatOptions.ToString(); @@ -515,12 +381,12 @@ private void ValidateOptionalProperty(string propertyName, string sqlString, } /// - /// Validates optional properties for the Orc or Parquet file format + /// Validates optional properties for the JSON, Orc, Parquet or Delta file format /// and adds them to the T-SQL script. /// /// The external file format T-SQL script. /// The scripting preferences. - private void ValidateOrcOrParquetProperties(StringBuilder script, ScriptingPreferences sp) + private void ValidateOrcParquetJsonOrDeltaProperties(StringBuilder script, ScriptingPreferences sp) { List defaultValues = new List { null, string.Empty }; diff --git a/src/Microsoft/SqlServer/Management/Smo/Microsoft.SqlServer.Smo.csproj b/src/Microsoft/SqlServer/Management/Smo/Microsoft.SqlServer.Smo.csproj index 911e5b39..fbeddbcc 100644 --- a/src/Microsoft/SqlServer/Management/Smo/Microsoft.SqlServer.Smo.csproj +++ b/src/Microsoft/SqlServer/Management/Smo/Microsoft.SqlServer.Smo.csproj @@ -669,4 +669,3 @@ - diff --git a/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs b/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs index 77a78611..fff27657 100644 --- a/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs +++ b/src/Microsoft/SqlServer/Management/Smo/SqlSmoObject.cs @@ -1764,7 +1764,7 @@ internal void AddObjectPropsFromDataReader(System.Data.IDataReader reader, bool /// been changed by the user /// Index of the first column /// Index of the last column. If -1 then go to the end. - internal void AddObjectPropsFromDataReader(System.Data.IDataReader reader, bool skipIfDirty, + internal virtual void AddObjectPropsFromDataReader(System.Data.IDataReader reader, bool skipIfDirty, int startColIdx, int endColIdx) { var schemaTable = reader.GetSchemaTable(); @@ -4263,6 +4263,11 @@ public IEnumerable GetDisabledProperties(ScriptingPreferences sp = null) yield return nameof(Index.IsSpatialIndex); yield return nameof(Server.Configuration.ContainmentEnabled); } + if (((sp != null && sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlOnDemand) || this.DatabaseEngineEdition != DatabaseEngineEdition.SqlOnDemand) && + ((sp != null && sp.TargetDatabaseEngineEdition != DatabaseEngineEdition.SqlDataWarehouse) || this.DatabaseEngineEdition != DatabaseEngineEdition.SqlDataWarehouse)) + { + yield return nameof(ExternalFileFormat.FirstRow); + } if ((sp != null && sp.TargetDatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand) || this.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand) { yield return nameof(Database.AutoClose); diff --git a/src/Microsoft/SqlServer/Management/Smo/enumerations.cs b/src/Microsoft/SqlServer/Management/Smo/enumerations.cs index 737dc481..5b8a4abb 100644 --- a/src/Microsoft/SqlServer/Management/Smo/enumerations.cs +++ b/src/Microsoft/SqlServer/Management/Smo/enumerations.cs @@ -419,12 +419,14 @@ make sure to update both enums with any changes SqlManagedInstance = 0x000008, ///The server is a SQL Edge Instance SqlDatabaseEdge = 0x000009, + ///The server is an Azure Arc Managed SQL Instance + SqlAzureArcManagedInstance = 0x00000A, ///The server is SQL SqlOnDemand SqlOnDemand = 0x00000B, /* * NOTE: If you're adding new value here, * please update as well ScriptDatabaseEngineEdition enum - * in Sql\ssms\extensions\synthesis\NextGenDPW\SqlScriptPublishModel\SqlScriptOptions.cs + * in src\Microsoft\SqlServer\Management\SqlScriptPublish\SqlScriptOptions.cs */ } diff --git a/src/Microsoft/SqlServer/Management/Smo/serverbase.cs b/src/Microsoft/SqlServer/Management/Smo/serverbase.cs index ab090cb4..b55dab29 100644 --- a/src/Microsoft/SqlServer/Management/Smo/serverbase.cs +++ b/src/Microsoft/SqlServer/Management/Smo/serverbase.cs @@ -3089,8 +3089,6 @@ private StringCollection CreateInitFieldsColl(Type typeObject) // but we need them at runtime when we initialize the object, and we'd // rather have them in the collection for performance consideration - // TODO: FIX_IN_KATMAI: Why does Server need to know about all of its children? Delegate the call to the child. - if (typeObject.IsSubclassOf(typeof(ScriptSchemaObjectBase))) { fields.Add("Schema"); @@ -3131,6 +3129,17 @@ private StringCollection CreateInitFieldsColl(Type typeObject) fields.Add("CategoryID"); fields.Add("JobID"); } + else if (typeObject == typeof(Database)) + { + fields.Add(nameof(Database.Name)); + // If we are connected to an OnDemand or DataWarehouse instance through the ServerConnection + // the Database can only be the same edition as the ServerConnection. + // If we are connected to logical master then Database can have a different edition, so + // add RealEngineEdition to the query so we get the edition from sys.database_service_objectives + if (DatabaseEngineEdition == DatabaseEngineEdition.SqlDatabase) { + fields.Add("RealEngineEdition"); + } + } else if (typeObject.IsSubclassOf(typeof(NamedSmoObject))) { fields.Add("Name"); diff --git a/src/Microsoft/SqlServer/Management/Smo/tablebase.cs b/src/Microsoft/SqlServer/Management/Smo/tablebase.cs index 2434525f..06eb9648 100644 --- a/src/Microsoft/SqlServer/Management/Smo/tablebase.cs +++ b/src/Microsoft/SqlServer/Management/Smo/tablebase.cs @@ -642,7 +642,6 @@ internal override void ScriptCreate(StringCollection queries, ScriptingPreferenc } bool fAnsiNullsExists = false; - bool fQuotedIdentifierExists = false; bool ansiPaddingStatus = false; if (Cmn.DatabaseEngineType.SqlAzureDatabase != this.DatabaseEngineType) @@ -676,14 +675,10 @@ internal override void ScriptCreate(StringCollection queries, ScriptingPreferenc sb.Length = 0; } - fQuotedIdentifierExists = (null != Properties.Get("QuotedIdentifierStatus").Value); - if (fQuotedIdentifierExists) - { - sb.AppendFormat(SmoApplication.DefaultCulture, Scripts.SET_QUOTED_IDENTIFIER, - (bool)Properties["QuotedIdentifierStatus"].Value ? Globals.On : Globals.Off); - scqueries.Add(sb.ToString()); - sb.Length = 0; - } + // QUOTED_IDENTIFIER in Tables metadata is always ON + sb.AppendFormat(SmoApplication.DefaultCulture, Scripts.SET_QUOTED_IDENTIFIER, Globals.On); + scqueries.Add(sb.ToString()); + sb.Length = 0; } // set the ANSI_PADDING only if the table creation script @@ -2301,22 +2296,12 @@ private void ProcessSqlDwTableProperties(StringBuilder script, ScriptingPreferen { case DwTableDistributionType.Hash: - // get the distribution column name - var distributionColumnNameList = new List(); - - foreach (Column col in this.Columns) - { - if (col.GetPropValueOptional(IsDistributedColumnPropertyName, false)) - { - distributionColumnNameList.Add(col.GetPropValueOptional(DistributionColumnNamePropertyName, string.Empty)); - break; - } - } - - string distributionColumnNames = string.Join(",", distributionColumnNameList.Select(x => MakeSqlBraket(x))); - string distributionWithDistributionColName = string.Format("{0} ( {1} )", - typeConverter.ConvertToInvariantString(distribution), - distributionColumnNames); + // get the distribution column names + var distributionColumnNames = string.Join(",", Columns.Cast() + .Where(col => col.GetPropValueOptional(IsDistributedColumnPropertyName, false)) + .Select(col => MakeSqlBraket(col.GetPropValueOptional(DistributionColumnNamePropertyName, string.Empty)))); + + var distributionWithDistributionColName = $"{typeConverter.ConvertToInvariantString(distribution)} ( {distributionColumnNames} )"; this.AddPropertyToScript(distributionWithDistributionColName, "DISTRIBUTION = {0}", script); break; @@ -4546,7 +4531,6 @@ internal static string[] GetScriptFields(Type parentType, "RejectSampleValue", "RejectType", "RejectValue", - "QuotedIdentifierStatus", "RemoteObjectName", "RemoteSchemaName", "ShardingColumnName", diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/SqlConditionedStatement.cs b/src/Microsoft/SqlServer/Management/SqlEnum/SqlConditionedStatement.cs index 6c9232a5..1934b848 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/SqlConditionedStatement.cs +++ b/src/Microsoft/SqlServer/Management/SqlEnum/SqlConditionedStatement.cs @@ -135,4 +135,29 @@ public override void AddHit(string field, SqlObjectBase obj, StatementBuilder sb sb.AddCondition(this.GetLocalSql(obj)); } } + + internal class SqlConditionedStatementWhereClause : SqlConditionedStatement + { + public SqlConditionedStatementWhereClause(XmlReadSpecialQuery xrcs) : base(xrcs) + { + } + + public static void AddAll(ConditionedSqlList list, XmlReadSpecialQuery xrcs) + { + if (null != xrcs) + { + do + { + list.Add(new SqlConditionedStatementWhereClause(xrcs)); + } + while (xrcs.Next()); + } + } + /// + ///add hit for field + public override void AddHit(string field, SqlObjectBase obj, StatementBuilder sb) + { + sb.AddWhere(this.GetLocalSql(obj)); + } + } } diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/SqlObject.cs b/src/Microsoft/SqlServer/Management/SqlEnum/SqlObject.cs index 0dc56748..33840ea3 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/SqlObject.cs +++ b/src/Microsoft/SqlServer/Management/SqlEnum/SqlObject.cs @@ -176,10 +176,20 @@ internal virtual void Load(XmlReadDoc xrd, Assembly assembly, StringCollection r xrobr.Close(); } - XmlReadSpecialQuery xrsq = xrs.SpecialQuery; + var xrsq = xrs.SpecialQuery; if (null != xrsq) { - this.AddSpecialQuery(xrsq.Database, xrsq.Query); + // Preserve original behavior - database-specific where clause + var database = xrsq.Database; + if (!string.IsNullOrEmpty(database)) + { + this.AddSpecialQuery(xrsq.Database, xrsq.Sql); + } + else + // Where clause based on Fields + { + SqlConditionedStatementWhereClause.AddAll(ConditionedSqlList, xrsq); + } this.AddQueryHint(xrsq.Hint); xrsq.Close(); } diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/XmlRead.CS b/src/Microsoft/SqlServer/Management/SqlEnum/XmlRead.CS index 9890354b..e63fa432 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/XmlRead.CS +++ b/src/Microsoft/SqlServer/Management/SqlEnum/XmlRead.CS @@ -18,6 +18,9 @@ namespace Microsoft.SqlServer.Management.Smo #endif using Microsoft.SqlServer.Management.Sdk.Sfc; using Microsoft.SqlServer.Management.Smo.SqlEnum; + using System.Collections.Generic; + using System.Text; + /// ///base class for parsing a xml configuration file [ComVisible(false)] @@ -305,23 +308,23 @@ namespace Microsoft.SqlServer.Management.Smo ///read a 'fields' entry ( list of fields separated by '#' ) static protected StringCollection GetFields(string fields) { - String fieldName = String.Empty; - StringCollection col = new StringCollection(); + var fieldName = new StringBuilder(); + var col = new StringCollection(); if( null != fields ) { - foreach(char c in fields) + foreach(var c in fields) { if( '#' == c ) { if( 0 < fieldName.Length ) { - col.Add(fieldName); + col.Add(fieldName.ToString()); } - fieldName = String.Empty; + fieldName = new StringBuilder(); continue; } - fieldName += c; + fieldName.Append(c); } } return col; @@ -329,7 +332,7 @@ namespace Microsoft.SqlServer.Management.Smo /// ///reads the text of the current element if available - ///it assumes the curent element is empty or has inside it either a text node or + ///it assumes the current element is empty or has inside it either a text node or ///an element node. probably a link_multiple. protected string GetTextOfElement() { @@ -349,7 +352,7 @@ namespace Microsoft.SqlServer.Management.Smo //we found text if( XmlNodeType.Text == this.Reader.NodeType ) { - //so get it's value + //so get its value return this.Reader.Value; } } @@ -1759,7 +1762,7 @@ namespace Microsoft.SqlServer.Management.Smo /// ///class to read a special query [ComVisible(false)] - internal class XmlReadSpecialQuery : XmlRead + internal class XmlReadSpecialQuery : XmlReadConditionedStatement { /// ///initialize with reader @@ -1774,12 +1777,6 @@ namespace Microsoft.SqlServer.Management.Smo get { return this.Reader["database"]; } } - /// - ///get attribute - query - public String Query - { - get { return this.Reader["query"]; } - } /// /// Used to get attribute 'query hint' @@ -1793,5 +1790,10 @@ namespace Microsoft.SqlServer.Management.Smo { get { return this.Reader["hint"]; } } + + public override bool Next() + { + return Next("special_query"); + } } } diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/enumstructs.cs b/src/Microsoft/SqlServer/Management/SqlEnum/enumstructs.cs index dcbab44c..e28edfeb 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/enumstructs.cs +++ b/src/Microsoft/SqlServer/Management/SqlEnum/enumstructs.cs @@ -339,12 +339,18 @@ public enum ExternalFileFormatType /// [TsqlSyntaxString("PARQUET")] Parquet = 3, - + /// /// JSON file format. /// [TsqlSyntaxString("JSON")] - JSON = 4 + JSON = 4, + + /// + /// DELTA file format. + /// + [TsqlSyntaxString("DELTA")] + Delta = 5 } /// @@ -3123,6 +3129,11 @@ public enum AuditActionType /// [TsqlSyntaxString("SENSITIVE_BATCH_COMPLETED_GROUP")] SensitiveBatchCompletedGroup, + /// + /// EXTGOV_OPERATION_GROUP + /// + [TsqlSyntaxString("EXTGOV_OPERATION_GROUP")] + ExternalGovernanceOperationGroup, } /// diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/permenum.cs b/src/Microsoft/SqlServer/Management/SqlEnum/permenum.cs index da275dcb..cafd8cca 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/permenum.cs +++ b/src/Microsoft/SqlServer/Management/SqlEnum/permenum.cs @@ -297,6 +297,50 @@ public enum DatabasePermissionSetValue [PermissionType("EAEE")] [PermissionName("EXECUTE ANY EXTERNAL ENDPOINT")] ExecuteAnyExternalEndpoint = 93, + [PermissionType("CRDS")] + [PermissionName("CREATE ANY DATABASE EVENT SESSION")] + CreateAnyDatabaseEventSession = 94, + [PermissionType("DRDS")] + [PermissionName("DROP ANY DATABASE EVENT SESSION")] + DropAnyDatabaseEventSession = 95, + [PermissionType("LDSO")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION OPTION")] + AlterAnyDatabaseEventSessionOption = 96, + [PermissionType("LDAE")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION ADD EVENT")] + AlterAnyDatabaseEventSessionAddEvent = 97, + [PermissionType("LDDE")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION DROP EVENT")] + AlterAnyDatabaseEventSessionDropEvent = 98, + + [PermissionType("EDES")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION ENABLE")] + AlterAnyDatabaseEventSessionEnable = 99, + + [PermissionType("DDES")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION DISABLE")] + AlterAnyDatabaseEventSessionDisable = 100, + + [PermissionType("LDAT")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION ADD TARGET")] + AlterAnyDatabaseEventSessionAddTarget = 101, + + [PermissionType("LDDT")] + [PermissionName("ALTER ANY DATABASE EVENT SESSION DROP TARGET")] + AlterAnyDatabaseEventSessionDropTarget = 102, + + [PermissionType("VWP")] + [PermissionName("VIEW PERFORMANCE DEFINITION")] + ViewPerformanceDefinition = 103, + + [PermissionType("VDSA")] + [PermissionName("VIEW DATABASE SECURITY AUDIT")] + ViewDatabaseSecurityAudit = 104, + + [PermissionType("ALC")] + [PermissionName("ALTER LEDGER CONFIGURATION")] + AlterLedgerConfiguration = 105, + } ///enum containing all possible ObjectPermissions @@ -485,7 +529,56 @@ public enum ServerPermissionSetValue ViewServerPerformanceState = 39, [PermissionType("VACD")] [PermissionName("VIEW ANY CRYPTOGRAPHICALLY SECURED DEFINITION")] - ViewAnyCryptographicallySecuredDefinition = 40 + ViewAnyCryptographicallySecuredDefinition = 40, + + [PermissionType("VAP")] + [PermissionName("VIEW ANY PERFORMANCE DEFINITION")] + ViewAnyPerformanceDefinition = 41, + + [PermissionType("CRES")] + [PermissionName("CREATE ANY EVENT SESSION")] + CreateAnyEventSession = 42, + + [PermissionType("DRES")] + [PermissionName("DROP ANY EVENT SESSION")] + DropAnyEventSession = 43, + + [PermissionType("LESO")] + [PermissionName("ALTER ANY EVENT SESSION OPTION")] + AlterAnyEventSessionOption = 44, + + [PermissionType("LSAE")] + [PermissionName("ALTER ANY EVENT SESSION ADD EVENT")] + AlterAnyEventSessionAddEvent = 45, + + [PermissionType("LSDE")] + [PermissionName("ALTER ANY EVENT SESSION DROP EVENT")] + AlterAnyEventSessionDropEvent = 46, + + [PermissionType("EES")] + [PermissionName("ALTER ANY EVENT SESSION ENABLE")] + AlterAnyEventSessionEnable = 47, + + [PermissionType("DES")] + [PermissionName("ALTER ANY EVENT SESSION DISABLE")] + AlterAnyEventSessionDisable = 48, + + [PermissionType("LSAT")] + [PermissionName("ALTER ANY EVENT SESSION ADD TARGET")] + AlterAnyEventSessionAddTarget = 49, + + [PermissionType("LSDT")] + [PermissionName("ALTER ANY EVENT SESSION DROP TARGET")] + AlterAnyEventSessionDropTarget = 50, + + [PermissionType("VEL")] + [PermissionName("VIEW ANY ERROR LOG")] + ViewAnyErrorLog = 51, + + [PermissionType("VSSA")] + [PermissionName("VIEW SERVER SECURITY AUDIT")] + ViewServerSecurityAudit = 52, + } ///encapsulates functions that translate from sql codes into enum used to represent the permissions diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/xml/Database.xml b/src/Microsoft/SqlServer/Management/SqlEnum/xml/Database.xml index 4656fd34..ac7dbc4c 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/xml/Database.xml +++ b/src/Microsoft/SqlServer/Management/SqlEnum/xml/Database.xml @@ -1,5 +1,5 @@ - + @@ -29,7 +29,7 @@ - + @@ -47,7 +47,7 @@ - dso.database_id = dtb.database_id + dso.database_id = dtb.database_id @@ -88,24 +88,26 @@ - - - create table #dso (database_id int primary key, isDw bit) + + + create table #dso (database_id int primary key, azureEdition sysname null, engineEdition int) + if serverproperty('EngineEdition') = 11 + BEGIN + insert into #dso select database_id, NULL, 11 from sys.databases + END + ELSE BEGIN TRY - insert into #dso select database_id, CAST( - case - when Edition = 'DataWarehouse' then cast(1 as bit) - else cast(0 as bit) - end - AS bit) from sys.database_service_objectives + exec sp_executesql N' + insert into #dso select database_id, edition, + case when edition = ''DataWarehouse'' then 6 else 5 end + from sys.database_service_objectives' END TRY BEGIN CATCH - insert into #dso select database_id, cast(0 as bit) from sys.databases + insert into #dso select database_id, N'', case when [name] = 'master' then 5 else 0 end from sys.databases END CATCH - - drop table #dso - @@ -154,6 +156,11 @@ + + + drop table #dso + + - + @@ -224,7 +231,10 @@ class_name='Microsoft.SqlServer.Management.Smo.PostProcessDatabaseInsideAttribs' triggered_fields='#DatabaseName7#'/> - + + + dso.engineEdition != 0 + @@ -251,7 +261,7 @@ dtb.status & <msparam>4194304</msparam> - + case when dtb.name in ('master') then 1 else dtb.is_distributor end (select schema_name()) @@ -263,10 +273,14 @@ ( case dtb.is_read_only when 1 then 0 else 1 end) + - ISNULL(dso.isDw, 0) + case when isnull(dso.engineEdition, 0) = 6 then 1 else 0 end + ISNULL(dso.azureEdition, N'') + case when dtb.name = 'master' then ISNULL(dso.engineEdition, 5) else ISNULL(dso.engineEdition, 0) end - + + ISNULL((select top 1 ftc.name from sys.fulltext_catalogs as ftc where ftc.is_default=1),N'') @@ -304,7 +318,7 @@ 0 - + dtb.is_ansi_null_default_on dtb.is_ansi_nulls_on @@ -333,7 +347,7 @@ dtb.compatibility_level dtb.is_read_committed_snapshot_on - + isnull(dtb.source_database_id, 0) (select count(1) from sys.databases dtbmir where dtbmir.source_database_id = dtb.database_id) @@ -439,7 +453,7 @@ - dtb.is_ledger_on + ISNULL(dtb.is_ledger_on, 0) @@ -531,8 +545,8 @@ - - DATABASEPROPERTYEX(dtb.name, 'Edition') + + CONVERT(float, DATABASEPROPERTYEX(dtb.Name, 'MaxSizeInBytes')) / 1024.0 / 1024.0 @@ -540,12 +554,13 @@ (CASE WHEN 0 > CONVERT(float, DATABASEPROPERTYEX(dtb.Name, 'MaxSizeInBytes')) THEN 0 ELSE 1 END) - + (SELECT IIF(databasepropertyex(dtb.name,'Edition') = 'Hyperscale', 0, (SELECT ((CAST(DATABASEPROPERTYEX(dtb.Name, 'MaxSizeInBytes') AS float) / 1024.0) - (SUM(reserved_page_count)*8.0 )) / 1024.0 FROM sys.dm_db_partition_stats))) 0 + N'DataWarehouse' @@ -556,7 +571,7 @@ CHARINDEX(N'_CS_', CAST(DATABASEPROPERTYEX(dtb.name, 'Collation') AS nvarchar(255))) - + case when CHARINDEX(N'_CS_', dtb.collation_name) > 0 then 1 when CHARINDEX(N'_BIN', dtb.collation_name) > 0 then 1 @@ -622,7 +637,7 @@ - + 0 0 diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/xml/ExternalFileFormat.xml b/src/Microsoft/SqlServer/Management/SqlEnum/xml/ExternalFileFormat.xml index f62a9aa2..ff24944b 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/xml/ExternalFileFormat.xml +++ b/src/Microsoft/SqlServer/Management/SqlEnum/xml/ExternalFileFormat.xml @@ -9,7 +9,7 @@ eff.name eff.file_format_id - CASE eff.format_type when 'DELIMITEDTEXT' then 0 when 'RCFILE' then 1 when 'ORC' then 2 when 'PARQUET' then 3 when 'JSON' then 4 END + CASE eff.format_type when 'DELIMITEDTEXT' then 0 when 'RCFILE' then 1 when 'ORC' then 2 when 'PARQUET' then 3 when 'JSON' then 4 when 'DELTA' then 5 END ISNULL(eff.field_terminator,N'') ISNULL(eff.string_delimiter,N'') @@ -19,7 +19,7 @@ ISNULL(eff.row_terminator,N'') ISNULL(eff.encoding,N'') ISNULL(eff.data_compression,N'') - + ISNULL(eff.first_row, 0) diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/xml/README.md b/src/Microsoft/SqlServer/Management/SqlEnum/xml/README.md index 84b91693..31c17222 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/xml/README.md +++ b/src/Microsoft/SqlServer/Management/SqlEnum/xml/README.md @@ -128,3 +128,8 @@ Post Processing is for doing additional calculations on the returned data. This - class_name: The name of the class that handles the post-processing. Should extend [PostProcess](../PostProcess.cs) - fields: The list of fields which will cause the post-processing to happen - triggered_fields: The list of fields that are needed to compute the value for the field requested by the user + +### special_query + +This tag has 2 specialized uses and one standard behavior. Originally it was a special case for [table.xml](table.xml), to add a filter to hide temp tables when enumerating tables in tempdb, and to enable adding a query hint for optimizing the overall tables query. +Now it also acts as similarly to `post_process` by being a general purpose conditioned sql tag with a `fields` attribute and a body which is added to the `WHERE` clause of the query with an `AND` condition. diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/xml/inc_server.xml b/src/Microsoft/SqlServer/Management/SqlEnum/xml/inc_server.xml index 0da6a40f..d5a7bd96 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/xml/inc_server.xml +++ b/src/Microsoft/SqlServer/Management/SqlEnum/xml/inc_server.xml @@ -385,7 +385,7 @@ FROM sys.dm_hadr_cluster END TRY BEGIN CATCH - IF(ERROR_NUMBER() NOT IN (297,300, 15562)) + IF(ERROR_NUMBER() NOT IN (297,300, 15562, 371)) BEGIN THROW END diff --git a/src/Microsoft/SqlServer/Management/SqlEnum/xml/table.xml b/src/Microsoft/SqlServer/Management/SqlEnum/xml/table.xml index 55985fcc..aaab6700 100644 --- a/src/Microsoft/SqlServer/Management/SqlEnum/xml/table.xml +++ b/src/Microsoft/SqlServer/Management/SqlEnum/xml/table.xml @@ -184,7 +184,7 @@ triggered_fields='#DatabaseName#SchemaName#TableName#'/> - + tbl.name not like '#%' @@ -265,7 +265,7 @@ ISNULL((select top 1 1 from sys.all_columns as clmns join sys.types as usrt on usrt.user_type_id = clmns.user_type_id where clmns.object_id = tbl.object_id and usrt.name = N'xml'), 0) ISNULL((select top 1 1 from sys.all_columns as clmns join sys.types as usrt on usrt.user_type_id = clmns.user_type_id where clmns.object_id = tbl.object_id and usrt.name in (N'geometry', N'geography')), 0) tbl.uses_ansi_nulls - ISNULL(OBJECTPROPERTY(tbl.object_id,N'IsQuotedIdentOn'),0) + ISNULL(OBJECTPROPERTY(tbl.object_id,N'IsQuotedIdentOn'),1) 0 diff --git a/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptions.cs b/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptions.cs index c5cdf415..9d7dcf94 100644 --- a/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptions.cs +++ b/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptions.cs @@ -78,7 +78,9 @@ public enum ScriptDatabaseEngineEdition [DisplayNameKey("SqlServerOnDemandEdition")] SqlServerOnDemandEdition, [DisplayNameKey("SqlDatabaseEdgeEdition")] - SqlDatabaseEdgeEdition + SqlDatabaseEdgeEdition, + [DisplayNameKey("SqlAzureArcManagedInstanceEdition")] + SqlAzureArcManagedInstanceEdition, /* * NOTE: If you're adding new value here, @@ -328,6 +330,7 @@ public ICollection ConfigureVisibleEnumFields(ITypeDescriptorContext context, Ar values.Remove(ScriptDatabaseEngineEdition.SqlDatabaseEdgeEdition); values.Remove(ScriptDatabaseEngineEdition.SqlAzureDatabaseEdition); values.Remove(ScriptDatabaseEngineEdition.SqlServerOnDemandEdition); + values.Remove(ScriptDatabaseEngineEdition.SqlAzureArcManagedInstanceEdition); } else { @@ -340,6 +343,7 @@ public ICollection ConfigureVisibleEnumFields(ITypeDescriptorContext context, Ar values.Remove(ScriptDatabaseEngineEdition.SqlServerManagedInstanceEdition); values.Remove(ScriptDatabaseEngineEdition.SqlDatabaseEdgeEdition); values.Remove(ScriptDatabaseEngineEdition.SqlDatawarehouseEdition); + values.Remove(ScriptDatabaseEngineEdition.SqlAzureArcManagedInstanceEdition); } } else diff --git a/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptionsSR.strings b/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptionsSR.strings index 436edfc0..2ceee6f1 100644 --- a/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptionsSR.strings +++ b/src/Microsoft/SqlServer/Management/SqlScriptPublish/SqlScriptOptionsSR.strings @@ -235,6 +235,7 @@ StretchEdition = Microsoft SQL Server Stretch Database Edition SqlServerManagedInstanceEdition = Microsoft Azure SQL Database Managed Instance Edition SqlServerOnDemandEdition = Microsoft Azure SQL OnDemand Edition SqlDatabaseEdgeEdition = Microsoft Azure SQL Edge Edition +SqlAzureArcManagedInstanceEdition = Microsoft Azure Arc SQL Managed Instance Edition IncludeUnsupportedStatements = Include unsupported statements IncludeUnsupportedStatementsDescription = Include statements in the script that are not supported on the specified SQL Server database engine type. diff --git a/src/UnitTest/SqlScriptPublish/SqlScriptOptionsTests.cs b/src/UnitTest/SqlScriptPublish/SqlScriptOptionsTests.cs index 72f7b5b2..c66cf8df 100644 --- a/src/UnitTest/SqlScriptPublish/SqlScriptOptionsTests.cs +++ b/src/UnitTest/SqlScriptPublish/SqlScriptOptionsTests.cs @@ -39,7 +39,8 @@ public void ConfigureVisibleEnumFields_hides_inappropriate_values() ScriptDatabaseEngineEdition.SqlServerExpressEdition, ScriptDatabaseEngineEdition.SqlServerStretchEdition, ScriptDatabaseEngineEdition.SqlServerManagedInstanceEdition, - ScriptDatabaseEngineEdition.SqlDatabaseEdgeEdition + ScriptDatabaseEngineEdition.SqlDatabaseEdgeEdition, + ScriptDatabaseEngineEdition.SqlAzureArcManagedInstanceEdition }), "Allowed edition values for SingleInstance type"); scriptOptions.TargetDatabaseEngineType = SqlScriptOptions.ScriptDatabaseEngineType.SqlAzure; editionAllowedValues = engineEditionProperty.Converter.GetStandardValues(context)