Enable Rename Database for on-prem servers. Use common method for getting OE node info. (#24517)

This commit is contained in:
Cory Rivera
2023-09-27 11:21:07 -07:00
committed by GitHub
parent 646b001160
commit 131c288ab4
2 changed files with 85 additions and 46 deletions

View File

@@ -578,7 +578,7 @@
},
{
"command": "mssql.renameObject",
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|Table|View|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && config.workbench.enablePreviewFeatures",
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|Table|View|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && config.workbench.enablePreviewFeatures",
"group": "1_objectManagement@1"
},
{

View File

@@ -146,20 +146,16 @@ async function handleObjectPropertiesDialogCommand(context: azdata.ObjectExplore
if (!connectionUri) {
return;
}
const object = await getObjectInfoForContext(context);
try {
const parentUrn = context.isConnectionNode ? undefined : await getParentUrn(context);
const objectType = context.nodeInfo ? context.nodeInfo.nodeType as ObjectManagement.NodeType : (context.connectionProfile.databaseName === '' ? ObjectManagement.NodeType.Server : ObjectManagement.NodeType.Database);
const objectName = context.nodeInfo ? context.nodeInfo.label : (!context.connectionProfile.databaseName ? context.connectionProfile.serverName : context.connectionProfile.databaseName);
const objectUrn = context.nodeInfo ? context.nodeInfo!.metadata!.urn : (context.connectionProfile.databaseName === '' ? 'Server' : `Server/Database[@Name='${escapeSingleQuotes(context.connectionProfile.databaseName)}']`);
const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri,
isNewObject: false,
database: context.connectionProfile!.databaseName!,
objectType: objectType,
objectName: objectName,
parentUrn: parentUrn,
objectUrn: objectUrn,
database: context.connectionProfile?.databaseName,
objectType: object.type,
objectName: object.name,
parentUrn: object.parentUrn,
objectUrn: object.urn,
objectExplorerContext: context
};
const dialog = getDialog(service, options);
@@ -167,10 +163,10 @@ async function handleObjectPropertiesDialogCommand(context: azdata.ObjectExplore
}
catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenPropertiesDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: object.type
}).send();
console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenObjectPropertiesDialogError(objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType), context.nodeInfo!.label, getErrorMessage(err)));
await vscode.window.showErrorMessage(objectManagementLoc.OpenObjectPropertiesDialogError(objectManagementLoc.getNodeTypeDisplayName(object.type), object.name, getErrorMessage(err)));
}
}
@@ -179,16 +175,18 @@ async function handleDropObjectCommand(context: azdata.ObjectExplorerContext, se
if (!connectionUri) {
return;
}
const object = await getObjectInfoForContext(context);
let additionalConfirmationMessage: string | undefined = undefined;
switch (context.nodeInfo!.nodeType) {
switch (object.type) {
case ObjectManagement.NodeType.ServerLevelLogin:
additionalConfirmationMessage = objectManagementLoc.DropLoginConfirmationText;
break;
default:
break;
}
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType);
let confirmMessage = objectManagementLoc.DropObjectConfirmationText(nodeTypeDisplayName, context.nodeInfo!.label);
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(object.type);
let confirmMessage = objectManagementLoc.DropObjectConfirmationText(nodeTypeDisplayName, object.name);
if (additionalConfirmationMessage) {
confirmMessage = `${additionalConfirmationMessage} ${confirmMessage}`;
}
@@ -197,23 +195,23 @@ async function handleDropObjectCommand(context: azdata.ObjectExplorerContext, se
return;
}
azdata.tasks.startBackgroundOperation({
displayName: objectManagementLoc.DropObjectOperationDisplayName(nodeTypeDisplayName, context.nodeInfo!.label),
displayName: objectManagementLoc.DropObjectOperationDisplayName(nodeTypeDisplayName, object.name),
description: '',
isCancelable: false,
operation: async (operation) => {
try {
const startTime = Date.now();
await service.drop(connectionUri, context.nodeInfo.nodeType as ObjectManagement.NodeType, context.nodeInfo!.metadata!.urn);
await service.drop(connectionUri, object.type, object.urn);
TelemetryReporter.sendTelemetryEvent(TelemetryActions.DropObject, {
objectType: context.nodeInfo!.nodeType
objectType: object.type
}, {
elapsedTimeMs: Date.now() - startTime
});
}
catch (err) {
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.DropObjectError(nodeTypeDisplayName, context.nodeInfo!.label, getErrorMessage(err)));
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.DropObjectError(nodeTypeDisplayName, object.name, getErrorMessage(err)));
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.DropObject, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: object.type
}).send();
console.error(err);
return;
@@ -229,11 +227,12 @@ async function handleRenameObjectCommand(context: azdata.ObjectExplorerContext,
if (!connectionUri) {
return;
}
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(context.nodeInfo!.nodeType);
const originalName = context.nodeInfo!.metadata!.name;
const object = await getObjectInfoForContext(context);
const nodeTypeDisplayName = objectManagementLoc.getNodeTypeDisplayName(object.type);
const newName = await vscode.window.showInputBox({
title: objectManagementLoc.RenameObjectDialogTitle,
value: originalName,
value: object.name,
validateInput: (value: string): string | undefined => {
if (!value) {
return objectManagementLoc.NameCannotBeEmptyError;
@@ -245,28 +244,28 @@ async function handleRenameObjectCommand(context: azdata.ObjectExplorerContext,
});
// return if no change was made or the dialog was canceled.
if (newName === originalName || !newName) {
if (newName === object.name || !newName) {
return;
}
azdata.tasks.startBackgroundOperation({
displayName: objectManagementLoc.RenameObjectOperationDisplayName(nodeTypeDisplayName, originalName, newName),
displayName: objectManagementLoc.RenameObjectOperationDisplayName(nodeTypeDisplayName, object.name, newName),
description: '',
isCancelable: false,
operation: async (operation) => {
try {
const startTime = Date.now();
await service.rename(connectionUri, context.nodeInfo.nodeType as ObjectManagement.NodeType, context.nodeInfo!.metadata!.urn, newName);
await service.rename(connectionUri, object.type, object.urn, newName);
TelemetryReporter.sendTelemetryEvent(TelemetryActions.RenameObject, {
objectType: context.nodeInfo!.nodeType
objectType: object.type
}, {
elapsedTimeMs: Date.now() - startTime
});
}
catch (err) {
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.RenameObjectError(nodeTypeDisplayName, originalName, newName, getErrorMessage(err)));
operation.updateStatus(azdata.TaskStatus.Failed, objectManagementLoc.RenameObjectError(nodeTypeDisplayName, object.name, newName, getErrorMessage(err)));
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.RenameObject, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: object.type
}).send();
console.error(err);
return;
@@ -282,16 +281,19 @@ async function handleDetachDatabase(context: azdata.ObjectExplorerContext, servi
if (!connectionUri) {
return;
}
const object = await getObjectInfoForContext(context);
try {
const parentUrn = await getParentUrn(context);
if (object.type !== ObjectManagement.NodeType.Database) {
throw new Error(objectManagementLoc.NotSupportedError(ObjectManagement.NodeType.Database));
}
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,
database: object.name,
objectType: object.type,
objectName: object.name,
parentUrn: object.parentUrn,
objectUrn: object.urn,
objectExplorerContext: context
};
const dialog = new DetachDatabaseDialog(service, options);
@@ -299,7 +301,7 @@ async function handleDetachDatabase(context: azdata.ObjectExplorerContext, servi
}
catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDetachDatabaseDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: object.type
}).send();
console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenDetachDatabaseDialogError(getErrorMessage(err)));
@@ -339,18 +341,19 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
if (!connectionUri) {
return;
}
const object = await getObjectInfoForContext(context);
try {
const parentUrn = await getParentUrn(context);
const objectName = context.nodeInfo?.label ?? context.connectionProfile.databaseName;
const objectUrn = context.nodeInfo?.metadata?.urn ?? `Server/Database[@Name='${escapeSingleQuotes(context.connectionProfile.databaseName)}']`;
if (object.type !== ObjectManagement.NodeType.Database) {
throw new Error(objectManagementLoc.NotSupportedError(ObjectManagement.NodeType.Database));
}
const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri,
isNewObject: false,
database: context.connectionProfile!.databaseName!,
objectType: ObjectManagement.NodeType.Database,
objectName: objectName,
parentUrn: parentUrn,
objectUrn: objectUrn,
database: object.name,
objectType: object.type,
objectName: object.name,
parentUrn: object.parentUrn,
objectUrn: object.urn,
objectExplorerContext: context
};
const dialog = new DropDatabaseDialog(service, options);
@@ -358,7 +361,7 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
}
catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDropDatabaseDialog, err).withAdditionalProperties({
objectType: ObjectManagement.NodeType.Database
objectType: object.type
}).send();
console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenDropDatabaseDialogError(getErrorMessage(err)));
@@ -407,3 +410,39 @@ async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<stri
}
return parentUrn;
}
interface ObjectInfo {
parentUrn: string;
name: string;
type: ObjectManagement.NodeType;
urn: string;
}
async function getObjectInfoForContext(context: azdata.ObjectExplorerContext): Promise<ObjectInfo> {
let nodeType: ObjectManagement.NodeType;
let objectName: string;
let objectUrn: string;
if (context.nodeInfo) {
nodeType = context.nodeInfo.nodeType as ObjectManagement.NodeType;
objectName = context.nodeInfo.metadata?.name;
objectUrn = context.nodeInfo.metadata?.urn;
} else {
// Node info will be missing for top level connection items like servers and databases, so make a best guess here based on connection info.
if (context.connectionProfile?.databaseName?.length > 0) {
nodeType = ObjectManagement.NodeType.Database;
objectName = context.connectionProfile.databaseName;
objectUrn = `Server/Database[@Name='${escapeSingleQuotes(objectName)}']`;
} else {
nodeType = ObjectManagement.NodeType.Server;
objectName = context.connectionProfile.serverName;
objectUrn = 'Server';
}
}
let parentUrn = await getParentUrn(context);
return {
parentUrn: parentUrn,
name: objectName,
type: nodeType,
urn: objectUrn
}
}