mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Add extra delete database functionality to DatabaseHandler (#2168)
* Also fixed connections not being properly closed in Detach operations * Fixed errors being thrown in InitializeObjectView because certain db property fields are not supported against Azure
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
#nullable disable
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement.Contracts
|
||||
{
|
||||
public class DropDatabaseRequestParams : GeneralRequestDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// SFC (SMO) URN identifying the object
|
||||
/// </summary>
|
||||
public string ObjectUrn { get; set; }
|
||||
/// <summary>
|
||||
/// URI of the underlying connection for this request
|
||||
/// </summary>
|
||||
public string ConnectionUri { get; set; }
|
||||
/// <summary>
|
||||
/// Whether to drop active connections to this database
|
||||
/// </summary>
|
||||
public bool DropConnections { get; set; }
|
||||
/// <summary>
|
||||
/// Whether to delete the backup and restore history for this database
|
||||
/// </summary>
|
||||
public bool DeleteBackupHistory { get; set; }
|
||||
/// <summary>
|
||||
/// Whether to generate a TSQL script for the operation instead of dropping the database
|
||||
/// </summary>
|
||||
public bool GenerateScript { get; set; }
|
||||
}
|
||||
|
||||
public class DropDatabaseRequest
|
||||
{
|
||||
public static readonly RequestType<DropDatabaseRequestParams, string> Type = RequestType<DropDatabaseRequestParams, string>.Create("objectManagement/dropDatabase");
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
this.serviceHost.SetRequestHandler(DisposeViewRequest.Type, HandleDisposeViewRequest, true);
|
||||
this.serviceHost.SetRequestHandler(SearchRequest.Type, HandleSearchRequest, true);
|
||||
this.serviceHost.SetRequestHandler(DetachDatabaseRequest.Type, HandleDetachDatabaseRequest, true);
|
||||
this.serviceHost.SetRequestHandler(DropDatabaseRequest.Type, HandleDropDatabaseRequest, true);
|
||||
}
|
||||
|
||||
internal async Task HandleRenameRequest(RenameRequestParams requestParams, RequestContext<RenameRequestResponse> requestContext)
|
||||
@@ -206,6 +207,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
await requestContext.SendResult(sqlScript);
|
||||
}
|
||||
|
||||
internal async Task HandleDropDatabaseRequest(DropDatabaseRequestParams requestParams, RequestContext<string> requestContext)
|
||||
{
|
||||
var handler = this.GetObjectTypeHandler(SqlObjectType.Database) as DatabaseHandler;
|
||||
var sqlScript = handler.Drop(requestParams);
|
||||
await requestContext.SendResult(sqlScript);
|
||||
}
|
||||
|
||||
private IObjectTypeHandler GetObjectTypeHandler(SqlObjectType objectType)
|
||||
{
|
||||
foreach (var handler in objectTypeHandlers)
|
||||
|
||||
@@ -126,11 +126,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
bool isDw = azurePrototype != null && azurePrototype.AzureEdition == AzureEdition.DataWarehouse;
|
||||
bool isAzureDB = dataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase;
|
||||
bool isManagedInstance = dataContainer.Server.DatabaseEngineEdition == DatabaseEngineEdition.SqlManagedInstance;
|
||||
bool isSqlOnDemand = dataContainer.Server.Information.DatabaseEngineEdition == DatabaseEngineEdition.SqlOnDemand;
|
||||
|
||||
var databaseViewInfo = new DatabaseViewInfo()
|
||||
{
|
||||
ObjectInfo = new DatabaseInfo(),
|
||||
IsAzureDB = isAzureDB
|
||||
IsAzureDB = isAzureDB,
|
||||
IsManagedInstance = isManagedInstance,
|
||||
IsSqlOnDemand = isSqlOnDemand
|
||||
};
|
||||
|
||||
// Collect the Database properties information
|
||||
@@ -144,11 +147,7 @@ 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(),
|
||||
MemoryAllocatedToMemoryOptimizedObjectsInMb = ByteConverter.ConvertKbtoMb(smoDatabase.MemoryAllocatedToMemoryOptimizedObjectsInKB),
|
||||
MemoryUsedByMemoryOptimizedObjectsInMb = ByteConverter.ConvertKbtoMb(smoDatabase.MemoryUsedByMemoryOptimizedObjectsInKB),
|
||||
NumberOfUsers = smoDatabase.Users.Count,
|
||||
@@ -164,14 +163,24 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
EncryptionEnabled = smoDatabase.EncryptionEnabled
|
||||
};
|
||||
|
||||
if (!isAzureDB)
|
||||
{
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).ContainmentType = displayContainmentTypes[smoDatabase.ContainmentType];
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).RecoveryModel = displayRecoveryModels[smoDatabase.RecoveryModel];
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).LastDatabaseBackup = smoDatabase.LastBackupDate == DateTime.MinValue ? SR.databaseBackupDate_None : smoDatabase.LastBackupDate.ToString();
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).LastDatabaseLogBackup = smoDatabase.LastLogBackupDate == DateTime.MinValue ? SR.databaseBackupDate_None : smoDatabase.LastLogBackupDate.ToString();
|
||||
}
|
||||
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 (!isAzureDB)
|
||||
{
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).PageVerify = displayPageVerifyOptions[smoDatabase.PageVerify];
|
||||
((DatabaseInfo)databaseViewInfo.ObjectInfo).TargetRecoveryTimeInSec = smoDatabase.TargetRecoveryTime;
|
||||
}
|
||||
|
||||
if (prototype is DatabasePrototype160)
|
||||
{
|
||||
@@ -251,11 +260,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
}
|
||||
finally
|
||||
{
|
||||
ServerConnection serverConnection = dataContainer.Server.ConnectionContext;
|
||||
if (serverConnection.IsOpen)
|
||||
{
|
||||
serverConnection.Disconnect();
|
||||
}
|
||||
dataContainer.ServerConnection.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -290,45 +295,52 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
ConnectionInfo connectionInfo = this.GetConnectionInfo(detachParams.ConnectionUri);
|
||||
using (var dataContainer = CreateDatabaseDataContainer(detachParams.ConnectionUri, detachParams.ObjectUrn, false, null))
|
||||
{
|
||||
var smoDatabase = dataContainer.SqlDialogSubject as Database;
|
||||
if (smoDatabase != null)
|
||||
try
|
||||
{
|
||||
if (detachParams.GenerateScript)
|
||||
var smoDatabase = dataContainer.SqlDialogSubject as Database;
|
||||
if (smoDatabase != null)
|
||||
{
|
||||
sqlScript = CreateDetachScript(detachParams, smoDatabase.Name);
|
||||
if (detachParams.GenerateScript)
|
||||
{
|
||||
sqlScript = CreateDetachScript(detachParams, smoDatabase.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
DatabaseUserAccess originalAccess = smoDatabase.DatabaseOptions.UserAccess;
|
||||
try
|
||||
{
|
||||
// In order to drop all connections to the database, we switch it to single
|
||||
// user access mode so that only our current connection to the database stays open.
|
||||
// Any pending operations are terminated and rolled back.
|
||||
if (detachParams.DropConnections)
|
||||
{
|
||||
smoDatabase.Parent.KillAllProcesses(smoDatabase.Name);
|
||||
smoDatabase.DatabaseOptions.UserAccess = SqlServer.Management.Smo.DatabaseUserAccess.Single;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
smoDatabase.Parent.DetachDatabase(smoDatabase.Name, detachParams.UpdateStatistics);
|
||||
}
|
||||
catch (SmoException)
|
||||
{
|
||||
// Revert to database's previous user access level if we changed it as part of dropping connections
|
||||
// before hitting this exception.
|
||||
if (originalAccess != smoDatabase.DatabaseOptions.UserAccess)
|
||||
{
|
||||
smoDatabase.DatabaseOptions.UserAccess = originalAccess;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DatabaseUserAccess originalAccess = smoDatabase.DatabaseOptions.UserAccess;
|
||||
try
|
||||
{
|
||||
// In order to drop all connections to the database, we switch it to single
|
||||
// user access mode so that only our current connection to the database stays open.
|
||||
// Any pending operations are terminated and rolled back.
|
||||
if (detachParams.DropConnections)
|
||||
{
|
||||
smoDatabase.Parent.KillAllProcesses(smoDatabase.Name);
|
||||
smoDatabase.DatabaseOptions.UserAccess = SqlServer.Management.Smo.DatabaseUserAccess.Single;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
smoDatabase.Parent.DetachDatabase(smoDatabase.Name, detachParams.UpdateStatistics);
|
||||
}
|
||||
catch (SmoException)
|
||||
{
|
||||
// Revert to database's previous user access level if we changed it as part of dropping connections
|
||||
// before hitting this exception.
|
||||
if (originalAccess != smoDatabase.DatabaseOptions.UserAccess)
|
||||
{
|
||||
smoDatabase.DatabaseOptions.UserAccess = originalAccess;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
throw new InvalidOperationException($"Provided URN '{detachParams.ObjectUrn}' did not correspond to an existing database.");
|
||||
}
|
||||
}
|
||||
else
|
||||
finally
|
||||
{
|
||||
throw new InvalidOperationException($"Provided URN '{detachParams.ObjectUrn}' did not correspond to an existing database.");
|
||||
dataContainer.ServerConnection.Disconnect();
|
||||
}
|
||||
}
|
||||
return sqlScript;
|
||||
@@ -355,24 +367,118 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to drop the specified database
|
||||
/// </summary>
|
||||
/// <param name="dropParams">The various parameters needed for the Drop operation</param>
|
||||
public string Drop(DropDatabaseRequestParams dropParams)
|
||||
{
|
||||
var sqlScript = string.Empty;
|
||||
ConnectionInfo connectionInfo = this.GetConnectionInfo(dropParams.ConnectionUri);
|
||||
using (var dataContainer = CreateDatabaseDataContainer(dropParams.ConnectionUri, dropParams.ObjectUrn, false, null))
|
||||
{
|
||||
try
|
||||
{
|
||||
var smoDatabase = dataContainer.SqlDialogSubject as Database;
|
||||
if (smoDatabase != null)
|
||||
{
|
||||
var originalAccess = smoDatabase.DatabaseOptions.UserAccess;
|
||||
var server = smoDatabase.Parent;
|
||||
var originalExecuteMode = server.ConnectionContext.SqlExecutionModes;
|
||||
|
||||
if (dropParams.GenerateScript)
|
||||
{
|
||||
server.ConnectionContext.SqlExecutionModes = SqlExecutionModes.CaptureSql;
|
||||
server.ConnectionContext.CapturedSql.Clear();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// In order to drop all connections to the database, we switch it to single
|
||||
// user access mode so that only our current connection to the database stays open.
|
||||
// Any pending operations are terminated and rolled back.
|
||||
if (dropParams.DropConnections)
|
||||
{
|
||||
smoDatabase.DatabaseOptions.UserAccess = SqlServer.Management.Smo.DatabaseUserAccess.Single;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
if (dropParams.DeleteBackupHistory)
|
||||
{
|
||||
server.DeleteBackupHistory(smoDatabase.Name);
|
||||
}
|
||||
smoDatabase.Drop();
|
||||
if (dropParams.GenerateScript)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var scriptEntry in server.ConnectionContext.CapturedSql.Text)
|
||||
{
|
||||
if (scriptEntry != null)
|
||||
{
|
||||
builder.AppendLine(scriptEntry);
|
||||
builder.AppendLine("GO");
|
||||
}
|
||||
}
|
||||
sqlScript = builder.ToString();
|
||||
}
|
||||
}
|
||||
catch (SmoException)
|
||||
{
|
||||
// Revert to database's previous user access level if we changed it as part of dropping connections
|
||||
// before hitting this exception.
|
||||
if (originalAccess != smoDatabase.DatabaseOptions.UserAccess)
|
||||
{
|
||||
smoDatabase.DatabaseOptions.UserAccess = originalAccess;
|
||||
smoDatabase.Alter(TerminationClause.RollbackTransactionsImmediately);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (dropParams.GenerateScript)
|
||||
{
|
||||
server.ConnectionContext.SqlExecutionModes = originalExecuteMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Provided URN '{dropParams.ObjectUrn}' did not correspond to an existing database.");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
dataContainer.ServerConnection.Disconnect();
|
||||
}
|
||||
}
|
||||
return sqlScript;
|
||||
}
|
||||
|
||||
private CDataContainer CreateDatabaseDataContainer(string connectionUri, string? objectURN, bool isNewDatabase, string? databaseName)
|
||||
{
|
||||
ConnectionInfo connectionInfo = this.GetConnectionInfo(connectionUri);
|
||||
if (!isNewDatabase && !string.IsNullOrEmpty(databaseName))
|
||||
var originalDatabaseName = connectionInfo.ConnectionDetails.DatabaseName;
|
||||
try
|
||||
{
|
||||
connectionInfo.ConnectionDetails.DatabaseName = databaseName;
|
||||
if (!isNewDatabase && !string.IsNullOrEmpty(databaseName))
|
||||
{
|
||||
connectionInfo.ConnectionDetails.DatabaseName = databaseName;
|
||||
}
|
||||
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connectionInfo, databaseExists: !isNewDatabase);
|
||||
if (dataContainer.Server == null)
|
||||
{
|
||||
throw new InvalidOperationException(serverNotExistsError);
|
||||
}
|
||||
if (string.IsNullOrEmpty(objectURN))
|
||||
{
|
||||
objectURN = string.Format(System.Globalization.CultureInfo.InvariantCulture, "Server");
|
||||
}
|
||||
dataContainer.SqlDialogSubject = dataContainer.Server.GetSmoObject(objectURN);
|
||||
return dataContainer;
|
||||
}
|
||||
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connectionInfo, databaseExists: !isNewDatabase);
|
||||
if (dataContainer.Server == null)
|
||||
finally
|
||||
{
|
||||
throw new InvalidOperationException(serverNotExistsError);
|
||||
connectionInfo.ConnectionDetails.DatabaseName = originalDatabaseName;
|
||||
}
|
||||
if (string.IsNullOrEmpty(objectURN))
|
||||
{
|
||||
objectURN = string.Format(System.Globalization.CultureInfo.InvariantCulture, "Server");
|
||||
}
|
||||
dataContainer.SqlDialogSubject = dataContainer.Server.GetSmoObject(objectURN);
|
||||
return dataContainer;
|
||||
}
|
||||
|
||||
private string ConfigureDatabase(InitializeViewRequestParams viewParams, DatabaseInfo database, ConfigAction configAction, RunType runType)
|
||||
@@ -516,11 +622,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
}
|
||||
finally
|
||||
{
|
||||
ServerConnection serverConnection = dataContainer.Server.ConnectionContext;
|
||||
if (serverConnection.IsOpen)
|
||||
{
|
||||
serverConnection.Disconnect();
|
||||
}
|
||||
dataContainer.ServerConnection.Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectManagement
|
||||
public DatabaseFile[] Files { get; set; }
|
||||
|
||||
public bool IsAzureDB { get; set; }
|
||||
public bool IsManagedInstance { get; set; }
|
||||
public bool IsSqlOnDemand { get; set; }
|
||||
public string[] AzureBackupRedundancyLevels { get; set; }
|
||||
public AzureEditionDetails[] AzureServiceLevelObjectives { get; set; }
|
||||
public string[] AzureEditions { get; set; }
|
||||
|
||||
@@ -439,6 +439,113 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectManagement
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteDatabaseTest()
|
||||
{
|
||||
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 deleteParams = new DropDatabaseRequestParams()
|
||||
{
|
||||
ConnectionUri = connectionUri,
|
||||
ObjectUrn = objUrn,
|
||||
DropConnections = false,
|
||||
DeleteBackupHistory = false,
|
||||
GenerateScript = false
|
||||
};
|
||||
var script = handler.Drop(deleteParams);
|
||||
|
||||
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, $"Database '{testDatabase.Name}' was not deleted succesfully");
|
||||
}
|
||||
finally
|
||||
{
|
||||
DropDatabase(server, testDatabase.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DeleteDatabaseScriptTest()
|
||||
{
|
||||
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;
|
||||
|
||||
var deleteParams = new DropDatabaseRequestParams()
|
||||
{
|
||||
ConnectionUri = connectionUri,
|
||||
ObjectUrn = objUrn,
|
||||
DropConnections = false,
|
||||
DeleteBackupHistory = false,
|
||||
GenerateScript = true
|
||||
};
|
||||
|
||||
var expectedDeleteScript = $"DROP DATABASE [{testDatabase.Name}]";
|
||||
var expectedAlterScript = $"ALTER DATABASE [{testDatabase.Name}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
|
||||
var expectedBackupScript = $"EXEC msdb.dbo.sp_delete_database_backuphistory @database_name = N'{testDatabase.Name}'";
|
||||
|
||||
var actualScript = handler.Drop(deleteParams);
|
||||
Assert.That(DatabaseExists(testDatabase.Name!, server), "Database should not have been deleted when just generating a script.");
|
||||
Assert.That(actualScript, Does.Contain(expectedDeleteScript).IgnoreCase);
|
||||
|
||||
// Drop connections only
|
||||
deleteParams.DropConnections = true;
|
||||
actualScript = handler.Drop(deleteParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedDeleteScript).IgnoreCase);
|
||||
Assert.That(actualScript, Does.Contain(expectedAlterScript).IgnoreCase);
|
||||
|
||||
// Delete backup/restore history only
|
||||
deleteParams.DropConnections = false;
|
||||
deleteParams.DeleteBackupHistory = true;
|
||||
actualScript = handler.Drop(deleteParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedBackupScript).IgnoreCase);
|
||||
|
||||
// Both drop and update
|
||||
deleteParams.DropConnections = true;
|
||||
actualScript = handler.Drop(deleteParams);
|
||||
Assert.That(actualScript, Does.Contain(expectedAlterScript).IgnoreCase);
|
||||
Assert.That(actualScript, Does.Contain(expectedBackupScript).IgnoreCase);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DropDatabase(server, testDatabase.Name!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool DatabaseExists(string dbName, Server server)
|
||||
{
|
||||
server.Databases.Refresh();
|
||||
|
||||
Reference in New Issue
Block a user