mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Add Delete Database dialog to enable additional deletion options (#24109)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "4.9.0.10",
|
||||
"version": "4.9.0.13",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-net7.0.zip",
|
||||
"Windows_64": "win-x64-net7.0.zip",
|
||||
|
||||
@@ -95,6 +95,12 @@
|
||||
"title": "%title.objectProperties%",
|
||||
"icon": "$(edit)"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteDatabase",
|
||||
"category": "MSSQL",
|
||||
"title": "%title.deleteObject%",
|
||||
"icon": "$(trash)"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteObject",
|
||||
"category": "MSSQL",
|
||||
@@ -504,6 +510,10 @@
|
||||
"command": "mssql.objectProperties",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteDatabase",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteObject",
|
||||
"when": "false"
|
||||
@@ -569,9 +579,14 @@
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !isCloud && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures && (productQualityType =~ /^(insider|dev)$/ || isDevelopment)",
|
||||
"group": "1_objectManagement@2"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@3"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@3"
|
||||
},
|
||||
{
|
||||
@@ -614,9 +629,14 @@
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && config.workbench.enablePreviewFeatures",
|
||||
"group": "inline@2"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "inline@3"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "inline@3"
|
||||
}
|
||||
],
|
||||
@@ -661,9 +681,14 @@
|
||||
"when": "connectionProvider == MSSQL && nodeType == Column && config.workbench.enablePreviewFeatures && nodePath =~ /^.*\\/Tables\\/.*\\/Columns\\/.*$/",
|
||||
"group": "1_objectManagement@1"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@3"
|
||||
},
|
||||
{
|
||||
"command": "mssql.deleteObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@3"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1645,6 +1645,18 @@ export namespace DetachDatabaseRequest {
|
||||
export const type = new RequestType<DetachDatabaseRequestParams, string, void, void>('objectManagement/detachDatabase');
|
||||
}
|
||||
|
||||
export interface DropDatabaseRequestParams {
|
||||
connectionUri: string;
|
||||
objectUrn: string;
|
||||
dropConnections: boolean;
|
||||
deleteBackupHistory: boolean;
|
||||
generateScript: boolean;
|
||||
}
|
||||
|
||||
export namespace DropDatabaseRequest {
|
||||
export const type = new RequestType<DropDatabaseRequestParams, string, void, void>('objectManagement/dropDatabase');
|
||||
}
|
||||
|
||||
// ------------------------------- < Object Management > ------------------------------------
|
||||
|
||||
// ------------------------------- < Encryption IV/KEY updation Event > ------------------------------------
|
||||
|
||||
2
extensions/mssql/src/mssql.d.ts
vendored
2
extensions/mssql/src/mssql.d.ts
vendored
@@ -984,6 +984,8 @@ declare module 'mssql' {
|
||||
* @returns A string value representing the generated TSQL query if generateScript was set to true, and an empty string otherwise.
|
||||
*/
|
||||
detachDatabase(connectionUri: string, objectUrn: string, dropConnections: boolean, updateStatistics: boolean, generateScript: boolean): Thenable<string>;
|
||||
|
||||
deleteDatabase(connectionUri: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string>;
|
||||
}
|
||||
// Object Management - End.
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { ApplicationRoleDialog } from './ui/applicationRoleDialog';
|
||||
import { DatabaseDialog } from './ui/databaseDialog';
|
||||
import { ServerPropertiesDialog } from './ui/serverPropertiesDialog';
|
||||
import { DetachDatabaseDialog } from './ui/detachDatabaseDialog';
|
||||
import { DeleteDatabaseDialog } from './ui/deleteDatabaseDialog';
|
||||
|
||||
export function registerObjectManagementCommands(appContext: AppContext) {
|
||||
// Notes: Change the second parameter to false to use the actual object management service.
|
||||
@@ -46,6 +47,9 @@ export function registerObjectManagementCommands(appContext: AppContext) {
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.detachDatabase', async (context: azdata.ObjectExplorerContext) => {
|
||||
await handleDetachDatabase(context, service);
|
||||
}));
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.deleteDatabase', async (context: azdata.ObjectExplorerContext) => {
|
||||
await handleDeleteDatabase(context, service);
|
||||
}));
|
||||
}
|
||||
|
||||
function getObjectManagementService(appContext: AppContext, useTestService: boolean): IObjectManagementService {
|
||||
@@ -286,6 +290,35 @@ async function handleDetachDatabase(context: azdata.ObjectExplorerContext, servi
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeleteDatabase(context: azdata.ObjectExplorerContext, service: IObjectManagementService): Promise<void> {
|
||||
const connectionUri = await getConnectionUri(context);
|
||||
if (!connectionUri) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const parentUrn = await getParentUrn(context);
|
||||
const options: ObjectManagementDialogOptions = {
|
||||
connectionUri: connectionUri,
|
||||
isNewObject: false,
|
||||
database: context.connectionProfile!.databaseName!,
|
||||
objectType: context.nodeInfo.nodeType as ObjectManagement.NodeType,
|
||||
objectName: context.nodeInfo.label,
|
||||
parentUrn: parentUrn,
|
||||
objectUrn: context.nodeInfo!.metadata!.urn,
|
||||
objectExplorerContext: context
|
||||
};
|
||||
const dialog = new DeleteDatabaseDialog(service, options);
|
||||
await dialog.open();
|
||||
}
|
||||
catch (err) {
|
||||
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDeleteDatabaseDialog, err).withAdditionalProperties({
|
||||
objectType: context.nodeInfo!.nodeType
|
||||
}).send();
|
||||
console.error(err);
|
||||
await vscode.window.showErrorMessage(objectManagementLoc.OpenDeleteDatabaseDialogError(getErrorMessage(err)));
|
||||
}
|
||||
}
|
||||
|
||||
function getDialog(service: IObjectManagementService, dialogOptions: ObjectManagementDialogOptions): ObjectManagementDialogBase<ObjectManagement.SqlObject, ObjectManagement.ObjectViewInfo<ObjectManagement.SqlObject>> {
|
||||
switch (dialogOptions.objectType) {
|
||||
case ObjectManagement.NodeType.ApplicationRole:
|
||||
|
||||
@@ -33,6 +33,7 @@ export const ViewMemoryServerPropertiesDocUrl = 'https://learn.microsoft.com/sql
|
||||
export const DetachDatabaseDocUrl = 'https://go.microsoft.com/fwlink/?linkid=2240322';
|
||||
export const DatabaseGeneralPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-general-page';
|
||||
export const DatabaseOptionsPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-options-page'
|
||||
export const DeleteDatabaseDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/drop-database-transact-sql';
|
||||
|
||||
export const enum TelemetryActions {
|
||||
CreateObject = 'CreateObject',
|
||||
@@ -41,7 +42,8 @@ export const enum TelemetryActions {
|
||||
OpenPropertiesDialog = 'OpenPropertiesDialog',
|
||||
RenameObject = 'RenameObject',
|
||||
UpdateObject = 'UpdateObject',
|
||||
OpenDetachDatabaseDialog = 'OpenDetachDatabaseDialog'
|
||||
OpenDetachDatabaseDialog = 'OpenDetachDatabaseDialog',
|
||||
OpenDeleteDatabaseDialog = 'OpenDeleteDatabaseDialog'
|
||||
}
|
||||
|
||||
export const ObjectManagementViewName = 'ObjectManagement';
|
||||
|
||||
@@ -458,6 +458,8 @@ export interface Database extends ObjectManagement.SqlObject {
|
||||
|
||||
export interface DatabaseViewInfo extends ObjectManagement.ObjectViewInfo<Database> {
|
||||
isAzureDB: boolean;
|
||||
isManagedInstance: boolean;
|
||||
isSqlOnDemand: boolean;
|
||||
loginNames?: OptionsCollection;
|
||||
collationNames?: OptionsCollection;
|
||||
compatibilityLevels?: OptionsCollection;
|
||||
|
||||
@@ -102,6 +102,13 @@ export function OpenDetachDatabaseDialogError(error: string): string {
|
||||
}, "An error occurred while opening the detach database dialog. {0}", error);
|
||||
}
|
||||
|
||||
export function OpenDeleteDatabaseDialogError(error: string): string {
|
||||
return localize({
|
||||
key: 'objectManagement.openDeleteDatabaseDialogError',
|
||||
comment: ['{0}: error message.']
|
||||
}, "An error occurred while opening the delete database dialog. {0}", error);
|
||||
}
|
||||
|
||||
export function OpenObjectPropertiesDialogError(objectType: string, objectName: string, error: string): string {
|
||||
return localize({
|
||||
key: 'objectManagement.openObjectPropertiesDialogError',
|
||||
@@ -182,6 +189,12 @@ export const DatabaseFilePathLabel = localize('objectManagement.databaseFilePath
|
||||
export const DatabaseFileGroupLabel = localize('objectManagement.databaseFileGroup', "File Group");
|
||||
export const DetachDatabaseOptions = localize('objectManagement.detachDatabaseOptions', "Detach Database Options");
|
||||
export const DetachButtonLabel = localize('objectManagement.detachButtonLabel', "Detach");
|
||||
export const DeleteDatabaseDialogTitle = (dbName: string) => localize('objectManagement.deleteDatabaseDialogTitle', "Delete Database - {0} (Preview)", dbName);
|
||||
export const DeleteButtonLabel = localize('objectManagement.deleteButtonLabel', "Delete");
|
||||
export const DeleteDatabaseOptions = localize('objectManagement.deleteDatabaseOptions', "Delete Database Options");
|
||||
export const DeleteDropConnections = localize('objectManagement.deleteDropConnections', "Close existing connections");
|
||||
export const DeleteDropBackupHistory = localize('objectManagement.deleteDropBackupHistory', "Delete backup and restore history information for database");
|
||||
export const DatabaseDetailsLabel = localize('objectManagement.databaseDetails', "Database Details");
|
||||
|
||||
// Login
|
||||
export const BlankPasswordConfirmationText: string = localize('objectManagement.blankPasswordConfirmation', "Creating a login with a blank password is a security risk. Are you sure you want to continue?");
|
||||
|
||||
@@ -70,6 +70,11 @@ export class ObjectManagementService extends BaseService implements IObjectManag
|
||||
const params: contracts.DetachDatabaseRequestParams = { connectionUri, objectUrn, dropConnections, updateStatistics, generateScript };
|
||||
return this.runWithErrorHandling(contracts.DetachDatabaseRequest.type, params);
|
||||
}
|
||||
|
||||
async deleteDatabase(connectionUri: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Promise<string> {
|
||||
const params: contracts.DropDatabaseRequestParams = { connectionUri, objectUrn, dropConnections, deleteBackupHistory, generateScript };
|
||||
return this.runWithErrorHandling(contracts.DropDatabaseRequest.type, params);
|
||||
}
|
||||
}
|
||||
|
||||
const ServerLevelSecurableTypes: SecurableTypeMetadata[] = [
|
||||
@@ -241,6 +246,10 @@ export class TestObjectManagementService implements IObjectManagementService {
|
||||
return this.delayAndResolve('');
|
||||
}
|
||||
|
||||
deleteDatabase(connectionUri: string, objectUrn: string, dropConnections: boolean, deleteBackupHistory: boolean, generateScript: boolean): Thenable<string> {
|
||||
return this.delayAndResolve('');
|
||||
}
|
||||
|
||||
private generateSearchResult(objectType: ObjectManagement.NodeType, schema: string | undefined, count: number): ObjectManagement.SearchResultItem[] {
|
||||
let items: ObjectManagement.SearchResultItem[] = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||
import { Database, DatabaseViewInfo } from '../interfaces';
|
||||
import { DeleteDatabaseDocUrl } from '../constants';
|
||||
import { DeleteButtonLabel, DeleteDatabaseDialogTitle, DeleteDropBackupHistory, DeleteDropConnections, DeleteDatabaseOptions, NameText, OwnerText, StatusText, DatabaseDetailsLabel } from '../localizedConstants';
|
||||
|
||||
export class DeleteDatabaseDialog extends ObjectManagementDialogBase<Database, DatabaseViewInfo> {
|
||||
private _dropConnections = false;
|
||||
private _deleteBackupHistory = false;
|
||||
|
||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||
super(objectManagementService, options, DeleteDatabaseDialogTitle(options.database), 'DeleteDatabase');
|
||||
this.dialogObject.okButton.label = DeleteButtonLabel;
|
||||
}
|
||||
|
||||
protected override get isDirty(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async initializeUI(): Promise<void> {
|
||||
let components = [];
|
||||
|
||||
let tableData = [[this.objectInfo.name, this.objectInfo.owner ?? '', this.objectInfo.status ?? '']];
|
||||
let columnNames = [NameText, OwnerText, StatusText];
|
||||
let fileTable = this.createTable(DatabaseDetailsLabel, columnNames, tableData);
|
||||
let tableGroup = this.createGroup(DatabaseDetailsLabel, [fileTable], false);
|
||||
components.push(tableGroup);
|
||||
|
||||
if (!this.viewInfo.isAzureDB && !this.viewInfo.isManagedInstance && !this.viewInfo.isSqlOnDemand) {
|
||||
let connCheckbox = this.createCheckbox(DeleteDropConnections, async checked => {
|
||||
this._dropConnections = checked;
|
||||
});
|
||||
let updateCheckbox = this.createCheckbox(DeleteDropBackupHistory, async checked => {
|
||||
this._deleteBackupHistory = checked;
|
||||
});
|
||||
let checkboxGroup = this.createGroup(DeleteDatabaseOptions, [connCheckbox, updateCheckbox], false);
|
||||
components.push(checkboxGroup);
|
||||
}
|
||||
this.formContainer.addItems(components);
|
||||
}
|
||||
|
||||
protected override get helpUrl(): string {
|
||||
return DeleteDatabaseDocUrl;
|
||||
}
|
||||
|
||||
protected override async saveChanges(contextId: string, object: ObjectManagement.SqlObject): Promise<void> {
|
||||
await this.objectManagementService.deleteDatabase(this.options.connectionUri, this.options.objectUrn, this._dropConnections, this._deleteBackupHistory, false);
|
||||
}
|
||||
|
||||
protected override async generateScript(): Promise<string> {
|
||||
return await this.objectManagementService.deleteDatabase(this.options.connectionUri, this.options.objectUrn, this._dropConnections, this._deleteBackupHistory, true);
|
||||
}
|
||||
|
||||
protected override async validateInput(): Promise<string[]> {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user