From a59f77f618aea6156fc80fb832d3efcb9848411f Mon Sep 17 00:00:00 2001 From: Fabio Di Stasio Date: Sun, 19 Dec 2021 11:59:09 +0100 Subject: [PATCH] feat(MySQL): ability to cancel queries --- .stylelintrc | 3 +- src/common/customizations/defaults.js | 1 + src/common/customizations/mysql.js | 1 + src/main/ipc-handlers/schema.js | 15 ++++- src/main/libs/clients/MySQLClient.js | 40 ++++++++++-- src/renderer/components/WorkspaceTabQuery.vue | 62 +++++++++++++++---- .../WorkspaceTabQueryEmptyState.vue | 11 +++- src/renderer/i18n/en-US.js | 3 +- src/renderer/ipc-api/Schema.js | 4 ++ src/renderer/scss/main.scss | 28 +++++++++ 10 files changed, 149 insertions(+), 19 deletions(-) diff --git a/.stylelintrc b/.stylelintrc index 079be0a0..f4abfb45 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -1,6 +1,7 @@ { "extends": [ - "stylelint-config-standard" + "stylelint-config-standard", + "stylelint-config-standard-scss" ], "fix": true, "formatter": "verbose", diff --git a/src/common/customizations/defaults.js b/src/common/customizations/defaults.js index e41ce30b..4a417792 100644 --- a/src/common/customizations/defaults.js +++ b/src/common/customizations/defaults.js @@ -11,6 +11,7 @@ module.exports = { sslConnection: false, sshConnection: false, fileConnection: false, + cancelQueries: false, // Tools processesList: false, usersManagement: false, diff --git a/src/common/customizations/mysql.js b/src/common/customizations/mysql.js index ff471b34..624edbe8 100644 --- a/src/common/customizations/mysql.js +++ b/src/common/customizations/mysql.js @@ -12,6 +12,7 @@ module.exports = { engines: true, sslConnection: true, sshConnection: true, + cancelQueries: true, // Tools processesList: true, // Structure diff --git a/src/main/ipc-handlers/schema.js b/src/main/ipc-handlers/schema.js index 10d71447..93c5f5a2 100644 --- a/src/main/ipc-handlers/schema.js +++ b/src/main/ipc-handlers/schema.js @@ -135,7 +135,7 @@ export default connections => { } }); - ipcMain.handle('raw-query', async (event, { uid, query, schema }) => { + ipcMain.handle('raw-query', async (event, { uid, query, schema, tabUid }) => { if (!query) return; try { @@ -143,6 +143,7 @@ export default connections => { nest: true, details: true, schema, + tabUid, comments: false }); @@ -152,4 +153,16 @@ export default connections => { return { status: 'error', response: err.toString() }; } }); + + ipcMain.handle('kill-tab-query', async (event, { uid, tabUid }) => { + if (!tabUid) return; + + try { + await connections[uid].killTabQuery(tabUid); + return { status: 'success' }; + } + catch (err) { + return { status: 'error', response: err.toString() }; + } + }); }; diff --git a/src/main/libs/clients/MySQLClient.js b/src/main/libs/clients/MySQLClient.js index 2aff5e58..d53d3589 100644 --- a/src/main/libs/clients/MySQLClient.js +++ b/src/main/libs/clients/MySQLClient.js @@ -9,6 +9,7 @@ export class MySQLClient extends AntaresCore { super(args); this._schema = null; + this._runningConnections = new Map(); this.types = { 0: 'DECIMAL', @@ -1210,10 +1211,26 @@ export class MySQLClient extends AntaresCore { }); } + /** + * + * @param {number} id + * @returns {Promise} + */ async killProcess (id) { return await this.raw(`KILL ${id}`); } + /** + * + * @param {string} tabUid + * @returns {Promise} + */ + async killTabQuery (tabUid) { + const id = this._runningConnections.get(tabUid); + if (id) + return await this.killProcess(id); + } + /** * CREATE TABLE * @@ -1535,6 +1552,9 @@ export class MySQLClient extends AntaresCore { const isPool = typeof this._connection.getConnection === 'function'; const connection = isPool ? await this._connection.getConnection() : this._connection; + if (args.tabUid && isPool) + this._runningConnections.set(args.tabUid, connection.connection.connectionId); + if (args.schema) await connection.query(`USE \`${args.schema}\``); @@ -1595,7 +1615,10 @@ export class MySQLClient extends AntaresCore { }); } catch (err) { - if (isPool) connection.release(); + if (isPool) { + connection.release(); + this._runningConnections.delete(args.tabUid); + } reject(err); } @@ -1604,7 +1627,10 @@ export class MySQLClient extends AntaresCore { keysArr = keysArr ? [...keysArr, ...response] : response; } catch (err) { - if (isPool) connection.release(); + if (isPool) { + connection.release(); + this._runningConnections.delete(args.tabUid); + } reject(err); } } @@ -1619,7 +1645,10 @@ export class MySQLClient extends AntaresCore { keys: keysArr }); }).catch((err) => { - if (isPool) connection.release(); + if (isPool) { + connection.release(); + this._runningConnections.delete(args.tabUid); + } reject(err); }); }); @@ -1627,7 +1656,10 @@ export class MySQLClient extends AntaresCore { resultsArr.push({ rows, report, fields, keys, duration }); } - if (isPool) connection.release(); + if (isPool) { + connection.release(); + this._runningConnections.delete(args.tabUid); + } return resultsArr.length === 1 ? resultsArr[0] : resultsArr; } diff --git a/src/renderer/components/WorkspaceTabQuery.vue b/src/renderer/components/WorkspaceTabQuery.vue index aa93f5e2..98f48173 100644 --- a/src/renderer/components/WorkspaceTabQuery.vue +++ b/src/renderer/components/WorkspaceTabQuery.vue @@ -4,6 +4,7 @@ class="workspace-query-tab column col-12 columns col-gapless no-outline p-0" tabindex="0" @keydown.116="runQuery(query)" + @keydown.75="killTabQuery" @keydown.ctrl.alt.87="clear" @keydown.ctrl.66="beautify" @keydown.ctrl.71="openHistoryModal" @@ -22,16 +23,29 @@
- +
{{ $t('message.runQuery') }}
+
+ {{ $t('message.killQuery') }} +
{{ $t('word.format') }}
@@ -25,6 +28,9 @@
F5
+
+ CTRL + K +
CTRL + B
@@ -47,7 +53,10 @@ diff --git a/src/renderer/i18n/en-US.js b/src/renderer/i18n/en-US.js index daed3a73..21424055 100644 --- a/src/renderer/i18n/en-US.js +++ b/src/renderer/i18n/en-US.js @@ -251,7 +251,8 @@ module.exports = { killProcess: 'Kill process', closeTab: 'Close tab', goToDownloadPage: 'Go to download page', - readOnlyMode: 'Read-only mode' + readOnlyMode: 'Read-only mode', + killQuery: 'Kill query' }, faker: { address: 'Address', diff --git a/src/renderer/ipc-api/Schema.js b/src/renderer/ipc-api/Schema.js index 12fde22a..02dee1d5 100644 --- a/src/renderer/ipc-api/Schema.js +++ b/src/renderer/ipc-api/Schema.js @@ -46,6 +46,10 @@ export default class { return ipcRenderer.invoke('kill-process', params); } + static killTabQuery (params) { + return ipcRenderer.invoke('kill-tab-query', params); + } + static useSchema (params) { return ipcRenderer.invoke('use-schema', params); } diff --git a/src/renderer/scss/main.scss b/src/renderer/scss/main.scss index 2db64eb2..c28ca7ad 100644 --- a/src/renderer/scss/main.scss +++ b/src/renderer/scss/main.scss @@ -59,6 +59,34 @@ option:checked { text-overflow: ellipsis; } +.cancellable { + color: transparent !important; + min-height: 0.8rem; + position: relative; + + > .mdi, + > .span { + visibility: hidden; + } + + &::after { + content: "\2715"; + color: $light-color; + font-weight: 700; + top: 36%; + display: block; + height: 0.8rem; + left: 50%; + margin-left: -0.4rem; + margin-top: -0.4rem; + opacity: 1; + padding: 0; + position: absolute; + width: 0.8rem; + z-index: 1; + } +} + .workspace-tabs { align-content: baseline;