mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Enabling Database scoped configurations tab to DB Properties (#2147)
* sending dsc values to ADS * modifying dsc method with unsupportable property IsValuedefault * getting the options and added a bool flag to maintian checkbox for secondary to save * sending data to ads * Ready for PR with minimal changes of loading UI as expected, TODO:saving logic * Excluding maxdop and resumable options from primary value conversion for 1/0's * Adding Id to the info, as we cannot depend on names, as names can be altered in future * saving successfully, todo-diff servers, script (secondary - primary compare and dont update),test, send null for unsupported * adding nullable dsc for unsupported servers * fixing script generation for some properties that are not touched. the generated script is unharmed but unnecessary here * adding test conditions for database scoped configurations * adding switch case method to get the values * Removing Loc string for the TSQL options * removing unnecessary using statement * Adding test case and fixing createDatabase issue * Update src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype130.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * comment update --------- Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
7c0da6b6b1
commit
e4db70fb39
@@ -46,6 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
public DateTime lastLogBackupDate;
|
public DateTime lastLogBackupDate;
|
||||||
public DatabaseUserAccess restrictAccess;
|
public DatabaseUserAccess restrictAccess;
|
||||||
public DatabaseStatus databaseState;
|
public DatabaseStatus databaseState;
|
||||||
|
public DatabaseScopedConfigurationCollection databaseScopedConfigurations;
|
||||||
public DefaultCursor defaultCursor;
|
public DefaultCursor defaultCursor;
|
||||||
public CompatibilityLevel databaseCompatibilityLevel;
|
public CompatibilityLevel databaseCompatibilityLevel;
|
||||||
public ContainmentType databaseContainmentType;
|
public ContainmentType databaseContainmentType;
|
||||||
@@ -556,6 +557,11 @@ WHERE do.database_id = @DbID
|
|||||||
this.isLedger = db.IsLedger;
|
this.isLedger = db.IsLedger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (db.IsSupportedObject<DatabaseScopedConfiguration>())
|
||||||
|
{
|
||||||
|
this.databaseScopedConfigurations = db.DatabaseScopedConfigurations;
|
||||||
|
}
|
||||||
|
|
||||||
//Only fill in the Azure properties when connected to an Azure server
|
//Only fill in the Azure properties when connected to an Azure server
|
||||||
if (context.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
|
if (context.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
|
||||||
{
|
{
|
||||||
@@ -689,6 +695,7 @@ WHERE do.database_id = @DbID
|
|||||||
this.maxSize = other.maxSize == null ? null : new DbSize(other.maxSize);
|
this.maxSize = other.maxSize == null ? null : new DbSize(other.maxSize);
|
||||||
this.backupStorageRedundancy = other.backupStorageRedundancy;
|
this.backupStorageRedundancy = other.backupStorageRedundancy;
|
||||||
this.isLedger = other.isLedger;
|
this.isLedger = other.isLedger;
|
||||||
|
this.databaseScopedConfigurations = other.databaseScopedConfigurations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -773,7 +780,8 @@ WHERE do.database_id = @DbID
|
|||||||
(this.queryStoreEnabled == other.queryStoreEnabled) &&
|
(this.queryStoreEnabled == other.queryStoreEnabled) &&
|
||||||
(this.maxSize == other.maxSize) &&
|
(this.maxSize == other.maxSize) &&
|
||||||
(this.backupStorageRedundancy == other.backupStorageRedundancy) &&
|
(this.backupStorageRedundancy == other.backupStorageRedundancy) &&
|
||||||
(this.isLedger == other.isLedger);
|
(this.isLedger == other.isLedger) &&
|
||||||
|
(this.databaseScopedConfigurations == other.databaseScopedConfigurations);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,51 +199,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
{
|
{
|
||||||
db.EncryptionEnabled = this.currentState.encryptionEnabled;
|
db.EncryptionEnabled = this.currentState.encryptionEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we support database scoped configurations in this database. Since these were all added at the same time,
|
|
||||||
// only check if MaxDop is supported rather than each individual property.
|
|
||||||
if (db.IsSupportedProperty("MaxDop"))
|
|
||||||
{
|
|
||||||
if (!this.Exists || (db.MaxDop != this.MaxDop))
|
|
||||||
{
|
|
||||||
db.MaxDop = this.MaxDop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.MaxDopForSecondary != this.MaxDopForSecondary))
|
|
||||||
{
|
|
||||||
db.MaxDopForSecondary = this.MaxDopForSecondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.LegacyCardinalityEstimation != this.currentState.legacyCardinalityEstimation))
|
|
||||||
{
|
|
||||||
db.LegacyCardinalityEstimation = this.currentState.legacyCardinalityEstimation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.LegacyCardinalityEstimationForSecondary != this.currentState.legacyCardinalityEstimationForSecondary))
|
|
||||||
{
|
|
||||||
db.LegacyCardinalityEstimationForSecondary = this.currentState.legacyCardinalityEstimationForSecondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.ParameterSniffing != this.currentState.parameterSniffing))
|
|
||||||
{
|
|
||||||
db.ParameterSniffing = this.currentState.parameterSniffing;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.ParameterSniffingForSecondary != this.currentState.parameterSniffingForSecondary))
|
|
||||||
{
|
|
||||||
db.ParameterSniffingForSecondary = this.currentState.parameterSniffingForSecondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.QueryOptimizerHotfixes != this.currentState.queryOptimizerHotfixes))
|
|
||||||
{
|
|
||||||
db.QueryOptimizerHotfixes = this.currentState.queryOptimizerHotfixes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.Exists || (db.QueryOptimizerHotfixesForSecondary != this.currentState.queryOptimizerHotfixesForSecondary))
|
|
||||||
{
|
|
||||||
db.QueryOptimizerHotfixesForSecondary = this.currentState.queryOptimizerHotfixesForSecondary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Helper Methods
|
#region Helper Methods
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
using Microsoft.SqlServer.Management.Smo;
|
||||||
|
using Microsoft.SqlTools.ServiceLayer.Management;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Database properties for SqlServer 2016
|
||||||
|
/// </summary>
|
||||||
|
internal class DatabasePrototype130 : DatabasePrototype110
|
||||||
|
{
|
||||||
|
// Properties that doen't support secondary value updates
|
||||||
|
// More info here: https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-scoped-configuration-transact-sql?view=sql-server-ver16
|
||||||
|
// The secondaryValUnsupportedPropsSet containst the configuration Ids of the below properties
|
||||||
|
// IDENTITY_CACHE(6)
|
||||||
|
// ELEVATE_ONLINE(11)
|
||||||
|
// ELEVATE_RESUMABLE(12)
|
||||||
|
// GLOBAL_TEMPORARY_TABLE_AUTO_DROP(21)
|
||||||
|
// PAUSED_RESUMABLE_INDEX_ABORT_DURATION_MINUTES(25)
|
||||||
|
private static readonly HashSet<int> secondaryValUnsupportedPropsSet = new HashSet<int> { 6, 11, 12, 21, 25 };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Database properties for SqlServer 2016 class constructor
|
||||||
|
/// </summary>
|
||||||
|
public DatabasePrototype130(CDataContainer context)
|
||||||
|
: base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Category_DatabaseScopedConfigurations")]
|
||||||
|
public DatabaseScopedConfigurationCollection DatabaseScopedConfiguration
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.currentState.databaseScopedConfigurations;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.currentState.databaseScopedConfigurations = value;
|
||||||
|
this.NotifyObservers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SaveProperties(Database db)
|
||||||
|
{
|
||||||
|
base.SaveProperties(db);
|
||||||
|
|
||||||
|
for (int i = 0; i < db.DatabaseScopedConfigurations.Count; i++)
|
||||||
|
{
|
||||||
|
if (db.DatabaseScopedConfigurations[i].Value != this.currentState.databaseScopedConfigurations[i].Value)
|
||||||
|
{
|
||||||
|
db.DatabaseScopedConfigurations[i].Value = this.currentState.databaseScopedConfigurations[i].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurations that are not allowed secondary replicas are excluded.
|
||||||
|
if (db.DatabaseScopedConfigurations[i].ValueForSecondary != this.currentState.databaseScopedConfigurations[i].ValueForSecondary
|
||||||
|
&& !secondaryValUnsupportedPropsSet.Contains(db.DatabaseScopedConfigurations[i].Id))
|
||||||
|
{
|
||||||
|
db.DatabaseScopedConfigurations[i].ValueForSecondary = this.currentState.databaseScopedConfigurations[i].ValueForSecondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Database properties for SqlServer 2017
|
/// Database properties for SqlServer 2017
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class DatabasePrototype140 : DatabasePrototype110
|
internal class DatabasePrototype140 : DatabasePrototype130
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Database properties for SqlServer 2017 class constructor
|
/// Database properties for SqlServer 2017 class constructor
|
||||||
@@ -71,6 +71,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void SaveProperties(Database db)
|
||||||
|
{
|
||||||
|
base.SaveProperties(db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
|||||||
{
|
{
|
||||||
this.prototype = new DatabasePrototype160(context);
|
this.prototype = new DatabasePrototype160(context);
|
||||||
}
|
}
|
||||||
|
else if (majorVersionNumber >= 14)
|
||||||
|
{
|
||||||
|
this.prototype = new DatabasePrototype140(context);
|
||||||
|
}
|
||||||
|
else if (majorVersionNumber == 13)
|
||||||
|
{
|
||||||
|
this.prototype = new DatabasePrototype130(context);
|
||||||
|
}
|
||||||
else if (Utils.IsSql11OrLater(context.Server.Version.Major))
|
else if (Utils.IsSql11OrLater(context.Server.Version.Major))
|
||||||
{
|
{
|
||||||
this.prototype = new DatabasePrototype110(context);
|
this.prototype = new DatabasePrototype110(context);
|
||||||
|
|||||||
@@ -12301,14 +12301,6 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string prototype_db_prop_databasescopedconfig_value_primary
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Keys.GetString(Keys.prototype_db_prop_databasescopedconfig_value_primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string error_db_prop_invalidleadingColumns
|
public static string error_db_prop_invalidleadingColumns
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -17828,9 +17820,6 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
public const string prototype_db_prop_databasescopedconfig_value_on = "prototype_db_prop_databasescopedconfig_value_on";
|
public const string prototype_db_prop_databasescopedconfig_value_on = "prototype_db_prop_databasescopedconfig_value_on";
|
||||||
|
|
||||||
|
|
||||||
public const string prototype_db_prop_databasescopedconfig_value_primary = "prototype_db_prop_databasescopedconfig_value_primary";
|
|
||||||
|
|
||||||
|
|
||||||
public const string error_db_prop_invalidleadingColumns = "error_db_prop_invalidleadingColumns";
|
public const string error_db_prop_invalidleadingColumns = "error_db_prop_invalidleadingColumns";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6702,10 +6702,6 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<value>ON</value>
|
<value>ON</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="prototype_db_prop_databasescopedconfig_value_primary" xml:space="preserve">
|
|
||||||
<value>PRIMARY</value>
|
|
||||||
<comment></comment>
|
|
||||||
</data>
|
|
||||||
<data name="error_db_prop_invalidleadingColumns" xml:space="preserve">
|
<data name="error_db_prop_invalidleadingColumns" xml:space="preserve">
|
||||||
<value>For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</value>
|
<value>For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
|
|||||||
@@ -2786,7 +2786,6 @@ prototype_db_prop_varDecimalEnabled = VarDecimal Storage Format Enabled
|
|||||||
prototype_db_prop_encryptionEnabled = Encryption Enabled
|
prototype_db_prop_encryptionEnabled = Encryption Enabled
|
||||||
prototype_db_prop_databasescopedconfig_value_off = OFF
|
prototype_db_prop_databasescopedconfig_value_off = OFF
|
||||||
prototype_db_prop_databasescopedconfig_value_on = ON
|
prototype_db_prop_databasescopedconfig_value_on = ON
|
||||||
prototype_db_prop_databasescopedconfig_value_primary = PRIMARY
|
|
||||||
error_db_prop_invalidleadingColumns = For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns
|
error_db_prop_invalidleadingColumns = For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns
|
||||||
compatibilityLevel_sphinx = SQL Server 7.0 (70)
|
compatibilityLevel_sphinx = SQL Server 7.0 (70)
|
||||||
compatibilityLevel_shiloh = SQL Server 2000 (80)
|
compatibilityLevel_shiloh = SQL Server 2000 (80)
|
||||||
|
|||||||
@@ -8216,11 +8216,6 @@ The Query Processor estimates that implementing the following index could improv
|
|||||||
<target state="new">ON</target>
|
<target state="new">ON</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="prototype_db_prop_databasescopedconfig_value_primary">
|
|
||||||
<source>PRIMARY</source>
|
|
||||||
<target state="new">PRIMARY</target>
|
|
||||||
<note></note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="error_db_prop_invalidleadingColumns">
|
<trans-unit id="error_db_prop_invalidleadingColumns">
|
||||||
<source>For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</source>
|
<source>For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</source>
|
||||||
<target state="new">For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</target>
|
<target state="new">For the distribution policy HASH, the number of leading hash columns is optional but should be from 1 to 16 columns</target>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ using Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters;
|
|||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Database object type handler
|
/// Database object type handler
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DatabaseHandler : ObjectTypeHandler<DatabaseInfo, DatabaseViewContext>
|
public class DatabaseHandler : ObjectTypeHandler<DatabaseInfo, DatabaseViewContext>
|
||||||
@@ -44,8 +44,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
|
|
||||||
internal static readonly string[] AzureEditionNames;
|
internal static readonly string[] AzureEditionNames;
|
||||||
internal static readonly string[] AzureBackupLevels;
|
internal static readonly string[] AzureBackupLevels;
|
||||||
|
internal static readonly string[] DscOnOffOptions;
|
||||||
|
internal static readonly string[] DscElevateOptions;
|
||||||
|
internal static readonly string[] DscEnableDisableOptions;
|
||||||
internal static readonly AzureEditionDetails[] AzureMaxSizes;
|
internal static readonly AzureEditionDetails[] AzureMaxSizes;
|
||||||
internal static readonly AzureEditionDetails[] AzureServiceLevels;
|
internal static readonly AzureEditionDetails[] AzureServiceLevels;
|
||||||
|
internal DatabaseScopedConfigurationCollection? databaseScopedConfigurationsCollection = null;
|
||||||
|
|
||||||
static DatabaseHandler()
|
static DatabaseHandler()
|
||||||
{
|
{
|
||||||
@@ -75,6 +79,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
displayRestrictAccessOptions.Add(DatabaseUserAccess.Single, SR.prototype_db_prop_restrictAccess_value_single);
|
displayRestrictAccessOptions.Add(DatabaseUserAccess.Single, SR.prototype_db_prop_restrictAccess_value_single);
|
||||||
displayRestrictAccessOptions.Add(DatabaseUserAccess.Restricted, SR.prototype_db_prop_restrictAccess_value_restricted);
|
displayRestrictAccessOptions.Add(DatabaseUserAccess.Restricted, SR.prototype_db_prop_restrictAccess_value_restricted);
|
||||||
|
|
||||||
|
DscOnOffOptions = new[]{
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_On,
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_Off
|
||||||
|
};
|
||||||
|
|
||||||
|
DscElevateOptions = new[]{
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_Off,
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_When_supported,
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_Fail_Unsupported
|
||||||
|
};
|
||||||
|
|
||||||
|
DscEnableDisableOptions = new[]{
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_Enabled,
|
||||||
|
CommonConstants.DatabaseScopedConfigurations_Value_Disabled
|
||||||
|
};
|
||||||
|
|
||||||
// Set up maps from displayName to enum type so we can retrieve the equivalent enum types later when getting a Save/Script request.
|
// Set up maps from displayName to enum type so we can retrieve the equivalent enum types later when getting a Save/Script request.
|
||||||
// We can't use a simple Enum.Parse for that since the displayNames get localized.
|
// We can't use a simple Enum.Parse for that since the displayNames get localized.
|
||||||
foreach (CompatibilityLevel key in displayCompatLevels.Keys)
|
foreach (CompatibilityLevel key in displayCompatLevels.Keys)
|
||||||
@@ -160,7 +180,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
AutoShrink = smoDatabase.AutoShrink,
|
AutoShrink = smoDatabase.AutoShrink,
|
||||||
AutoUpdateStatistics = smoDatabase.AutoUpdateStatisticsEnabled,
|
AutoUpdateStatistics = smoDatabase.AutoUpdateStatisticsEnabled,
|
||||||
AutoUpdateStatisticsAsynchronously = smoDatabase.AutoUpdateStatisticsAsync,
|
AutoUpdateStatisticsAsynchronously = smoDatabase.AutoUpdateStatisticsAsync,
|
||||||
EncryptionEnabled = smoDatabase.EncryptionEnabled
|
EncryptionEnabled = smoDatabase.EncryptionEnabled,
|
||||||
|
DatabaseScopedConfigurations = smoDatabase.IsSupportedObject<DatabaseScopedConfiguration>() ? GetDSCMetaData(smoDatabase.DatabaseScopedConfigurations) : null
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isAzureDB)
|
if (!isAzureDB)
|
||||||
@@ -187,7 +208,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).IsLedgerDatabase = smoDatabase.IsLedger;
|
((DatabaseInfo)databaseViewInfo.ObjectInfo).IsLedgerDatabase = smoDatabase.IsLedger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
databaseScopedConfigurationsCollection = smoDatabase.IsSupportedObject<DatabaseScopedConfiguration>() ? smoDatabase.DatabaseScopedConfigurations : null;
|
||||||
}
|
}
|
||||||
|
databaseViewInfo.DscOnOffOptions = DscOnOffOptions;
|
||||||
|
databaseViewInfo.DscElevateOptions = DscElevateOptions;
|
||||||
|
databaseViewInfo.DscEnableDisableOptions = DscEnableDisableOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// azure sql db doesn't have a sysadmin fixed role
|
// azure sql db doesn't have a sysadmin fixed role
|
||||||
@@ -569,6 +594,36 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
db110.DatabaseContainmentType = containmentTypeEnums[database.ContainmentType];
|
db110.DatabaseContainmentType = containmentTypeEnums[database.ContainmentType];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (prototype is DatabasePrototype130 db130)
|
||||||
|
{
|
||||||
|
if (!viewParams.IsNewObject && databaseScopedConfigurationsCollection != null && database.DatabaseScopedConfigurations != null)
|
||||||
|
{
|
||||||
|
foreach (DatabaseScopedConfigurationsInfo dsc in database.DatabaseScopedConfigurations)
|
||||||
|
{
|
||||||
|
foreach (DatabaseScopedConfiguration smoDscCollection in databaseScopedConfigurationsCollection)
|
||||||
|
{
|
||||||
|
if (smoDscCollection.Name == dsc.Name)
|
||||||
|
{
|
||||||
|
smoDscCollection.Value = dsc.ValueForPrimary == CommonConstants.DatabaseScopedConfigurations_Value_Enabled
|
||||||
|
? "1" : dsc.ValueForPrimary == CommonConstants.DatabaseScopedConfigurations_Value_Disabled
|
||||||
|
? "0" : dsc.ValueForPrimary;
|
||||||
|
|
||||||
|
// When sending the DSC seconday value to ADS, we convert the secondaryValue of 'PRIMARY' to match with primaryValue
|
||||||
|
// We need to set it back to 'PRIMARY' so that SMO would not generate any unnecessary scripts for unchanged properties
|
||||||
|
if (!(smoDscCollection.ValueForSecondary == CommonConstants.DatabaseScopedConfigurations_Value_Primary &&
|
||||||
|
dsc.ValueForPrimary.Equals(dsc.ValueForSecondary)))
|
||||||
|
{
|
||||||
|
smoDscCollection.ValueForSecondary = dsc.ValueForSecondary == CommonConstants.DatabaseScopedConfigurations_Value_Enabled
|
||||||
|
? "1" : dsc.ValueForSecondary == CommonConstants.DatabaseScopedConfigurations_Value_Disabled
|
||||||
|
? "0" : dsc.ValueForSecondary;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db130.DatabaseScopedConfiguration = databaseScopedConfigurationsCollection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AutoCreateStatisticsIncremental can only be set when AutoCreateStatistics is enabled
|
// AutoCreateStatisticsIncremental can only be set when AutoCreateStatistics is enabled
|
||||||
prototype.AutoCreateStatisticsIncremental = database.AutoCreateIncrementalStatistics;
|
prototype.AutoCreateStatisticsIncremental = database.AutoCreateIncrementalStatistics;
|
||||||
@@ -985,5 +1040,51 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
}
|
}
|
||||||
return sizes.ToArray();
|
return sizes.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares database scoped configurations list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="smoDSCMetaData"></param>
|
||||||
|
/// <returns>database scoped configurations metadata array</returns>
|
||||||
|
private static DatabaseScopedConfigurationsInfo[] GetDSCMetaData(DatabaseScopedConfigurationCollection smoDSCMetaData)
|
||||||
|
{
|
||||||
|
var dscMetaData = new List<DatabaseScopedConfigurationsInfo>();
|
||||||
|
foreach (DatabaseScopedConfiguration dsc in smoDSCMetaData)
|
||||||
|
{
|
||||||
|
string primaryValue = GetDscValue(dsc.Id, dsc.Value);
|
||||||
|
dscMetaData.Add(new DatabaseScopedConfigurationsInfo()
|
||||||
|
{
|
||||||
|
Id = dsc.Id,
|
||||||
|
Name = dsc.Name,
|
||||||
|
ValueForPrimary = primaryValue,
|
||||||
|
ValueForSecondary = dsc.ValueForSecondary == CommonConstants.DatabaseScopedConfigurations_Value_Primary ? primaryValue : GetDscValue(dsc.Id, dsc.ValueForSecondary)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return dscMetaData.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets primary and secondary value of the database scoped configuration property
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dsc"></param>
|
||||||
|
/// <returns>Value of the primary/secondary</returns>
|
||||||
|
private static string GetDscValue(int id, string value)
|
||||||
|
{
|
||||||
|
// MAXDOP(Id = 1) and PAUSED_RESUMABLE_INDEX_ABORT_DURATION_MINUTES(Id = 25) are integer numbers but coming as string value type and they need to send as is.
|
||||||
|
if (id == 1 || id == 25)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case "1":
|
||||||
|
return CommonConstants.DatabaseScopedConfigurations_Value_Enabled;
|
||||||
|
case "0":
|
||||||
|
return CommonConstants.DatabaseScopedConfigurations_Value_Disabled;
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,5 +39,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
public bool? DatabaseReadOnly { get; set; }
|
public bool? DatabaseReadOnly { get; set; }
|
||||||
public bool EncryptionEnabled { get; set; }
|
public bool EncryptionEnabled { get; set; }
|
||||||
public string? RestrictAccess { get; set; }
|
public string? RestrictAccess { get; set; }
|
||||||
|
public DatabaseScopedConfigurationsInfo[]? DatabaseScopedConfigurations { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DatabaseScopedConfigurationsInfo
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string ValueForPrimary { get; set; }
|
||||||
|
public string ValueForSecondary { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
|||||||
public AzureEditionDetails[] AzureMaxSizes { get; set; }
|
public AzureEditionDetails[] AzureMaxSizes { get; set; }
|
||||||
public string[] PageVerifyOptions { get; set; }
|
public string[] PageVerifyOptions { get; set; }
|
||||||
public string[] RestrictAccessOptions { get; set; }
|
public string[] RestrictAccessOptions { get; set; }
|
||||||
|
public string[] DscOnOffOptions { get; set; }
|
||||||
|
public string[] DscElevateOptions { get; set; }
|
||||||
|
public string[] DscEnableDisableOptions { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AzureEditionDetails
|
public class AzureEditionDetails
|
||||||
|
|||||||
@@ -19,5 +19,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
|||||||
public const string TempDbDatabaseName = "tempdb";
|
public const string TempDbDatabaseName = "tempdb";
|
||||||
|
|
||||||
public const string DefaultBatchSeperator = "GO";
|
public const string DefaultBatchSeperator = "GO";
|
||||||
|
|
||||||
|
// Database scoped configurations property values
|
||||||
|
public const string DatabaseScopedConfigurations_Value_On = "ON";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_Off = "OFF";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_Primary = "PRIMARY";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_When_supported = "WHEN_SUPPORTED";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_Fail_Unsupported = "FAIL_UNSUPPORTED";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_Enabled = "ENABLED";
|
||||||
|
public const string DatabaseScopedConfigurations_Value_Disabled = "DISABLED";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,6 +300,67 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
|||||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoUpdateStatisticsAsynchronously, Is.False, $"AutoUpdateStatisticsAsynchronously should match with testdata");
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoUpdateStatisticsAsynchronously, Is.False, $"AutoUpdateStatisticsAsynchronously should match with testdata");
|
||||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).PageVerify, Is.EqualTo(testDatabase.PageVerify), $"PageVerify should match with testdata");
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).PageVerify, Is.EqualTo(testDatabase.PageVerify), $"PageVerify should match with testdata");
|
||||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).RestrictAccess, Is.EqualTo(testDatabase.RestrictAccess), $"RestrictAccess should match with testdata");
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).RestrictAccess, Is.EqualTo(testDatabase.RestrictAccess), $"RestrictAccess should match with testdata");
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations, Is.Not.Null, $"DatabaseScopedConfigurations is not null");
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations.Count, Is.GreaterThan(0), $"DatabaseScopedConfigurations should have at least a+ few properties");
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn, throwIfNotExist: true);
|
||||||
|
Assert.That(DatabaseExists(testDatabase.Name!, server), Is.False, $"Database '{testDatabase.Name}' was not dropped succesfully");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Cleanup using SMO if Drop didn't work
|
||||||
|
DropDatabase(server, testDatabase.Name!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updating and validating database scoped configurations property values
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Test]
|
||||||
|
public async Task VerifyDatabaseScopedConfigurationsTest()
|
||||||
|
{
|
||||||
|
// setup, drop database if exists.
|
||||||
|
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", serverType: TestServerType.OnPrem);
|
||||||
|
using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(connectionResult.ConnectionInfo))
|
||||||
|
{
|
||||||
|
var server = new Server(new ServerConnection(sqlConn));
|
||||||
|
|
||||||
|
var testDatabase = ObjectManagementTestUtils.GetTestDatabaseInfo();
|
||||||
|
var objUrn = ObjectManagementTestUtils.GetDatabaseURN(testDatabase.Name);
|
||||||
|
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// create database
|
||||||
|
var parametersForCreation = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, "master", true, SqlObjectType.Database, "", "");
|
||||||
|
await ObjectManagementTestUtils.SaveObject(parametersForCreation, testDatabase);
|
||||||
|
Assert.That(DatabaseExists(testDatabase.Name!, server), $"Expected database '{testDatabase.Name}' was not created succesfully");
|
||||||
|
|
||||||
|
// Get database properties and verify
|
||||||
|
var parametersForUpdate = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, testDatabase.Name, false, SqlObjectType.Database, "", objUrn);
|
||||||
|
DatabaseViewInfo databaseViewInfo = await ObjectManagementTestUtils.GetDatabaseObject(parametersForUpdate, testDatabase);
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations, Is.Not.Null, $"DatabaseScopedConfigurations is not null");
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations.Count, Is.GreaterThan(0), $"DatabaseScopedConfigurations should have at least a+ few properties");
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations[0].ValueForPrimary, Is.EqualTo("ON"), $"DatabaseScopedConfigurations primary value should match");
|
||||||
|
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations[0].ValueForSecondary, Is.EqualTo("ON"), $"DatabaseScopedConfigurations secondary value should match");
|
||||||
|
|
||||||
|
// Update few database scoped configurations
|
||||||
|
testDatabase.DatabaseScopedConfigurations = ((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseScopedConfigurations;
|
||||||
|
if (testDatabase.DatabaseScopedConfigurations.Length > 0)
|
||||||
|
{
|
||||||
|
// ACCELERATED_PLAN_FORCING
|
||||||
|
testDatabase.DatabaseScopedConfigurations[0].ValueForPrimary = "OFF";
|
||||||
|
testDatabase.DatabaseScopedConfigurations[0].ValueForSecondary = "OFF";
|
||||||
|
}
|
||||||
|
await ObjectManagementTestUtils.SaveObject(parametersForUpdate, testDatabase);
|
||||||
|
DatabaseViewInfo updatedDatabaseViewInfo = await ObjectManagementTestUtils.GetDatabaseObject(parametersForUpdate, testDatabase);
|
||||||
|
|
||||||
|
// verify the modified properties
|
||||||
|
Assert.That(((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).DatabaseScopedConfigurations[0].ValueForPrimary, Is.EqualTo(testDatabase.DatabaseScopedConfigurations[0].ValueForPrimary), $"DSC updated primary value should match");
|
||||||
|
Assert.That(((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).DatabaseScopedConfigurations[0].ValueForSecondary, Is.EqualTo(testDatabase.DatabaseScopedConfigurations[0].ValueForSecondary), $"DSC updated Secondary value should match");
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn, throwIfNotExist: true);
|
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn, throwIfNotExist: true);
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
|||||||
AutoCreateStatistics = true,
|
AutoCreateStatistics = true,
|
||||||
AutoShrink = false,
|
AutoShrink = false,
|
||||||
AutoUpdateStatistics = true,
|
AutoUpdateStatistics = true,
|
||||||
AutoUpdateStatisticsAsynchronously = false
|
AutoUpdateStatisticsAsynchronously = false,
|
||||||
|
DatabaseScopedConfigurations = null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user