in gui/frontend/src/modules/db-editor/SidebarCommandHandler.tsx [77:936]
public async handleConnectionTreeCommand(command: Command, entry?: ConnectionDataModelEntry,
qualifiedName?: QualifiedName, pageId?: string): Promise<ISideBarCommandResult> {
let success = false;
const connection = entry?.connection;
if (connection) {
// Commands/actions that are related to a specific connection.
switch (command.command) {
case "msg.editConnection": {
success = await requisitions.execute("job", [
{ requestType: "showPage", parameter: {} },
{ requestType: "editConnection", parameter: connection.details.id },
]);
break;
}
case "msg.duplicateConnection": {
success = await requisitions.execute("job", [
{ requestType: "showPage", parameter: {} },
{ requestType: "duplicateConnection", parameter: connection.details.id },
]);
break;
}
case "msg.removeConnection": {
success = await requisitions.execute("job", [
{ requestType: "showPage", parameter: {} },
{ requestType: "removeConnection", parameter: connection.details.id },
]);
break;
}
case "msg.loadDumpFromDisk": {
// TODO: Implement this for embedded scenarios.
// It's not possible in a browser to get a full folder path for this functionality.
break;
}
case "msg.newSessionUsingConnection": {
let caption: string;
if (entry.type === CdmEntityType.Connection) {
caption = entry.details.caption;
const dbConnectionId = entry.details.id;
const details: IShellSessionDetails = {
sessionId: uuid(),
caption: `Session to ${caption}`,
dbConnectionId,
};
success = await requisitions.execute("job",
[{ requestType: "openSession", parameter: details }]);
}
break;
}
case "msg.mrs.loadSchemaFromJSONFile": {
// TODO: works with the file system, not possible in a browser.
break;
}
case "msg.mrs.exportServiceSdk": {
// TODO: works with the file system, not possible in a browser.
break;
}
case "msg.mrs.dumpCreateServiceSqlScript": {
// TODO: works with the file system, not possible in a browser.
break;
}
case "msg.mrs.copyCreateServiceSql": {
const object = entry as ICdmRestDbObjectEntry;
try {
const result = await entry.connection.backend.mrs.getServiceCreateStatement(object.details.id,
true,
);
requisitions.writeToClipboard(result);
void ui.showInformationMessage("The CREATE statement was copied to the system clipboard", {});
success = true;
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error getting the SQL for this REST Service: ${message}`, {});
}
break;
}
case "msg.mrs.configureMySQLRestService": {
const treeItem = entry.type === CdmEntityType.Connection
? entry
: entry.type === CdmEntityType.MrsRoot
? entry.parent
: undefined;
if (treeItem) {
if (!treeItem.isOpen) {
const statusBarItem = ui.createStatusBarItem();
try {
statusBarItem.text = "$(loading~spin) Opening Database Connection ...";
await treeItem.refresh?.();
} catch (error) {
break;
} finally {
statusBarItem.dispose();
}
}
success = await this.mrsHubRef.current
?.showMrsConfigurationDialog(connection) ?? false;
}
break;
}
case "msg.mrs.enableMySQLRestService":
case "msg.mrs.disableMySQLRestService": {
const enableMrs = command.command === "msg.mrs.enableMySQLRestService";
success = await this.configureMrs(connection, enableMrs);
break;
}
case "msg.mrs.addService": {
const configured = await this.checkMrsStatus(connection.backend, false);
if (configured) {
success = await this.mrsHubRef.current?.showMrsServiceDialog(connection.backend) ?? false;
}
break;
}
case "msg.mrs.editService": {
const service = entry as ICdmRestServiceEntry;
success = await this.mrsHubRef.current
?.showMrsServiceDialog(connection.backend, service.details) ?? false;
break;
}
case "msg.mrs.setCurrentService": {
const service = entry as ICdmRestServiceEntry;
try {
await connection.backend?.mrs.setCurrentService(service.details.id);
void ui.showInformationMessage("The MRS service has been set as the new default service.", {});
success = true;
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage(`Error setting the default MRS service: ${message}`, {});
}
break;
}
case "msg.mrs.linkAuthApp": {
try {
const service = entry as ICdmRestServiceEntry;
const apps = await connection.backend.mrs.listAuthApps();
const items = apps.map((app) => {
return app.name;
});
const response = await DialogHost.showDialog({
id: "msg.mrs.linkToService",
type: DialogType.Select,
title: "Select REST Authentication App",
parameters: {
prompt: "Select a REST Authentication app to link it to this service.",
default: "Accept",
options: items,
},
});
if (response.closure === DialogResponseClosure.Accept) {
const name = response.values?.input as string;
if (name) {
const authApp = apps.find((candidate) => {
return candidate.name === name;
});
if (authApp !== undefined) {
try {
await connection.backend.mrs.linkAuthAppToService(authApp.id!, service.id);
void ui.showInformationMessage("The MRS Authentication App has " +
`been linked to service ${service.details.name}`, {});
success = true;
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage("Error linking an MRS Authentication App: " +
`${message}`, {});
}
}
}
}
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage(`Error adding a new MRS Authentication App: ${message}`, {});
}
break;
}
case "msg.mrs.addAuthApp": {
try {
let serviceDetails;
if (entry.type === CdmEntityType.MrsService) {
serviceDetails = entry.details;
}
success = await this.mrsHubRef.current?.showMrsAuthAppDialog(connection.backend, undefined,
serviceDetails) ?? false;
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage(`Error adding a new MRS Authentication App: ${message}`, {});
}
break;
}
case "msg.mrs.editAuthApp": {
try {
const app = entry as ICdmRestAuthAppEntry;
success = await this.mrsHubRef.current?.showMrsAuthAppDialog(
connection.backend, app.details) ?? false;
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage(`Error adding a new MRS Authentication App: ${message}`, {});
}
break;
}
case "msg.mrs.deleteAuthApp": {
const app = entry as ICdmRestAuthAppEntry;
if (app.details.id) {
const prompt = `Are you sure the MRS authentication app "${app.details.name}" should ` +
"be deleted?";
const response = await DialogHost.showDialog({
id: "msg.mrs.deleteAuthApp",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt,
accept: "Delete",
refuse: "No",
default: "No",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
await connection.backend?.mrs.deleteAuthApp(app.details.id);
success = true;
void ui.showInformationMessage(`The MRS Authentication App ` +
`"${app.details.name}" has been deleted.`, {});
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error removing an Auth App: ${message}`, {});
}
}
}
break;
}
case "msg.mrs.linkToService": {
const authApp = entry as ICdmRestAuthAppEntry;
const services = await connection.backend.mrs.listServices();
const items = services.map((s) => {
return s.urlContextRoot;
});
const response = await DialogHost.showDialog({
id: "msg.mrs.linkToService",
type: DialogType.Select,
title: "Select REST Service",
parameters: {
prompt: "Select a REST service to link this authentication app to.",
default: "Accept",
options: items,
},
});
if (response.closure === DialogResponseClosure.Accept) {
const name = response.values?.input as string;
if (name) {
const service = services.find((candidate) => {
return candidate.urlContextRoot === name;
});
if (service) {
try {
await connection.backend.mrs.linkAuthAppToService(authApp.details.id!,
service.id);
void ui.showInformationMessage("The MRS Authentication App has been linked " +
`to service ${service.name}`, {});
success = true;
} catch (reason) {
const message = convertErrorToString(reason);
void ui.showErrorMessage("Error linking an MRS Authentication App: " +
`${message}`, {});
}
}
}
}
break;
}
case "msg.mrs.unlinkAuthApp": {
const app = entry as ICdmRestServiceAuthAppEntry;
if (app.details.id) {
const prompt = `Are you sure the MRS authentication app "${app.details.name}" should ` +
`be unlinked from the service "${app.parent.caption}"?`;
const response = await DialogHost.showDialog({
id: "msg.mrs.unlinkAuthApp",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt,
accept: "Unlink",
refuse: "No",
default: "No",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
await connection.backend?.mrs.unlinkAuthAppFromService(app.details.id,
app.parent.details.id);
success = true;
void ui.showInformationMessage(`The MRS Authentication App ` +
`"${app.details.name}" has been unlinked.`, {});
} catch (error) {
void ui.showErrorMessage(`Error removing an Auth App: ${String(error)}`, {});
}
}
}
break;
}
case "msg.mrs.deleteService": {
const service = entry as ICdmRestServiceEntry;
const response = await DialogHost.showDialog({
id: "msg.mrs.deleteService",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt: `Are you sure the MRS service ${service.details.urlContextRoot} should be deleted?`,
accept: "Delete",
refuse: "No",
default: "No",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
await connection.backend?.mrs.deleteService(service.details.id);
success = true;
void ui.showInformationMessage("The MRS service has been deleted successfully.", {});
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error removing an MRS service: ${message}`, {});
}
}
break;
}
case "msg.mrs.editSchema": {
const service = entry as ICdmRestSchemaEntry;
const path = await this.mrsHubRef.current?.showMrsSchemaDialog(connection.backend,
qualifiedName?.schema, service.details);
if (path) {
success = true;
}
break;
}
case "msg.mrs.deleteSchema": {
const response = await DialogHost.showDialog({
id: "msg.mrs.deleteSchema",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt: `Are you sure the MRS schema ${entry.caption} should be deleted?`,
accept: "Delete",
refuse: "Cancel",
default: "Cancel",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
const schema = entry as ICdmRestSchemaEntry;
await connection.backend.mrs.deleteSchema(schema.details.id, schema.details.serviceId);
success = true;
void ui.showInformationMessage("The MRS schema has been deleted successfully.", {});
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error removing an MRS schema: ${message}`, {});
}
}
break;
}
case "msg.mrs.addDbObject": {
switch (entry.type) {
case CdmEntityType.Table:
case CdmEntityType.View:
case CdmEntityType.StoredFunction:
case CdmEntityType.StoredProcedure: {
try {
const configured = await this.checkMrsStatus(connection.backend, true);
if (!configured) {
return { success: false };
}
// First, create a new temporary dbObject, then call the DbObject dialog.
const dbObject = await this.createNewDbObject(entry);
await this.mrsHubRef.current?.showMrsDbObjectDialog(connection.backend,
{ dbObject, createObject: true });
return {
success: true,
mrsServiceId: dbObject.serviceId,
mrsSchemaId: dbObject.dbSchemaId,
};
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error while adding the object: ${message}`, {});
return { success: false };
}
}
default: {
void ui.showErrorMessage(
`The database object type '${entry.caption}' is not supported at this time`, {});
}
}
break;
}
case "msg.mrs.editDbObject": {
const dbObject = entry as ICdmRestDbObjectEntry;
await this.mrsHubRef.current?.showMrsDbObjectDialog(connection.backend,
{ dbObject: dbObject.details, createObject: false });
return {
success: true,
mrsServiceId: dbObject.details.serviceId,
mrsSchemaId: dbObject.details.dbSchemaId,
};
}
case "msg.mrs.copyDbObjectRequestPath": {
const path = this.buildDbObjectRequestPath(entry as ICdmRestDbObjectEntry);
if (path) {
requisitions.writeToClipboard(path.toString());
success = true;
void ui.showInformationMessage("The DB Object Path was copied to the system clipboard", {});
}
break;
}
case "msg.mrs.copyCreateSchemaSql": {
try {
const schema = entry as ICdmRestSchemaEntry;
const result = await entry.connection.backend.mrs.getSchemaCreateStatement(schema.details.id,
true);
requisitions.writeToClipboard(result);
success = true;
void ui.showInformationMessage("The CREATE statement was copied to the system clipboard", {});
} catch (reason) {
void ui.showErrorMessage(`Error getting the SQL for this REST Schema`, {});
}
break;
}
case "msg.mrs.copyCreateDbObjectSql": {
try {
const object = entry as ICdmRestDbObjectEntry;
const result = await entry.connection.backend.mrs.getDbObjectCreateStatement(object.details.id);
requisitions.writeToClipboard(result);
success = true;
void ui.showInformationMessage("The CREATE statement was copied to the system clipboard", {});
} catch (reason) {
void ui.showErrorMessage(`Error getting the SQL for this REST DB Object`, {});
}
break;
}
case "msg.mrs.deleteDbObject": {
const response = await DialogHost.showDialog({
id: "msg.mrs.deleteDbObject",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt: `Are you sure you want to delete the REST DB Object ${entry.caption}?`,
accept: "Delete",
refuse: "Cancel",
default: "Cancel",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
const dbObject = entry as ICdmRestDbObjectEntry;
await connection.backend.mrs.deleteDbObject(dbObject.details.id);
success = true;
void ui.showInformationMessage("The MRS DB object has been deleted successfully.", {});
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error removing an MRS schema: ${message}`, {});
}
}
break;
}
case "msg.mrs.addUser": {
if (this.mrsHubRef.current) {
const authApp = entry as ICdmRestAuthAppEntry;
success = await this.mrsHubRef.current.showMrsUserDialog(authApp.connection.backend,
authApp.details);
}
break;
}
case "msg.mrs.editUser": {
if (this.mrsHubRef.current) {
const user = entry as ICdmRestUserEntry;
const authApp = user.parent;
success = await this.mrsHubRef.current.showMrsUserDialog(authApp.connection.backend,
authApp.details, user.details);
}
break;
}
case "msg.mrs.deleteUser": {
const response = await DialogHost.showDialog({
id: "msg.mrs.deleteUser",
type: DialogType.Confirm,
parameters: {
title: "Confirmation",
prompt: `Are you sure you want to delete the MRS user "${entry.caption}"?`,
accept: "Delete",
refuse: "Cancel",
default: "Cancel",
},
});
if (response.closure === DialogResponseClosure.Accept) {
try {
const user = entry as ICdmRestUserEntry;
await connection.backend.mrs.deleteUser(user.details.id!);
success = true;
void ui.showInformationMessage(`The MRS user ${user.caption} has been deleted ` +
`successfully.`, {});
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error removing an MRS user: ${message}`, {});
}
}
break;
}
case "msg.selectRows": {
if (qualifiedName?.schema && qualifiedName.name) {
let query;
const uppercaseKeywords = Settings.get("dbEditor.upperCaseKeywords", true);
const select = uppercaseKeywords ? "SELECT" : "select";
const from = uppercaseKeywords ? "FROM" : "from";
if (entry.type === CdmEntityType.Column) {
const qualifiedTableName = `${quote(qualifiedName.schema)}.${quote(qualifiedName.table!)}`;
query = `${select} ${qualifiedTableName}.${quote(qualifiedName.name)} ${from} ` +
`${qualifiedTableName}`;
} else {
const qualifiedTableName = `${quote(qualifiedName.schema)}.${quote(qualifiedName.name)}`;
query = `${select} * ${from} ${qualifiedTableName}`;
}
const options: IEditorExtendedExecutionOptions = {
code: query,
language: "mysql",
};
const connectionId = connection.details.id;
success = await requisitions.execute("job", [
{
requestType: "showPage",
parameter: { connectionId, pageId },
},
{ requestType: "editorRunCode", parameter: options },
]);
}
break;
}
case "filterMenuItem": {
break;
}
case "inspectorMenuItem": {
break;
}
case "msg.copyNameToEditor":
case "msg.copyNameToClipboard": {
if (command.command === "msg.copyNameToClipboard") {
requisitions.writeToClipboard(entry.caption);
void ui.showInformationMessage("The name was copied to the system clipboard", {});
success = true;
} else {
const connectionId = connection.details.id;
success = await requisitions.execute("job", [
{
requestType: "showPage",
parameter: { connectionId },
},
{ requestType: "editorInsertText", parameter: entry.caption },
]);
}
break;
}
case "msg.copyCreateStatementToClipboard":
case "msg.copyCreateStatementToEditor": {
let type;
let qualifier = qualifiedName ? `\`${qualifiedName.schema}\`.` : "";
let index = 1; // The column index in the result row.
switch (entry.type) {
case CdmEntityType.Schema: {
type = "schema";
qualifier = "";
break;
}
case CdmEntityType.Table: {
type = "table";
break;
}
case CdmEntityType.View: {
type = "view";
break;
}
case CdmEntityType.StoredFunction: {
index = 2;
type = "function";
break;
}
case CdmEntityType.StoredProcedure: {
index = 2;
type = "procedure";
break;
}
case CdmEntityType.Trigger: {
type = "trigger";
break;
}
case CdmEntityType.Event: {
index = 3;
type = "event";
break;
}
default:
}
if (type) {
const data = await connection?.backend.execute(
`show create ${type} ${qualifier}\`${entry.caption}\``);
const rows = data?.rows;
if (rows && rows.length > 0) {
// Returns one row with 2 columns.
const row = rows[0] as string[];
if (row.length > index) {
if (command.command === "msg.copyCreateStatementToClipboard") {
requisitions.writeToClipboard(row[index]);
void ui.showInformationMessage("The CREATE statement was copied to the " +
"system clipboard", {});
success = true;
} else {
const connectionId = connection.details.id;
success = await requisitions.execute("job", [
{
requestType: "showPage",
parameter: { connectionId, pageId },
},
{ requestType: "editorInsertText", parameter: row[index] },
]);
}
}
}
}
break;
}
case "msg.createSchema": {
break;
}
case "msg.alterSchema": {
break;
}
case "msg.mrs.addSchema": {
if (this.mrsHubRef.current) {
const configured = await this.checkMrsStatus(connection.backend, true);
if (!configured) {
return { success: false };
}
try {
const serviceId = await this.mrsHubRef.current.showMrsSchemaDialog(connection.backend,
entry.caption);
return {
success: true,
mrsServiceId: serviceId,
};
} catch (error) {
const message = convertErrorToString(error);
void ui.showErrorMessage(`Error while adding the schema: ${message}.`, {});
return { success: false };
}
}
break;
}
case "refreshMenuItem": {
break;
}
default:
}
}
// Other Commands/actions that are not related to a specific connection.
switch (command.command) {
case "msg.addConnection": {
success = await requisitions.execute("job", [
{ requestType: "showPage", parameter: {} },
{ requestType: "addNewConnection", parameter: {} },
]);
break;
}
case "msg.refreshConnections": {
await this.connectionDataModel.reloadConnections();
success = true;
break;
}
case "msg.mrs.docs": {
window.open("https://dev.mysql.com/doc/dev/mysql-rest-service/latest/", "_blank");
success = true;
break;
}
case "msg.mrs.docs.service": {
window.open("https://dev.mysql.com/doc/dev/mysql-rest-service/latest/#rest-service-properties",
"_blank");
success = true;
break;
}
case "msg.fileBugReport": {
// The version is injected by the vite config.
const currentVersion = process.env.versionNumber ?? "1.0.0";
void window.open("https://bugs.mysql.com/report.php?category=Shell%20VSCode%20Extension" +
`&version=${currentVersion}`);
break;
}
case "msg.mrs.copyDbObjectRequestPath": {
const path = this.buildDbObjectRequestPath(entry as ICdmRestDbObjectEntry);
if (path) {
requisitions.writeToClipboard(path.toString());
success = true;
void ui.showInformationMessage("The DB Object Path was copied to the system clipboard", {});
}
break;
}
case "msg.mrs.openDbObjectRequestPath": {
const path = this.buildDbObjectRequestPath(entry as ICdmRestDbObjectEntry);
if (path) {
window.open(path);
success = true;
}
break;
}
case "msg.copyNameToClipboard": {
requisitions.writeToClipboard(entry!.caption);
success = true;
break;
}
case "msg.dropSchema": {
const schema = entry as ICdmSchemaEntry;
await this.dropItem(schema);
success = true;
break;
}
default:
}
return { success };
}