mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Enable Detach Database in database handler (#2110)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.SqlClient;
|
||||
@@ -13,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.Admin;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using NUnit.Framework;
|
||||
using static Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper;
|
||||
@@ -201,7 +203,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
{ AzureEdition.Hyperscale, "HS_Gen5_2" }
|
||||
};
|
||||
Assert.That(actualLevelsMap.Count, Is.EqualTo(expectedDefaults.Count), "Did not get expected number of editions for DatabaseHandler's service levels");
|
||||
foreach(AzureEdition edition in expectedDefaults.Keys)
|
||||
foreach (AzureEdition edition in expectedDefaults.Keys)
|
||||
{
|
||||
if (AzureSqlDbHelper.TryGetServiceObjectiveInfo(edition, out var expectedLevelInfo))
|
||||
{
|
||||
@@ -211,7 +213,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
|
||||
var expectedDefaultIndex = expectedLevelInfo.Key;
|
||||
var expectedDefault = expectedServiceLevels[expectedDefaultIndex];
|
||||
var actualDefault = actualServiceLevels[0];
|
||||
var actualDefault = actualServiceLevels[0];
|
||||
Assert.That(actualDefault, Is.EqualTo(expectedDefault), "Did not get expected default SLO for edition '{0}'", edition.DisplayName);
|
||||
}
|
||||
else
|
||||
@@ -240,7 +242,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
{ AzureEdition.Hyperscale, "0MB" }
|
||||
};
|
||||
Assert.That(actualSizesMap.Count, Is.EqualTo(expectedDefaults.Count), "Did not get expected number of editions for DatabaseHandler's max sizes");
|
||||
foreach(AzureEdition edition in expectedDefaults.Keys)
|
||||
foreach (AzureEdition edition in expectedDefaults.Keys)
|
||||
{
|
||||
if (AzureSqlDbHelper.TryGetDatabaseSizeInfo(edition, out var expectedSizeInfo))
|
||||
{
|
||||
@@ -250,7 +252,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
|
||||
var expectedDefaultIndex = expectedSizeInfo.Key;
|
||||
var expectedDefault = expectedSizes[expectedDefaultIndex];
|
||||
var actualDefault = actualSizes[0];
|
||||
var actualDefault = actualSizes[0];
|
||||
Assert.That(actualDefault, Is.EqualTo(expectedDefault.ToString()), "Did not get expected default size for edition '{0}'", edition.DisplayName);
|
||||
}
|
||||
else
|
||||
@@ -304,6 +306,132 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DetachDatabaseTest()
|
||||
{
|
||||
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master");
|
||||
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 to test with
|
||||
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");
|
||||
|
||||
var handler = new DatabaseHandler(ConnectionService.Instance);
|
||||
var connectionUri = connectionResult.ConnectionInfo.OwnerUri;
|
||||
|
||||
var detachParams = new DetachDatabaseRequestParams()
|
||||
{
|
||||
ConnectionUri = connectionUri,
|
||||
ObjectUrn = objUrn,
|
||||
DropConnections = true,
|
||||
UpdateStatistics = true,
|
||||
GenerateScript = false
|
||||
};
|
||||
|
||||
// Get databases's files so we can reattach it later before dropping it
|
||||
var fileCollection = new StringCollection();
|
||||
var smoDatabase = server.GetSmoObject(objUrn) as Database;
|
||||
foreach (FileGroup fileGroup in smoDatabase!.FileGroups)
|
||||
{
|
||||
foreach (DataFile file in fileGroup.Files)
|
||||
{
|
||||
fileCollection.Add(file.FileName);
|
||||
}
|
||||
}
|
||||
foreach (LogFile file in smoDatabase.LogFiles)
|
||||
{
|
||||
fileCollection.Add(file.FileName);
|
||||
}
|
||||
|
||||
var script = handler.Detach(detachParams);
|
||||
Assert.That(script, Is.Empty, "Should only return an empty string if GenerateScript is false");
|
||||
|
||||
server.Databases.Refresh();
|
||||
Assert.That(DatabaseExists(testDatabase.Name!, server), Is.False, $"Expected database '{testDatabase.Name}' was not detached succesfully");
|
||||
|
||||
server.AttachDatabase(testDatabase.Name, fileCollection);
|
||||
|
||||
server.Databases.Refresh();
|
||||
Assert.That(DatabaseExists(testDatabase.Name!, server), $"Expected database '{testDatabase.Name}' was not re-attached succesfully");
|
||||
}
|
||||
finally
|
||||
{
|
||||
DropDatabase(server, testDatabase.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DetachDatabaseScriptTest()
|
||||
{
|
||||
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master");
|
||||
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 to test with
|
||||
var parametersForCreation = ObjectManagementTestUtils.GetInitializeViewRequestParams(connectionResult.ConnectionInfo.OwnerUri, "master", true, SqlObjectType.Database, "", "");
|
||||
await ObjectManagementTestUtils.SaveObject(parametersForCreation, testDatabase);
|
||||
|
||||
var handler = new DatabaseHandler(ConnectionService.Instance);
|
||||
var connectionUri = connectionResult.ConnectionInfo.OwnerUri;
|
||||
|
||||
// Default use case
|
||||
var detachParams = new DetachDatabaseRequestParams()
|
||||
{
|
||||
ConnectionUri = connectionUri,
|
||||
ObjectUrn = objUrn,
|
||||
DropConnections = false,
|
||||
UpdateStatistics = false,
|
||||
GenerateScript = true
|
||||
};
|
||||
var expectedDetachScript = $"EXEC master.dbo.sp_detach_db @dbname = N'{testDatabase.Name}'";
|
||||
var expectedAlterScript = $"ALTER DATABASE [{testDatabase.Name}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
|
||||
var expectedStatsScript = $"EXEC master.dbo.sp_detach_db @dbname = N'{testDatabase.Name}', @skipchecks = 'false'";
|
||||
|
||||
var actualScript = handler.Detach(detachParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedDetachScript).IgnoreCase);
|
||||
|
||||
// Drop connections only
|
||||
detachParams.DropConnections = true;
|
||||
actualScript = handler.Detach(detachParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedDetachScript).IgnoreCase);
|
||||
Assert.That(actualScript, Does.Contain(expectedAlterScript).IgnoreCase);
|
||||
|
||||
// Update statistics only
|
||||
detachParams.DropConnections = false;
|
||||
detachParams.UpdateStatistics = true;
|
||||
actualScript = handler.Detach(detachParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedStatsScript).IgnoreCase);
|
||||
|
||||
// Both drop and update
|
||||
detachParams.DropConnections = true;
|
||||
actualScript = handler.Detach(detachParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedAlterScript).IgnoreCase);
|
||||
Assert.That(actualScript, Does.Contain(expectedStatsScript).IgnoreCase);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DropDatabase(server, testDatabase.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool DatabaseExists(string dbName, Server server)
|
||||
{
|
||||
server.Databases.Refresh();
|
||||
|
||||
Reference in New Issue
Block a user