Sai/db properties options tab (#2121)

* Sending values to ADS, including the arrays, need refactor and tests

* adjusting dd options as per ssms

* sending back the updated options properties to smo

* saving changes

* pulling correct database name changes

* Refactoring

* saving is working fine

* Added genral tab section options for the option tab

* modifying userAccess and pageVerify props types

* fix for database name being master for always for existing database

* Managed Instance save error fixed

* added new assertions to the test case

* server engine edition conditions handling from ADS side

* Adding unsupported options approach to the properties, so that these nullable options can be excluded from UI

* modifying the props name

* modified empty string to null

* Test case update
This commit is contained in:
Sai Avishkar Sreerama
2023-07-06 13:48:11 -04:00
committed by GitHub
parent c2d53a3215
commit 11f632aaa9
6 changed files with 118 additions and 10 deletions

View File

@@ -62,6 +62,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
{
this.prototype = new DatabasePrototypeAzure(context);
}
else if (majorVersionNumber == 16)
{
this.prototype = new DatabasePrototype160(context);
}
else if (Utils.IsSql11OrLater(context.Server.Version.Major))
{
this.prototype = new DatabasePrototype110(context);

View File

@@ -35,6 +35,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
private static readonly Dictionary<CompatibilityLevel, string> displayCompatLevels = new Dictionary<CompatibilityLevel, string>();
private static readonly Dictionary<ContainmentType, string> displayContainmentTypes = new Dictionary<ContainmentType, string>();
private static readonly Dictionary<RecoveryModel, string> displayRecoveryModels = new Dictionary<RecoveryModel, string>();
private static readonly Dictionary<PageVerify, string> displayPageVerifyOptions = new Dictionary<PageVerify, string>();
private static readonly Dictionary<DatabaseUserAccess, string> displayRestrictAccessOptions = new Dictionary<DatabaseUserAccess, string>();
private static readonly Dictionary<string, CompatibilityLevel> compatLevelEnums = new Dictionary<string, CompatibilityLevel>();
private static readonly Dictionary<string, ContainmentType> containmentTypeEnums = new Dictionary<string, ContainmentType>();
@@ -65,6 +67,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
displayRecoveryModels.Add(RecoveryModel.BulkLogged, SR.general_recoveryModel_bulkLogged);
displayRecoveryModels.Add(RecoveryModel.Simple, SR.general_recoveryModel_simple);
displayPageVerifyOptions.Add(PageVerify.Checksum, SR.prototype_db_prop_pageVerify_value_checksum);
displayPageVerifyOptions.Add(PageVerify.TornPageDetection, SR.prototype_db_prop_pageVerify_value_tornPageDetection);
displayPageVerifyOptions.Add(PageVerify.None, SR.prototype_db_prop_pageVerify_value_none);
displayRestrictAccessOptions.Add(DatabaseUserAccess.Multiple, SR.prototype_db_prop_restrictAccess_value_multiple);
displayRestrictAccessOptions.Add(DatabaseUserAccess.Single, SR.prototype_db_prop_restrictAccess_value_single);
displayRestrictAccessOptions.Add(DatabaseUserAccess.Restricted, SR.prototype_db_prop_restrictAccess_value_restricted);
// 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.
foreach (CompatibilityLevel key in displayCompatLevels.Keys)
@@ -100,7 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
public override Task<InitializeViewResult> InitializeObjectView(InitializeViewRequestParams requestParams)
{
// create a default data context and database object
using (var dataContainer = CreateDatabaseDataContainer(requestParams.ConnectionUri, requestParams.ObjectUrn, requestParams.IsNewObject))
using (var dataContainer = CreateDatabaseDataContainer(requestParams.ConnectionUri, requestParams.ObjectUrn, requestParams.IsNewObject, requestParams.Database))
{
if (dataContainer.Server == null)
{
@@ -115,6 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
var azurePrototype = prototype as DatabasePrototypeAzure;
bool isDw = azurePrototype != null && azurePrototype.AzureEdition == AzureEdition.DataWarehouse;
bool isAzureDB = dataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase;
bool isManagedInstance = dataContainer.Server.DatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance;
var databaseViewInfo = new DatabaseViewInfo()
{
@@ -132,6 +143,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
Name = smoDatabase.Name,
CollationName = smoDatabase.Collation,
CompatibilityLevel = displayCompatLevels[smoDatabase.CompatibilityLevel],
ContainmentType = displayContainmentTypes[smoDatabase.ContainmentType],
RecoveryModel = displayRecoveryModels[smoDatabase.RecoveryModel],
DateCreated = smoDatabase.CreateDate.ToString(),
LastDatabaseBackup = smoDatabase.LastBackupDate == DateTime.MinValue ? SR.databaseBackupDate_None : smoDatabase.LastBackupDate.ToString(),
LastDatabaseLogBackup = smoDatabase.LastLogBackupDate == DateTime.MinValue ? SR.databaseBackupDate_None : smoDatabase.LastLogBackupDate.ToString(),
@@ -141,8 +155,28 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
Owner = smoDatabase.Owner,
SizeInMb = smoDatabase.Size,
SpaceAvailableInMb = ByteConverter.ConvertKbtoMb(smoDatabase.SpaceAvailable),
Status = smoDatabase.Status.ToString()
Status = smoDatabase.Status.ToString(),
AutoCreateIncrementalStatistics = smoDatabase.AutoCreateIncrementalStatisticsEnabled,
AutoCreateStatistics = smoDatabase.AutoCreateStatisticsEnabled,
AutoShrink = smoDatabase.AutoShrink,
AutoUpdateStatistics = smoDatabase.AutoUpdateStatisticsEnabled,
AutoUpdateStatisticsAsynchronously = smoDatabase.AutoUpdateStatisticsAsync,
EncryptionEnabled = smoDatabase.EncryptionEnabled
};
if (!isManagedInstance)
{
databaseViewInfo.PageVerifyOptions = displayPageVerifyOptions.Values.ToArray();
databaseViewInfo.RestrictAccessOptions = displayRestrictAccessOptions.Values.ToArray();
((DatabaseInfo)databaseViewInfo.ObjectInfo).DatabaseReadOnly = smoDatabase.ReadOnly;
((DatabaseInfo)databaseViewInfo.ObjectInfo).RestrictAccess = displayRestrictAccessOptions[smoDatabase.UserAccess];
((DatabaseInfo)databaseViewInfo.ObjectInfo).PageVerify = displayPageVerifyOptions[smoDatabase.PageVerify];
((DatabaseInfo)databaseViewInfo.ObjectInfo).TargetRecoveryTimeInSec = smoDatabase.TargetRecoveryTime;
if (prototype is DatabasePrototype160) {
((DatabaseInfo)databaseViewInfo.ObjectInfo).IsLedgerDatabase = smoDatabase.IsLedger;
}
}
}
}
@@ -259,7 +293,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
var sqlScript = string.Empty;
ConnectionInfo connectionInfo = this.GetConnectionInfo(detachParams.ConnectionUri);
using (var dataContainer = CreateDatabaseDataContainer(detachParams.ConnectionUri, detachParams.ObjectUrn, false))
using (var dataContainer = CreateDatabaseDataContainer(detachParams.ConnectionUri, detachParams.ObjectUrn, false, null))
{
var smoDatabase = dataContainer.SqlDialogSubject as Database;
if (smoDatabase != null)
@@ -326,9 +360,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
return builder.ToString();
}
private CDataContainer CreateDatabaseDataContainer(string connectionUri, string? objectURN, bool isNewDatabase)
private CDataContainer CreateDatabaseDataContainer(string connectionUri, string? objectURN, bool isNewDatabase, string? databaseName)
{
ConnectionInfo connectionInfo = this.GetConnectionInfo(connectionUri);
if (!isNewDatabase && !string.IsNullOrEmpty(databaseName))
{
connectionInfo.ConnectionDetails.DatabaseName = databaseName;
}
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connectionInfo, databaseExists: !isNewDatabase);
if (dataContainer.Server == null)
{
@@ -349,7 +387,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
throw new ArgumentException("Database name not provided.");
}
using (var dataContainer = CreateDatabaseDataContainer(viewParams.ConnectionUri, viewParams.ObjectUrn, viewParams.IsNewObject))
using (var dataContainer = CreateDatabaseDataContainer(viewParams.ConnectionUri, viewParams.ObjectUrn, viewParams.IsNewObject, viewParams.Database))
{
if (dataContainer.Server == null)
{
@@ -363,7 +401,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
prototype.Name = database.Name;
// Update database file names now that we have a database name
if (!prototype.HideFileSettings)
// Modifying logical file name is not supported in SQL Database Managed Instance.
if (!prototype.HideFileSettings && dataContainer.Server.DatabaseEngineEdition != DatabaseEngineEdition.SqlManagedInstance)
{
var sanitizedName = DatabaseUtils.SanitizeDatabaseFileName(prototype.Name);
@@ -385,7 +424,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
}
}
if (database.Owner != null)
if (database.Owner != null && viewParams.IsNewObject)
{
prototype.Owner = database.Owner;
}
@@ -401,10 +440,48 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
{
prototype.DatabaseCompatibilityLevel = compatLevelEnums[database.CompatibilityLevel];
}
if (prototype is DatabasePrototype110 db110 && database.ContainmentType != null)
if (prototype is DatabasePrototype80 db80)
{
if (database.DatabaseReadOnly != null)
{
db80.IsReadOnly = (bool)database.DatabaseReadOnly;
}
}
if (prototype is DatabasePrototype90 db90)
{
db90.AutoUpdateStatisticsAsync = database.AutoUpdateStatisticsAsynchronously;
db90.PageVerifyDisplay = database.PageVerify;
}
if (prototype is DatabasePrototype100 db100)
{
db100.EncryptionEnabled = database.EncryptionEnabled;
}
if (prototype is DatabasePrototype110 db110)
{
if (database.TargetRecoveryTimeInSec != null) {
db110.TargetRecoveryTime = (int)database.TargetRecoveryTimeInSec;
}
if (database.ContainmentType != null)
{
db110.DatabaseContainmentType = containmentTypeEnums[database.ContainmentType];
}
}
if (prototype is DatabasePrototype160 db160)
{
if (database.IsLedgerDatabase != null)
{
db160.IsLedger = (bool)database.IsLedgerDatabase;
}
}
// AutoCreateStatisticsIncremental can only be set when AutoCreateStatistics is enabled
prototype.AutoCreateStatisticsIncremental = database.AutoCreateIncrementalStatistics;
prototype.AutoCreateStatistics = database.AutoCreateStatistics;
prototype.AutoShrink= database.AutoShrink;
prototype.AutoUpdateStatistics = database.AutoUpdateStatistics;
prototype.RestrictAccess = database.RestrictAccess;
if (prototype is DatabasePrototypeAzure dbAz)
{

View File

@@ -28,5 +28,16 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
public string? AzureServiceLevelObjective { get; set; }
public string? AzureEdition { get; set; }
public string? AzureMaxSize { get; set; }
public bool AutoCreateIncrementalStatistics { get; set; }
public bool AutoCreateStatistics { get; set; }
public bool AutoShrink { get; set; }
public bool AutoUpdateStatistics { get; set; }
public bool AutoUpdateStatisticsAsynchronously { get; set; }
public bool? IsLedgerDatabase { get; set; }
public string? PageVerify { get; set; }
public int? TargetRecoveryTimeInSec { get; set; }
public bool? DatabaseReadOnly { get; set; }
public bool EncryptionEnabled { get; set; }
public string? RestrictAccess { get; set; }
}
}

View File

@@ -21,6 +21,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
public AzureEditionDetails[] AzureServiceLevelObjectives { get; set; }
public string[] AzureEditions { get; set; }
public AzureEditionDetails[] AzureMaxSizes { get; set; }
public string[] PageVerifyOptions { get; set; }
public string[] RestrictAccessOptions { get; set; }
}
public class AzureEditionDetails

View File

@@ -293,6 +293,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).LastDatabaseBackup, Is.EqualTo(testDatabase.LastDatabaseBackup), $"Should have no database last backup date");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).LastDatabaseLogBackup, Is.EqualTo(testDatabase.LastDatabaseLogBackup), $"Should have no database backup log date");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).SizeInMb, Is.GreaterThan(0), $"Should have default database size when created");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoCreateIncrementalStatistics, Is.True, $"AutoCreateIncrementalStatistics match with testdata");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoCreateStatistics, Is.True, $"AutoCreateStatistics should match with testdata");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoShrink, Is.False, $"AutoShrink should match with testdata");
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).AutoUpdateStatistics, Is.True, $"AutoUpdateStatistics 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).RestrictAccess, Is.EqualTo(testDatabase.RestrictAccess), $"RestrictAccess should match with testdata");
// cleanup
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn, throwIfNotExist: true);

View File

@@ -72,7 +72,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
ContainmentType = "None",
RecoveryModel = "Full",
LastDatabaseBackup = "None",
LastDatabaseLogBackup = "None"
LastDatabaseLogBackup = "None",
PageVerify = "CHECKSUM",
RestrictAccess = "MULTI_USER",
AutoCreateIncrementalStatistics = true,
AutoCreateStatistics = true,
AutoShrink = false,
AutoUpdateStatistics = true,
AutoUpdateStatisticsAsynchronously = false
};
}