mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-26 09:35:38 -05:00
Enabling FILEGROUPS tab experience to the Database Properties (#2182)
* 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 * sending required data, verify autogrowth... * using fullTextIndexing to open the files tab for sql server and not to other servers * Adding test case and fixing createDatabase issue * sending files as objecinfo * Update src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabasePrototype130.cs Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * comment update * preparing filegroup and filetype options * sending required all fields * saving file code changes, need more to work * Saving file is completed, todo:edit & remove * Logic to remove the file * add,edit,save working * cleaning merge conflicts accidentally added code * Adding tests to validates Files by adding, removing, updating files * adding comments * all working including tests, except fileStream size question * code review comments updates * memoryoptimized filegroups should be part of filestream group * Initial commit * failing tests fix * Modify tests by create database using SqlTestDb * Modify tests by create database using SqlTestDb * Update src/Microsoft.SqlTools.ServiceLayer/ObjectManagement/ObjectTypes/Database/DatabaseHandler.cs Co-authored-by: Cory Rivera <corivera@microsoft.com> * preparing filegroup data to model * fixing test * commenting remove file testing as failing pipeline but passing locally * saving filegroups * using enum for type * trying to fix the test in server, removed the complaining file from test * all working but saving needs condition for filestream types * removing fulltext param and test fix * saving filegroups completed, need tests * fixing the path.. * adding test for Filegroups * test fix * fixing filegroups as filestream is not enabled on test server * missing conflict resolving * cleaning unused method * Code review updates for both filegroups and files logic --------- Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> Co-authored-by: Cory Rivera <corivera@microsoft.com>
This commit is contained in:
committed by
GitHub
parent
1f045ba669
commit
c73ab55055
@@ -216,6 +216,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).TargetRecoveryTimeInSec = smoDatabase.TargetRecoveryTime;
|
||||
// Files tab is only supported in SQL Server, but files exists for all servers and used in detach database, cannot depend on files property to check the supportability
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).IsFilesTabSupported = true;
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).Filegroups = GetFileGroups(smoDatabase, databaseViewInfo);
|
||||
}
|
||||
|
||||
if (prototype is DatabasePrototype160)
|
||||
@@ -225,9 +226,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
}
|
||||
databaseScopedConfigurationsCollection = smoDatabase.IsSupportedObject<DatabaseScopedConfiguration>() ? smoDatabase.DatabaseScopedConfigurations : null;
|
||||
databaseViewInfo.FileTypesOptions = displayFileTypes.Values.ToArray();
|
||||
|
||||
// Get file groups names
|
||||
GetFileGroupNames(smoDatabase, databaseViewInfo);
|
||||
}
|
||||
databaseViewInfo.DscOnOffOptions = DscOnOffOptions;
|
||||
databaseViewInfo.DscElevateOptions = DscElevateOptions;
|
||||
@@ -700,8 +698,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
|
||||
if (!viewParams.IsNewObject && database.Files != null)
|
||||
{
|
||||
HashSet<int> fileIdsToRemove = new HashSet<int>(prototype.Files.Select(file => file.ID));
|
||||
foreach (var file in database.Files)
|
||||
Dictionary<int, DatabaseFilePrototype> fileDict = new Dictionary<int, DatabaseFilePrototype>();
|
||||
foreach (DatabaseFilePrototype file in prototype.Files)
|
||||
{
|
||||
fileDict[file.ID] = file;
|
||||
}
|
||||
foreach (DatabaseFile file in database.Files)
|
||||
{
|
||||
// Add a New file
|
||||
if (file.Id == 0)
|
||||
@@ -712,7 +714,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
newFile.PhysicalName = file.FileNameWithExtension;
|
||||
newFile.DatabaseFileType = fileTypesEnums[file.Type];
|
||||
newFile.Exists = false;
|
||||
newFile.Autogrowth = GetAutogrowth(prototype, file);
|
||||
newFile.Autogrowth = GetAutogrowth(prototype, file);
|
||||
if (!string.IsNullOrEmpty(file.Path.Trim()))
|
||||
{
|
||||
newFile.Folder = Utility.DatabaseUtils.ConvertToLocalMachinePath(Path.GetFullPath(file.Path));
|
||||
@@ -732,24 +734,69 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
// Edit file properties: updating the existed files with modified data
|
||||
else
|
||||
{
|
||||
var existedFile = prototype.Files.FirstOrDefault(x => x.ID == file.Id);
|
||||
if (existedFile != null)
|
||||
DatabaseFilePrototype? existingFile;
|
||||
if (fileDict.TryGetValue(file.Id, out existingFile))
|
||||
{
|
||||
fileIdsToRemove.Remove(file.Id);
|
||||
existedFile.Name = file.Name;
|
||||
existedFile.InitialSize = (int)file.SizeInMb;
|
||||
existedFile.Autogrowth = GetAutogrowth(prototype, file);
|
||||
existingFile.Name = file.Name;
|
||||
existingFile.InitialSize = (int)file.SizeInMb;
|
||||
existingFile.Autogrowth = GetAutogrowth(prototype, file);
|
||||
}
|
||||
// Once updated, remove it from the dictionary
|
||||
fileDict.Remove(file.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
foreach (var currentFile in prototype.Files)
|
||||
foreach (KeyValuePair<int,DatabaseFilePrototype> removedfile in fileDict)
|
||||
{
|
||||
if (fileIdsToRemove.Contains(currentFile.ID))
|
||||
removedfile.Value.Removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!viewParams.IsNewObject && database.Filegroups != null)
|
||||
{
|
||||
Dictionary<string, FilegroupPrototype> groupNameDict = new Dictionary<string, FilegroupPrototype>();
|
||||
foreach (FilegroupPrototype fileGroup in prototype.Filegroups)
|
||||
{
|
||||
groupNameDict[fileGroup.Name] = fileGroup;
|
||||
}
|
||||
// process row data filegroups
|
||||
foreach (FileGroupSummary fg in database.Filegroups)
|
||||
{
|
||||
if (fg.Id < 0)
|
||||
{
|
||||
currentFile.Removed = true;
|
||||
FilegroupPrototype newfileGroup = new FilegroupPrototype(prototype);
|
||||
newfileGroup.FileGroupType = fg.Type;
|
||||
newfileGroup.Name = fg.Name;
|
||||
newfileGroup.IsReadOnly = fg.IsReadOnly;
|
||||
newfileGroup.IsDefault = fg.IsDefault;
|
||||
newfileGroup.IsAutogrowAllFiles = fg.IsDefault;
|
||||
prototype.Filegroups.Add(newfileGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
FilegroupPrototype? existingFileGroup;
|
||||
if (groupNameDict.TryGetValue(fg.Name, out existingFileGroup))
|
||||
{
|
||||
if (fg.Type != FileGroupType.MemoryOptimizedDataFileGroup)
|
||||
{
|
||||
existingFileGroup.IsReadOnly = fg.IsReadOnly;
|
||||
existingFileGroup.IsDefault = fg.IsDefault;
|
||||
if (fg.Type != FileGroupType.FileStreamDataFileGroup)
|
||||
{
|
||||
existingFileGroup.IsAutogrowAllFiles = fg.AutogrowAllFiles;
|
||||
}
|
||||
}
|
||||
// Once updated, remove it from the dictionary
|
||||
groupNameDict.Remove(fg.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the filegroups
|
||||
foreach (KeyValuePair<string, FilegroupPrototype> removedFilegroups in groupNameDict)
|
||||
{
|
||||
removedFilegroups.Value.Removed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,35 +1065,26 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
return filesList.ToArray();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the file group names from the database fileGroup
|
||||
/// Preparing the filegroups of various FileGroupTypes
|
||||
/// </summary>
|
||||
/// <param name="database">smo database prototype</param>
|
||||
/// <param name="databaseViewInfo">database view info object</param>
|
||||
private void GetFileGroupNames(Database database, DatabaseViewInfo databaseViewInfo)
|
||||
/// <param name="database"></param>
|
||||
/// <param name="databaseViewInfo"></param>
|
||||
private FileGroupSummary[] GetFileGroups(Database database, DatabaseViewInfo databaseViewInfo)
|
||||
{
|
||||
var rowDataGroups = new List<string>();
|
||||
var fileStreamDataGroups = new List<string>();
|
||||
foreach (FileGroup fileGroup in database.FileGroups)
|
||||
var filegroups = new List<FileGroupSummary>();
|
||||
foreach (FileGroup filegroup in database.FileGroups)
|
||||
{
|
||||
if (fileGroup.FileGroupType == FileGroupType.FileStreamDataFileGroup || fileGroup.FileGroupType == FileGroupType.MemoryOptimizedDataFileGroup)
|
||||
filegroups.Add(new FileGroupSummary()
|
||||
{
|
||||
fileStreamDataGroups.Add(fileGroup.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
rowDataGroups.Add(fileGroup.Name);
|
||||
}
|
||||
Id = filegroup.ID,
|
||||
Name = filegroup.Name,
|
||||
Type = filegroup.FileGroupType,
|
||||
IsReadOnly = filegroup.ReadOnly,
|
||||
IsDefault = filegroup.IsDefault
|
||||
});
|
||||
}
|
||||
|
||||
// If no fileStream groups available
|
||||
if (fileStreamDataGroups.Count == 0)
|
||||
{
|
||||
fileStreamDataGroups.Add(SR.prototype_file_noApplicableFileGroup);
|
||||
}
|
||||
databaseViewInfo.RowDataFileGroupsOptions = rowDataGroups.ToArray();
|
||||
databaseViewInfo.FileStreamFileGroupsOptions = fileStreamDataGroups.ToArray();
|
||||
return filegroups.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public DatabaseScopedConfigurationsInfo[]? DatabaseScopedConfigurations { get; set; }
|
||||
public bool? IsFilesTabSupported { get; set; }
|
||||
public DatabaseFile[] Files { get; set; }
|
||||
public FileGroupSummary[]? Filegroups { get; set; }
|
||||
}
|
||||
|
||||
public class DatabaseScopedConfigurationsInfo
|
||||
@@ -69,4 +70,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public double MaxSizeLimitInMb { get; set; }
|
||||
}
|
||||
|
||||
public class FileGroupSummary
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public FileGroupType Type { get; set; }
|
||||
public bool IsReadOnly { get; set; }
|
||||
public bool IsDefault { get; set; }
|
||||
public bool AutogrowAllFiles { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,8 +27,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public string[] DscOnOffOptions { get; set; }
|
||||
public string[] DscElevateOptions { get; set; }
|
||||
public string[] DscEnableDisableOptions { get; set; }
|
||||
public string[] RowDataFileGroupsOptions { get; set; }
|
||||
public string[] FileStreamFileGroupsOptions { get; set; }
|
||||
public string[] FileTypesOptions { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using NUnit.Framework;
|
||||
using static Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper;
|
||||
using DatabaseFile = Microsoft.SqlTools.ServiceLayer.ObjectManagement.DatabaseFile;
|
||||
using FileGroup = Microsoft.SqlServer.Management.Smo.FileGroup;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
{
|
||||
@@ -305,10 +306,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
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).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?.Length, Is.GreaterThan(0), $"DatabaseScopedConfigurations should have at least a+ few properties");
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Files.Count, Is.EqualTo(2), $"Create database should create two database files");
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Files[0].Type, Is.EqualTo("ROWS Data"), $"Database files first file should be Row type database files");
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Files[1].Type, Is.EqualTo("LOG"), $"Database files first file should be Log type database files");
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Filegroups?.Length, Is.GreaterThan(0), $"Database file groups should exists");
|
||||
|
||||
// cleanup
|
||||
await ObjectManagementTestUtils.DropObject(connectionResult.ConnectionInfo.OwnerUri, objUrn, throwIfNotExist: true);
|
||||
@@ -438,6 +440,71 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adding, modifying and deleting database filegroups
|
||||
/// /// </summary>
|
||||
/// <returns></returns>
|
||||
[Test]
|
||||
public async Task VerifyDatabaseFileGroupsTest()
|
||||
{
|
||||
using (var testDatabase = await SqlTestDb.CreateNewAsync(serverType: TestServerType.OnPrem, dbNamePrefix: "VerifyDatabaseFilegeoupsTest"))
|
||||
{
|
||||
var connectionResult = LiveConnectionHelper.InitLiveConnectionInfo(testDatabase.DatabaseName);
|
||||
using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(connectionResult.ConnectionInfo))
|
||||
{
|
||||
var testDatabaseInfo = ObjectManagementTestUtils.GetTestDatabaseInfo();
|
||||
testDatabaseInfo.Name = testDatabase.DatabaseName;
|
||||
testDatabaseInfo.CollationName = "";
|
||||
var objUrn = ObjectManagementTestUtils.GetDatabaseURN(testDatabase.DatabaseName);
|
||||
|
||||
// Get database properties and verify
|
||||
var parametersForUpdate = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, testDatabase.DatabaseName, false, SqlObjectType.Database, "", objUrn);
|
||||
DatabaseViewInfo databaseViewInfo = await ObjectManagementTestUtils.GetDatabaseObject(parametersForUpdate, testDatabaseInfo);
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Filegroups?.Length, Is.EqualTo(1), $"Create database should create one default database filegroup");
|
||||
Assert.That(((DatabaseInfo)databaseViewInfo.ObjectInfo).Filegroups[0].Name, Is.EqualTo("PRIMARY"), $"Database default filegroup name should be PRIMARY");
|
||||
|
||||
List<FileGroupSummary> databaseFilegroup = new List<FileGroupSummary>();
|
||||
|
||||
// copy exisitng Row data files to the list
|
||||
databaseFilegroup.Add(((DatabaseInfo)databaseViewInfo.ObjectInfo).Filegroups[0]);
|
||||
|
||||
// Add new Filegroups
|
||||
var testDatabaseFilegroups = ObjectManagementTestUtils.GetTestDatabaseFilegroups();
|
||||
databaseFilegroup.AddRange(testDatabaseFilegroups);
|
||||
|
||||
// Attaching the filegroups to the testdatabase
|
||||
testDatabaseInfo.Filegroups = databaseFilegroup.ToArray();
|
||||
|
||||
// Validate the result
|
||||
await ObjectManagementTestUtils.SaveObject(parametersForUpdate, testDatabaseInfo);
|
||||
DatabaseViewInfo updatedDatabaseViewInfo = await ObjectManagementTestUtils.GetDatabaseObject(parametersForUpdate, testDatabaseInfo);
|
||||
|
||||
// verify the modified properties
|
||||
Assert.That(((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).Filegroups?.Length, Is.EqualTo(3), $"Four filegroups should exists, as we created three more");
|
||||
var filegroup = ((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).Filegroups.FirstOrDefault(x => x.Name == databaseFilegroup[1].Name);
|
||||
Assert.That(filegroup, Is.Not.Null, $"filegroup should exists");
|
||||
Assert.That(filegroup.Type, Is.EqualTo(FileGroupType.RowsFileGroup), $"Filegroup type should be matched");
|
||||
|
||||
filegroup = ((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).Filegroups.FirstOrDefault(x => x.Name == databaseFilegroup[2].Name);
|
||||
Assert.That(filegroup, Is.Not.Null, $"filegroup should exists");
|
||||
Assert.That(filegroup.Type, Is.EqualTo(FileGroupType.MemoryOptimizedDataFileGroup), $"Filegroup type should be matched");
|
||||
|
||||
// Deleting newly created file
|
||||
List<FileGroupSummary> newfilegroups = ((DatabaseInfo)updatedDatabaseViewInfo.ObjectInfo).Filegroups.ToList();
|
||||
var fileIndexTobeRemoved = newfilegroups.FindIndex(x => x.Name == databaseFilegroup[1].Name);
|
||||
newfilegroups.RemoveAt(fileIndexTobeRemoved);
|
||||
testDatabaseInfo.Filegroups = newfilegroups.ToArray();
|
||||
|
||||
// Validate the result files
|
||||
await ObjectManagementTestUtils.SaveObject(parametersForUpdate, testDatabaseInfo);
|
||||
DatabaseViewInfo databaseViewInfoAfterFileDelete = await ObjectManagementTestUtils.GetDatabaseObject(parametersForUpdate, testDatabaseInfo);
|
||||
Assert.That(((DatabaseInfo)databaseViewInfoAfterFileDelete.ObjectInfo).Filegroups.Count, Is.EqualTo(2), $"Should have only 3 filegroups as we removed one");
|
||||
filegroup = ((DatabaseInfo)databaseViewInfoAfterFileDelete.ObjectInfo).Filegroups.FirstOrDefault(x => x.Name == databaseFilegroup[1].Name);
|
||||
Assert.That(filegroup, Is.Null, $"filegroup should exists");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task DetachDatabaseTest()
|
||||
|
||||
@@ -127,7 +127,28 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
return databaseFiles.ToArray();
|
||||
}
|
||||
|
||||
internal static UserInfo GetTestUserInfo(DatabaseUserType userType, string userName = null, string loginName = null)
|
||||
internal static List<FileGroupSummary> GetTestDatabaseFilegroups()
|
||||
{
|
||||
List<FileGroupSummary> fgs = new List<FileGroupSummary>();
|
||||
fgs.Add(new FileGroupSummary()
|
||||
{
|
||||
Id = -1,
|
||||
Name = "rowFilegroup1",
|
||||
IsDefault = false,
|
||||
IsReadOnly = false,
|
||||
AutogrowAllFiles = true,
|
||||
Type = FileGroupType.RowsFileGroup
|
||||
});
|
||||
fgs.Add(new FileGroupSummary()
|
||||
{
|
||||
Id = -2,
|
||||
Name = "memOptFg1",
|
||||
Type = FileGroupType.MemoryOptimizedDataFileGroup
|
||||
});
|
||||
return fgs;
|
||||
}
|
||||
|
||||
internal static UserInfo GetTestUserInfo(DatabaseUserType userType, string userName = null, string loginName = null)
|
||||
{
|
||||
return new UserInfo()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user