Handle undefined nodeInfo for top-level database objects (#24298)

This commit is contained in:
Cory Rivera
2023-09-06 14:12:07 -07:00
committed by GitHub
parent 9f4e19f3db
commit 32817ae52e
2 changed files with 65 additions and 46 deletions

View File

@@ -69,40 +69,52 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
if (!connectionUri) { if (!connectionUri) {
return; return;
} }
let objectType: ObjectManagement.NodeType; let objectType: ObjectManagement.NodeType;
switch (context.nodeInfo!.objectType) { if (context.nodeInfo) {
case FolderType.ApplicationRoles: switch (context.nodeInfo.objectType) {
objectType = ObjectManagement.NodeType.ApplicationRole; case FolderType.ApplicationRoles:
break; objectType = ObjectManagement.NodeType.ApplicationRole;
case FolderType.DatabaseRoles:
objectType = ObjectManagement.NodeType.DatabaseRole;
break;
case FolderType.ServerLevelLogins:
objectType = ObjectManagement.NodeType.ServerLevelLogin;
break;
case FolderType.ServerLevelServerRoles:
objectType = ObjectManagement.NodeType.ServerLevelServerRole;
break;
case FolderType.Users:
objectType = ObjectManagement.NodeType.User;
break;
case FolderType.Databases:
objectType = ObjectManagement.NodeType.Database;
break;
}
// Fall back to node type in case the user right clicked on an object instead of a folder
if (!objectType) {
switch (context.nodeInfo!.nodeType) {
case ObjectManagement.NodeType.ApplicationRole:
case ObjectManagement.NodeType.DatabaseRole:
case ObjectManagement.NodeType.ServerLevelLogin:
case ObjectManagement.NodeType.ServerLevelServerRole:
case ObjectManagement.NodeType.User:
case ObjectManagement.NodeType.Database:
objectType = context.nodeInfo!.nodeType as ObjectManagement.NodeType;
break; break;
default: case FolderType.DatabaseRoles:
throw new Error(objectManagementLoc.NoDialogFoundError(context.nodeInfo!.nodeType, context.nodeInfo!.objectType)); objectType = ObjectManagement.NodeType.DatabaseRole;
break;
case FolderType.ServerLevelLogins:
objectType = ObjectManagement.NodeType.ServerLevelLogin;
break;
case FolderType.ServerLevelServerRoles:
objectType = ObjectManagement.NodeType.ServerLevelServerRole;
break;
case FolderType.Users:
objectType = ObjectManagement.NodeType.User;
break;
case FolderType.Databases:
objectType = ObjectManagement.NodeType.Database;
break;
}
// Fall back to node type in case the user right clicked on an object instead of a folder
if (!objectType) {
switch (context.nodeInfo.nodeType) {
case ObjectManagement.NodeType.ApplicationRole:
case ObjectManagement.NodeType.DatabaseRole:
case ObjectManagement.NodeType.ServerLevelLogin:
case ObjectManagement.NodeType.ServerLevelServerRole:
case ObjectManagement.NodeType.User:
case ObjectManagement.NodeType.Database:
objectType = context.nodeInfo.nodeType as ObjectManagement.NodeType;
break;
default:
throw new Error(objectManagementLoc.NoDialogFoundError(context.nodeInfo.nodeType, context.nodeInfo.objectType));
}
}
} 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 we don't have a database name, then we have to assume it's a server node, which isn't valid for the New Object command.
if (context.connectionProfile?.databaseName?.length > 0) {
objectType = ObjectManagement.NodeType.Database;
} else {
throw new Error(objectManagementLoc.NotSupportedError(ObjectManagement.NodeType.Server));
} }
} }
@@ -111,7 +123,7 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
const options: ObjectManagementDialogOptions = { const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri, connectionUri: connectionUri,
isNewObject: true, isNewObject: true,
database: context.connectionProfile!.databaseName!, database: context.connectionProfile?.databaseName,
objectType: objectType, objectType: objectType,
objectName: '', objectName: '',
parentUrn: parentUrn, parentUrn: parentUrn,
@@ -122,7 +134,7 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
} }
catch (err) { catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenNewObjectDialog, err).withAdditionalProperties({ TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenNewObjectDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType objectType: objectType
}).send(); }).send();
console.error(err); console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenNewObjectDialogError(objectManagementLoc.getNodeTypeDisplayName(objectType), getErrorMessage(err))); await vscode.window.showErrorMessage(objectManagementLoc.OpenNewObjectDialogError(objectManagementLoc.getNodeTypeDisplayName(objectType), getErrorMessage(err)));
@@ -329,14 +341,16 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
} }
try { try {
const parentUrn = await getParentUrn(context); 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)}']`;
const options: ObjectManagementDialogOptions = { const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri, connectionUri: connectionUri,
isNewObject: false, isNewObject: false,
database: context.connectionProfile!.databaseName!, database: context.connectionProfile!.databaseName!,
objectType: context.nodeInfo.nodeType as ObjectManagement.NodeType, objectType: ObjectManagement.NodeType.Database,
objectName: context.nodeInfo.label, objectName: objectName,
parentUrn: parentUrn, parentUrn: parentUrn,
objectUrn: context.nodeInfo!.metadata!.urn, objectUrn: objectUrn,
objectExplorerContext: context objectExplorerContext: context
}; };
const dialog = new DropDatabaseDialog(service, options); const dialog = new DropDatabaseDialog(service, options);
@@ -344,7 +358,7 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
} }
catch (err) { catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDropDatabaseDialog, err).withAdditionalProperties({ TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDropDatabaseDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType objectType: ObjectManagement.NodeType.Database
}).send(); }).send();
console.error(err); console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenDropDatabaseDialogError(getErrorMessage(err))); await vscode.window.showErrorMessage(objectManagementLoc.OpenDropDatabaseDialogError(getErrorMessage(err)));
@@ -380,12 +394,16 @@ async function getConnectionUri(context: azdata.ObjectExplorerContext): Promise<
return connectionUri; return connectionUri;
} }
async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<string> { async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<string | undefined> {
let node = undefined; let parentUrn: string = undefined;
let currentNodePath = context.nodeInfo!.parentNodePath; if (context.nodeInfo) {
do { let node = undefined;
node = await azdata.objectexplorer.getNode(context.connectionProfile!.id, currentNodePath); let currentNodePath = context.nodeInfo.parentNodePath;
currentNodePath = node?.parentNodePath; do {
} while (node && currentNodePath && !node.metadata?.urn); node = await azdata.objectexplorer.getNode(context.connectionProfile!.id, currentNodePath);
return node?.metadata?.urn; currentNodePath = node?.parentNodePath;
} while (node && currentNodePath && !node.metadata?.urn);
parentUrn = node?.metadata?.urn;
}
return parentUrn;
} }

View File

@@ -27,6 +27,7 @@ export const DatabaseRoleTypeDisplayName: string = localize('objectManagement.Da
export const DatabaseRoleTypeDisplayNameInTitle: string = localize('objectManagement.DatabaseRoleTypeDisplayNameInTitle', "Database Role"); export const DatabaseRoleTypeDisplayNameInTitle: string = localize('objectManagement.DatabaseRoleTypeDisplayNameInTitle', "Database Role");
export const DatabaseTypeDisplayNameInTitle: string = localize('objectManagement.DatabaseDisplayNameInTitle', "Database"); export const DatabaseTypeDisplayNameInTitle: string = localize('objectManagement.DatabaseDisplayNameInTitle', "Database");
export function NoDialogFoundError(nodeType: string, objectType: string): string { return localize('objectManagement.noDialogFoundError', "Could not find a supported dialog for node type '{0}' and object type '{1}'.", nodeType, objectType); } export function NoDialogFoundError(nodeType: string, objectType: string): string { return localize('objectManagement.noDialogFoundError', "Could not find a supported dialog for node type '{0}' and object type '{1}'.", nodeType, objectType); }
export function NotSupportedError(objectType: string): string { return localize('objectManagement.notSupportedError', "This command is not supported for object type '{0}'.", objectType); }
// Shared Strings // Shared Strings
export const FailedToRetrieveConnectionInfoErrorMessage: string = localize('objectManagement.noConnectionUriError', "Failed to retrieve the connection information, please reconnect and try again.") export const FailedToRetrieveConnectionInfoErrorMessage: string = localize('objectManagement.noConnectionUriError', "Failed to retrieve the connection information, please reconnect and try again.")