From 48f77bae01efbff40bd0f5ce8c66e2619f44bf3a Mon Sep 17 00:00:00 2001 From: Fabio Date: Sun, 6 Sep 2020 08:41:57 +0200 Subject: [PATCH] feat: support to multiple queries in the same tab --- package.json | 12 +- src/main/libs/AntaresConnector.js | 55 ++++---- src/renderer/components/Workspace.vue | 5 + src/renderer/components/WorkspaceQueryTab.vue | 119 ++++++++++-------- .../components/WorkspaceQueryTable.vue | 54 ++++++-- .../components/WorkspaceQueryTableRow.vue | 15 ++- src/renderer/components/WorkspaceTableTab.vue | 11 +- 7 files changed, 171 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index 25e9e2ea..49f4f74d 100644 --- a/package.json +++ b/package.json @@ -53,13 +53,13 @@ "monaco-editor": "^0.20.0", "mssql": "^6.2.1", "mysql": "^2.18.1", - "pg": "^8.3.2", + "pg": "^8.3.3", "source-map-support": "^0.5.16", "spectre.css": "^0.5.9", "vue-click-outside": "^1.1.0", "vue-i18n": "^8.21.0", "vue-the-mask": "^0.11.1", - "vuedraggable": "^2.24.0", + "vuedraggable": "^2.24.1", "vuex": "^3.5.1", "vuex-persist": "^2.2.0" }, @@ -71,7 +71,7 @@ "electron-devtools-installer": "^3.1.1", "electron-webpack": "^2.8.2", "electron-webpack-vue": "^2.4.0", - "eslint": "^7.7.0", + "eslint": "^7.8.1", "eslint-config-standard": "^14.1.1", "eslint-plugin-import": "^2.22.0", "eslint-plugin-node": "^11.1.0", @@ -80,12 +80,12 @@ "eslint-plugin-vue": "^6.2.2", "monaco-editor-webpack-plugin": "^1.9.0", "node-sass": "^4.14.1", - "sass-loader": "^10.0.1", + "sass-loader": "^10.0.2", "standard-version": "^9.0.0", - "stylelint": "^13.6.1", + "stylelint": "^13.7.0", "stylelint-config-standard": "^20.0.0", "stylelint-scss": "^3.18.0", - "vue": "^2.6.11", + "vue": "^2.6.12", "webpack": "^4.44.1" } } diff --git a/src/main/libs/AntaresConnector.js b/src/main/libs/AntaresConnector.js index e1fdf26d..b144b279 100644 --- a/src/main/libs/AntaresConnector.js +++ b/src/main/libs/AntaresConnector.js @@ -280,33 +280,44 @@ export class AntaresConnector { * @memberof AntaresConnector */ async raw (sql) { + const resultsArr = []; + const queries = sql.split(';'); + if (process.env.NODE_ENV === 'development') this._logger(sql);// TODO: replace BLOB content with a placeholder - switch (this._client) { // TODO: uniform fields with every client type, needed table name and fields array - case 'maria': - case 'mysql': { - const { rows, report, fields } = await new Promise((resolve, reject) => { - this._connection.query(sql, (err, response, fields) => { - if (err) - reject(err); - else { - resolve({ - rows: Array.isArray(response) ? response : false, - report: !Array.isArray(response) ? response : false, - fields - }); - } + for (const query of queries) { + if (!query) continue; + + switch (this._client) { // TODO: uniform fields with every client type, needed table name and fields array + case 'maria': + case 'mysql': { + const { rows, report, fields } = await new Promise((resolve, reject) => { + this._connection.query(query, (err, response, fields) => { + if (err) + reject(err); + else { + resolve({ + rows: Array.isArray(response) ? response : false, + report: !Array.isArray(response) ? response : false, + fields + }); + } + }); }); - }); - return { rows, report, fields }; + resultsArr.push({ rows, report, fields }); + break; + } + case 'mssql': { + const results = await this._connection.request().query(query); + resultsArr.push({ rows: results.recordsets[0] });// TODO: fields + break; + } + default: + break; } - case 'mssql': { - const results = await this._connection.request().query(sql); - return { rows: results.recordsets[0] };// TODO: fields - } - default: - break; } + + return resultsArr.length === 1 ? resultsArr[0] : resultsArr; } /** diff --git a/src/renderer/components/Workspace.vue b/src/renderer/components/Workspace.vue index e651b36a..aab41f0d 100644 --- a/src/renderer/components/Workspace.vue +++ b/src/renderer/components/Workspace.vue @@ -55,6 +55,11 @@ +
+

+ In future releases +

+
-
- {{ $t('word.results') }}: {{ results.rows.length }} +
+ {{ $t('word.results') }}: {{ resultsCount }}
-
- {{ $t('message.affectedRows') }}: {{ results.report.affectedRows }} +
+ {{ $t('message.affectedRows') }}: {{ affectedCount }}
{{ $t('word.schema') }}: {{ workspace.breadcrumbs.schema }} @@ -66,8 +66,10 @@ export default { query: '', lastQuery: '', isQuering: false, - results: {}, - selectedFields: [] + results: [], + resultsCount: 0, + affectedCount: 0, + selectedResultsset: 0 }; }, computed: { @@ -77,11 +79,6 @@ export default { workspace () { return this.getWorkspace(this.connection.uid); }, - table () { - if ('fields' in this.results && this.results.fields.length) - return this.results.fields[0].orgTable; - return ''; - }, schema () { if ('fields' in this.results && this.results.fields.length) return this.results.fields[0].db; @@ -94,6 +91,11 @@ export default { setTabFields: 'workspaces/setTabFields', setTabKeyUsage: 'workspaces/setTabKeyUsage' }), + getTable (index) { + if ('fields' in this.results[index] && this.results[index].fields.length) + return this.results[index].fields[0].orgTable; + return ''; + }, async runQuery (query) { if (!query) return; this.isQuering = true; @@ -107,56 +109,69 @@ export default { }; const { status, response } = await Connection.rawQuery(params); + if (status === 'success') { - this.results = response; - if (response.rows) { // if is a select - this.selectedFields = response.fields.map(field => field.orgName); + this.results = Array.isArray(response) ? response : [response]; - try { // Table data - const params = { - uid: this.connection.uid, - schema: this.schema, - table: this.table - }; + let selectedFields = []; + const fieldsArr = []; + const keysArr = []; - const { status, response } = await Tables.getTableColumns(params); + for (const [index, result] of this.results.entries()) { + if (result.rows) { // if is a select + selectedFields = result.fields.map(field => field.orgName); + this.resultsCount += result.rows.length; - if (status === 'success') { - let fields = response.filter(field => this.selectedFields.includes(field.name)); - if (this.selectedFields.length) { - fields = fields.map((field, index) => { - return { ...field, alias: this.results.fields[index].name }; - }); + try { // Table data + const params = { + uid: this.connection.uid, + schema: this.schema, + table: this.getTable(index) + }; + + const { status, response } = await Tables.getTableColumns(params); + + if (status === 'success') { + let fields = response.filter(field => selectedFields.includes(field.name)); + if (selectedFields.length) { + fields = fields.map((field, index) => { + return { ...field, alias: result.fields[index].name }; + }); + } + + fieldsArr.push(fields); } - - this.setTabFields({ cUid: this.connection.uid, tUid: this.tabUid, fields }); + else + this.addNotification({ status: 'error', message: response }); + } + catch (err) { + this.addNotification({ status: 'error', message: err.stack }); } - else - this.addNotification({ status: 'error', message: response }); - } - catch (err) { - this.addNotification({ status: 'error', message: err.stack }); - } - try { // Key usage (foreign keys) - const params = { - uid: this.connection.uid, - schema: this.schema, - table: this.table - }; + try { // Key usage (foreign keys) + const params = { + uid: this.connection.uid, + schema: this.schema, + table: this.getTable(index) + }; - const { status, response } = await Tables.getKeyUsage(params); - if (status === 'success') - this.setTabKeyUsage({ cUid: this.connection.uid, tUid: this.tabUid, keyUsage: response }); - else - this.addNotification({ status: 'error', message: response }); + const { status, response } = await Tables.getKeyUsage(params); + if (status === 'success') + keysArr.push(response); + else + this.addNotification({ status: 'error', message: response }); + } + catch (err) { + this.addNotification({ status: 'error', message: err.stack }); + } } - catch (err) { - this.addNotification({ status: 'error', message: err.stack }); + else { // if is a query without results + this.affectedCount += result.report.affectedRows; } } - else { // if is a query without results - } + console.log(fieldsArr); + this.setTabFields({ cUid: this.connection.uid, tUid: this.tabUid, fields: fieldsArr }); + this.setTabKeyUsage({ cUid: this.connection.uid, tUid: this.tabUid, keyUsage: keysArr }); } else this.addNotification({ status: 'error', message: response }); @@ -172,7 +187,9 @@ export default { this.runQuery(this.lastQuery); }, clearTabData () { - this.results = {}; + this.results = []; + this.resultsCount = 0; + this.affectedCount = 0; this.setTabFields({ cUid: this.connection.uid, tUid: this.tabUid, fields: [] }); } } diff --git a/src/renderer/components/WorkspaceQueryTable.vue b/src/renderer/components/WorkspaceQueryTable.vue index 7b20aa56..817757c2 100644 --- a/src/renderer/components/WorkspaceQueryTable.vue +++ b/src/renderer/components/WorkspaceQueryTable.vue @@ -11,6 +11,17 @@ @delete-selected="deleteSelected" @close-context="isContext = false" /> +
@@ -39,7 +50,7 @@
{ - return { ...item, _id: uidGen() }; - }) : []; + this.setLocalResults(); + this.resultsetIndex = 0; + }, + resultsetIndex () { + this.setLocalResults(); } }, updated () { if (this.$refs.table) this.refreshScroller(); + + if (this.$refs.tableWrapper) + this.scrollElement = this.$refs.tableWrapper; }, mounted () { window.addEventListener('resize', this.resizeResults); @@ -178,6 +192,12 @@ export default { return 'UNKNOWN ' + key; } }, + setLocalResults () { + this.resetSort(); + this.localResults = this.results[this.resultsetIndex] && this.results[this.resultsetIndex].rows ? this.results[this.resultsetIndex].rows.map(item => { + return { ...item, _id: uidGen() }; + }) : []; + }, resizeResults () { if (this.$refs.resultTable) { const el = this.$refs.tableWrapper; @@ -275,12 +295,15 @@ export default { resetSort () { this.currentSort = ''; this.currentSortDir = 'asc'; + }, + selectResultset (index) { + this.resultsetIndex = index; } } }; - diff --git a/src/renderer/components/WorkspaceQueryTableRow.vue b/src/renderer/components/WorkspaceQueryTableRow.vue index f5d1d975..cd796627 100644 --- a/src/renderer/components/WorkspaceQueryTableRow.vue +++ b/src/renderer/components/WorkspaceQueryTableRow.vue @@ -186,7 +186,10 @@ export default { }, props: { row: Object, - fields: Array, + fields: { + type: Array, + default: () => [] + }, keyUsage: Array }, data () { @@ -253,10 +256,12 @@ export default { return this.keyUsage.map(key => key.column); } }, - created () { - this.fields.forEach(field => { - this.isInlineEditor[field.name] = false; - }); + watch: { + fields () { + this.fields.forEach(field => { + this.isInlineEditor[field.name] = false; + }); + } }, methods: { getFieldType (cKey) { diff --git a/src/renderer/components/WorkspaceTableTab.vue b/src/renderer/components/WorkspaceTableTab.vue index 4ea09a7b..f9f20aca 100644 --- a/src/renderer/components/WorkspaceTableTab.vue +++ b/src/renderer/components/WorkspaceTableTab.vue @@ -33,8 +33,9 @@