Skip to content

Commit

Permalink
Handle undefined nodeInfo for top-level database objects (microsoft#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
corivera authored Sep 6, 2023
1 parent 9f4e19f commit 32817ae
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 46 deletions.
110 changes: 64 additions & 46 deletions extensions/mssql/src/objectManagement/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,40 +69,52 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
if (!connectionUri) {
return;
}

let objectType: ObjectManagement.NodeType;
switch (context.nodeInfo!.objectType) {
case FolderType.ApplicationRoles:
objectType = ObjectManagement.NodeType.ApplicationRole;
break;
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;
if (context.nodeInfo) {
switch (context.nodeInfo.objectType) {
case FolderType.ApplicationRoles:
objectType = ObjectManagement.NodeType.ApplicationRole;
break;
case FolderType.DatabaseRoles:
objectType = ObjectManagement.NodeType.DatabaseRole;
break;
case FolderType.ServerLevelLogins:
objectType = ObjectManagement.NodeType.ServerLevelLogin;
break;
case FolderType.ServerLevelServerRoles:
objectType = ObjectManagement.NodeType.ServerLevelServerRole;
break;
default:
throw new Error(objectManagementLoc.NoDialogFoundError(context.nodeInfo!.nodeType, context.nodeInfo!.objectType));
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));
}
}

Expand All @@ -111,7 +123,7 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri,
isNewObject: true,
database: context.connectionProfile!.databaseName!,
database: context.connectionProfile?.databaseName,
objectType: objectType,
objectName: '',
parentUrn: parentUrn,
Expand All @@ -122,7 +134,7 @@ async function handleNewObjectDialogCommand(context: azdata.ObjectExplorerContex
}
catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenNewObjectDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: objectType
}).send();
console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenNewObjectDialogError(objectManagementLoc.getNodeTypeDisplayName(objectType), getErrorMessage(err)));
Expand Down Expand Up @@ -329,22 +341,24 @@ async function handleDropDatabase(context: azdata.ObjectExplorerContext, service
}
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)}']`;
const options: ObjectManagementDialogOptions = {
connectionUri: connectionUri,
isNewObject: false,
database: context.connectionProfile!.databaseName!,
objectType: context.nodeInfo.nodeType as ObjectManagement.NodeType,
objectName: context.nodeInfo.label,
objectType: ObjectManagement.NodeType.Database,
objectName: objectName,
parentUrn: parentUrn,
objectUrn: context.nodeInfo!.metadata!.urn,
objectUrn: objectUrn,
objectExplorerContext: context
};
const dialog = new DropDatabaseDialog(service, options);
await dialog.open();
}
catch (err) {
TelemetryReporter.createErrorEvent2(ObjectManagementViewName, TelemetryActions.OpenDropDatabaseDialog, err).withAdditionalProperties({
objectType: context.nodeInfo!.nodeType
objectType: ObjectManagement.NodeType.Database
}).send();
console.error(err);
await vscode.window.showErrorMessage(objectManagementLoc.OpenDropDatabaseDialogError(getErrorMessage(err)));
Expand Down Expand Up @@ -380,12 +394,16 @@ async function getConnectionUri(context: azdata.ObjectExplorerContext): Promise<
return connectionUri;
}

async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<string> {
let node = undefined;
let currentNodePath = context.nodeInfo!.parentNodePath;
do {
node = await azdata.objectexplorer.getNode(context.connectionProfile!.id, currentNodePath);
currentNodePath = node?.parentNodePath;
} while (node && currentNodePath && !node.metadata?.urn);
return node?.metadata?.urn;
async function getParentUrn(context: azdata.ObjectExplorerContext): Promise<string | undefined> {
let parentUrn: string = undefined;
if (context.nodeInfo) {
let node = undefined;
let currentNodePath = context.nodeInfo.parentNodePath;
do {
node = await azdata.objectexplorer.getNode(context.connectionProfile!.id, currentNodePath);
currentNodePath = node?.parentNodePath;
} while (node && currentNodePath && !node.metadata?.urn);
parentUrn = node?.metadata?.urn;
}
return parentUrn;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const DatabaseRoleTypeDisplayName: string = localize('objectManagement.Da
export const DatabaseRoleTypeDisplayNameInTitle: string = localize('objectManagement.DatabaseRoleTypeDisplayNameInTitle', "Database Role");
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 NotSupportedError(objectType: string): string { return localize('objectManagement.notSupportedError', "This command is not supported for object type '{0}'.", objectType); }

// Shared Strings
export const FailedToRetrieveConnectionInfoErrorMessage: string = localize('objectManagement.noConnectionUriError', "Failed to retrieve the connection information, please reconnect and try again.")
Expand Down

0 comments on commit 32817ae

Please sign in to comment.