feat: views deletion

This commit is contained in:
Fabio Di Stasio 2020-12-26 14:47:15 +01:00
parent d94b49febf
commit dcf469ebed
11 changed files with 119 additions and 22 deletions

View File

@ -1,5 +1,5 @@
export const TEXT = ['CHAR', 'VARCHAR'];
export const LONG_TEXT = ['TEXT', 'MEDIUMTEXT', 'longtext'];
export const LONG_TEXT = ['TEXT', 'MEDIUMTEXT', 'LONGTEXT'];
export const NUMBER = ['INT', 'TINYINT', 'SMALLINT', 'MEDIUMINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'DECIMAL', 'BOOL'];

View File

@ -1,5 +1,6 @@
import connection from './connection';
import tables from './tables';
import views from './views';
import updates from './updates';
import application from './application';
import database from './database';
@ -9,6 +10,7 @@ const connections = {};
export default () => {
connection(connections);
tables(connections);
views(connections);
database(connections);
updates();
application();

View File

@ -0,0 +1,23 @@
import { ipcMain } from 'electron';
export default (connections) => {
ipcMain.handle('get-view-informations', async (event, params) => {
try {
const result = await connections[params.uid].getViewInformations(params);
return { status: 'success', response: result };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
ipcMain.handle('drop-view', async (event, params) => {
try {
await connections[params.uid].dropView(params);
return { status: 'success' };
}
catch (err) {
return { status: 'error', response: err.toString() };
}
});
};

View File

@ -262,6 +262,39 @@ export class MySQLClient extends AntaresCore {
});
}
/**
* SHOW CREATE VIEW
*
* @returns {Array.<Object>} view informations
* @memberof MySQLClient
*/
async getViewInformations ({ schema, view }) {
const sql = `SHOW CREATE VIEW \`${schema}\`.\`${view}\``;
const results = await this.raw(sql);
return results.rows.map(row => {
return {
algorithm: row['Create View'].match(/(?<=CREATE ALGORITHM=).*?(?=\s)/gs)[0],
definer: row['Create View'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
security: row['Create View'].match(/(?<=SQL SECURITY ).*?(?=\s)/gs)[0],
updateOption: row['Create View'].match(/(?<=WITH ).*?(?=\s)/gs) ? row['Create View'].match(/(?<=WITH ).*?(?=\s)/gs)[0] : '',
sql: row['Create View'].match(/(?<=AS ).*?$/gs)[0],
name: row.View
};
})[0];
}
/**
* DROP VIEW
*
* @returns {Array.<Object>} parameters
* @memberof MySQLClient
*/
async dropView (params) {
const sql = `DROP VIEW \`${params.view}\``;// TODO: schema
return await this.raw(sql);
}
/**
* SHOW COLLATION
*
@ -493,7 +526,7 @@ export class MySQLClient extends AntaresCore {
* @memberof MySQLClient
*/
async dropTable (params) {
const sql = `DROP TABLE \`${params.table}\``;
const sql = `DROP TABLE \`${params.table}\``;// TODO: schema
return await this.raw(sql);
}

View File

@ -108,7 +108,7 @@ export default {
databaseContextEvent: null,
tableContextEvent: null,
selectedDatabase: '',
selectedTable: ''
selectedTable: null
};
},
computed: {

View File

@ -17,9 +17,9 @@
v-for="table of database.tables"
:key="table.name"
class="menu-item"
:class="{'text-bold': breadcrumbs.schema === database.name && breadcrumbs.table === table.name}"
@click="setBreadcrumbs({schema: database.name, table: table.name})"
@contextmenu.prevent="showTableContext($event, table.name)"
:class="{'text-bold': breadcrumbs.schema === database.name && [breadcrumbs.table, breadcrumbs.view].includes(table.name)}"
@click="setBreadcrumbs({schema: database.name, [table.type]: table.name})"
@contextmenu.prevent="showTableContext($event, table)"
>
<a class="table-name">
<i class="table-icon mdi mdi-18px mr-1" :class="table.type === 'view' ? 'mdi-table-eye' : 'mdi-table'" />

View File

@ -3,7 +3,11 @@
:context-event="contextEvent"
@close-context="closeContext"
>
<div class="context-element" @click="showEmptyModal">
<div
v-if="selectedTable.type === 'table'"
class="context-element"
@click="showEmptyModal"
>
<span class="d-flex"><i class="mdi mdi-18px mdi-table-off text-light pr-1" /> {{ $t('message.emptyTable') }}</span>
</div>
<div class="context-element" @click="showDeleteModal">
@ -22,7 +26,7 @@
</template>
<div slot="body">
<div class="mb-2">
{{ $t('message.emptyCorfirm') }} "<b>{{ selectedTable }}</b>"?
{{ $t('message.emptyCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
</div>
</div>
</ConfirmModal>
@ -33,12 +37,12 @@
>
<template slot="header">
<div class="d-flex">
<i class="mdi mdi-24px mdi-table-remove mr-1" /> {{ $t('message.deleteTable') }}
<i class="mdi mdi-24px mdi-table-remove mr-1" /> {{ selectedTable.type === 'table' ? $t('message.deleteTable') : $t('message.deleteView') }}
</div>
</template>
<div slot="body">
<div class="mb-2">
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedTable }}</b>"?
{{ $t('message.deleteCorfirm') }} "<b>{{ selectedTable.name }}</b>"?
</div>
</div>
</ConfirmModal>
@ -50,6 +54,7 @@ import { mapGetters, mapActions } from 'vuex';
import BaseContextMenu from '@/components/BaseContextMenu';
import ConfirmModal from '@/components/BaseConfirmModal';
import Tables from '@/ipc-api/Tables';
import Views from '@/ipc-api/Views';
export default {
name: 'WorkspaceExploreBarTableContext',
@ -59,7 +64,7 @@ export default {
},
props: {
contextEvent: MouseEvent,
selectedTable: String
selectedTable: Object
},
data () {
return {
@ -103,11 +108,11 @@ export default {
try {
const { status, response } = await Tables.truncateTable({
uid: this.selectedWorkspace,
table: this.selectedTable
table: this.selectedTable.name
});
if (status === 'success') {
if (this.selectedTable === this.workspace.breadcrumbs.table)
if (this.selectedTable.name === this.workspace.breadcrumbs.table)
this.changeBreadcrumbs({ table: null });
this.closeContext();
@ -122,13 +127,25 @@ export default {
},
async deleteTable () {
try {
const { status, response } = await Tables.dropTable({
uid: this.selectedWorkspace,
table: this.selectedTable
});
let res;
if (this.selectedTable.type === 'table') {
res = await Tables.dropTable({
uid: this.selectedWorkspace,
table: this.selectedTable.name
});
}
else if (this.selectedTable.type === 'view') {
res = await Views.dropView({
uid: this.selectedWorkspace,
view: this.selectedTable.name
});
}
const { status, response } = res;
if (status === 'success') {
if (this.selectedTable === this.workspace.breadcrumbs.table)
if (this.selectedTable.name === this.workspace.breadcrumbs.table)
this.changeBreadcrumbs({ table: null });
this.closeContext();

View File

@ -171,7 +171,7 @@ export default {
const params = {
uid: this.connection.uid,
schema: this.schema,
table: this.workspace.breadcrumbs.table,
table: this.workspace.breadcrumbs.table || this.workspace.breadcrumbs.view,
sortParams
};

View File

@ -68,7 +68,12 @@ module.exports = {
autoCompletion: 'Auto Completion',
application: 'Application',
editor: 'Editor',
view: 'View'
view: 'View',
definer: 'Definer',
algorithm: 'Algorithm',
trigger: 'Trigger',
storedRoutine: 'Stored routine',
scheduler: 'Scheduler'
},
message: {
appWelcome: 'Welcome to Antares SQL Client!',
@ -133,7 +138,11 @@ module.exports = {
onDelete: 'On delete',
applicationTheme: 'Application Theme',
editorTheme: 'Editor Theme',
wrapLongLines: 'Wrap long lines'
wrapLongLines: 'Wrap long lines',
selectStatement: 'Select statement',
sqlSecurity: 'SQL security',
updateOption: 'Update option',
deleteView: 'Delete view'
},
// Date and Time
short: {

View File

@ -0,0 +1,12 @@
'use strict';
import { ipcRenderer } from 'electron';
export default class {
static getViewInformations (params) {
return ipcRenderer.invoke('get-view-informations', params);
}
static dropView (params) {
return ipcRenderer.invoke('drop-view', params);
}
}

View File

@ -322,7 +322,8 @@ export default {
table: null,
trigger: null,
procedure: null,
scheduler: null
scheduler: null,
view: null
};
const hasLastChildren = Object.keys(lastBreadcrumbs).filter(b => b !== 'schema').some(b => lastBreadcrumbs[b]);