1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-06-05 21:59:22 +02:00

feat(PostgreSQL): views management

This commit is contained in:
2021-03-31 16:54:06 +02:00
parent fe4c8e12b3
commit 99f7511c4d
6 changed files with 89 additions and 80 deletions

View File

@ -43,6 +43,10 @@ module.exports = {
autoIncrement: false, autoIncrement: false,
comment: false, comment: false,
collation: false, collation: false,
definer: false,
arrays: false, arrays: false,
onUpdate: false onUpdate: false,
viewAlgorithm: false,
viewSqlSecurity: false,
viewUpdateOption: false
}; };

View File

@ -42,5 +42,9 @@ module.exports = {
autoIncrement: true, autoIncrement: true,
comment: true, comment: true,
collation: true, collation: true,
onUpdate: true definer: true,
onUpdate: true,
viewAlgorithm: true,
viewSqlSecurity: true,
viewUpdateOption: true
}; };

View File

@ -12,16 +12,17 @@ module.exports = {
processesList: true, processesList: true,
// Structure // Structure
tables: true, tables: true,
views: false, views: true,
triggers: false, triggers: false,
routines: false, routines: false,
functions: false, functions: false,
schedulers: false, schedulers: false,
// Settings // Settings
tableAdd: true, tableAdd: true,
viewAdd: true,
databaseEdit: false, databaseEdit: false,
tableSettings: true, tableSettings: true,
viewSettings: false, viewSettings: true,
triggerSettings: false, triggerSettings: false,
routineSettings: false, routineSettings: false,
functionSettings: false, functionSettings: false,

View File

@ -454,17 +454,17 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async getViewInformations ({ schema, view }) { async getViewInformations ({ schema, view }) {
const sql = `SHOW CREATE VIEW \`${schema}\`.\`${view}\``; const sql = `SELECT "definition" FROM "pg_views" WHERE "viewname"='${view}' AND "schemaname"='${schema}'`;
const results = await this.raw(sql); const results = await this.raw(sql);
return results.rows.map(row => { return results.rows.map(row => {
return { return {
algorithm: row['Create View'].match(/(?<=CREATE ALGORITHM=).*?(?=\s)/gs)[0], algorithm: '',
definer: row['Create View'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0], definer: '',
security: row['Create View'].match(/(?<=SQL SECURITY ).*?(?=\s)/gs)[0], security: '',
updateOption: row['Create View'].match(/(?<=WITH ).*?(?=\s)/gs) ? row['Create View'].match(/(?<=WITH ).*?(?=\s)/gs)[0] : '', updateOption: '',
sql: row['Create View'].match(/(?<=AS ).*?$/gs)[0], sql: row.definition,
name: row.View name: view
}; };
})[0]; })[0];
} }
@ -476,7 +476,7 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async dropView (params) { async dropView (params) {
const sql = `DROP VIEW \`${params.view}\``; const sql = `DROP VIEW ${params.view}`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -488,10 +488,10 @@ export class PostgreSQLClient extends AntaresCore {
*/ */
async alterView (params) { async alterView (params) {
const { view } = params; const { view } = params;
let sql = `ALTER ALGORITHM = ${view.algorithm}${view.definer ? ` DEFINER=${view.definer}` : ''} SQL SECURITY ${view.security} VIEW \`${view.oldName}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`; let sql = `CREATE OR REPLACE VIEW ${view.oldName} AS ${view.sql}`;
if (view.name !== view.oldName) if (view.name !== view.oldName)
sql += `; RENAME TABLE \`${view.oldName}\` TO \`${view.name}\``; sql += `; ALTER VIEW ${view.oldName} RENAME TO ${view.name}`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -503,7 +503,7 @@ export class PostgreSQLClient extends AntaresCore {
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async createView (view) { async createView (view) {
const sql = `CREATE ALGORITHM = ${view.algorithm} ${view.definer ? `DEFINER=${view.definer} ` : ''}SQL SECURITY ${view.security} VIEW \`${view.name}\` AS ${view.sql} ${view.updateOption ? `WITH ${view.updateOption} CHECK OPTION` : ''}`; const sql = `CREATE VIEW ${view.name} AS ${view.sql}`;
return await this.raw(sql); return await this.raw(sql);
} }
@ -823,33 +823,33 @@ export class PostgreSQLClient extends AntaresCore {
* @returns {Array.<Object>} view informations * @returns {Array.<Object>} view informations
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async getEventInformations ({ schema, scheduler }) { // async getEventInformations ({ schema, scheduler }) {
const sql = `SHOW CREATE EVENT \`${schema}\`.\`${scheduler}\``; // const sql = `SHOW CREATE EVENT \`${schema}\`.\`${scheduler}\``;
const results = await this.raw(sql); // const results = await this.raw(sql);
return results.rows.map(row => { // return results.rows.map(row => {
const schedule = row['Create Event']; // const schedule = row['Create Event'];
const execution = schedule.includes('EVERY') ? 'EVERY' : 'ONCE'; // const execution = schedule.includes('EVERY') ? 'EVERY' : 'ONCE';
const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*([^\s]+)){0,2}/gs)[0].replaceAll('\'', '').split(' ') : []; // const every = execution === 'EVERY' ? row['Create Event'].match(/(?<=EVERY )(\s*([^\s]+)){0,2}/gs)[0].replaceAll('\'', '').split(' ') : [];
const starts = execution === 'EVERY' && schedule.includes('STARTS') ? schedule.match(/(?<=STARTS ').*?(?='\s)/gs)[0] : ''; // const starts = execution === 'EVERY' && schedule.includes('STARTS') ? schedule.match(/(?<=STARTS ').*?(?='\s)/gs)[0] : '';
const ends = execution === 'EVERY' && schedule.includes('ENDS') ? schedule.match(/(?<=ENDS ').*?(?='\s)/gs)[0] : ''; // const ends = execution === 'EVERY' && schedule.includes('ENDS') ? schedule.match(/(?<=ENDS ').*?(?='\s)/gs)[0] : '';
const at = execution === 'ONCE' && schedule.includes('AT') ? schedule.match(/(?<=AT ').*?(?='\s)/gs)[0] : ''; // const at = execution === 'ONCE' && schedule.includes('AT') ? schedule.match(/(?<=AT ').*?(?='\s)/gs)[0] : '';
return { // return {
definer: row['Create Event'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0], // definer: row['Create Event'].match(/(?<=DEFINER=).*?(?=\s)/gs)[0],
sql: row['Create Event'].match(/(?<=DO )(.*)/gs)[0], // sql: row['Create Event'].match(/(?<=DO )(.*)/gs)[0],
name: row.Event, // name: row.Event,
comment: row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '', // comment: row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs) ? row['Create Event'].match(/(?<=COMMENT ').*?(?=')/gs)[0] : '',
state: row['Create Event'].includes('ENABLE') ? 'ENABLE' : row['Create Event'].includes('DISABLE ON SLAVE') ? 'DISABLE ON SLAVE' : 'DISABLE', // state: row['Create Event'].includes('ENABLE') ? 'ENABLE' : row['Create Event'].includes('DISABLE ON SLAVE') ? 'DISABLE ON SLAVE' : 'DISABLE',
preserve: row['Create Event'].includes('ON COMPLETION PRESERVE'), // preserve: row['Create Event'].includes('ON COMPLETION PRESERVE'),
execution, // execution,
every, // every,
starts, // starts,
ends, // ends,
at // at
}; // };
})[0]; // })[0];
} // }
/** /**
* DROP EVENT * DROP EVENT
@ -857,10 +857,10 @@ export class PostgreSQLClient extends AntaresCore {
* @returns {Array.<Object>} parameters * @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async dropEvent (params) { // async dropEvent (params) {
const sql = `DROP EVENT \`${params.scheduler}\``; // const sql = `DROP EVENT \`${params.scheduler}\``;
return await this.raw(sql); // return await this.raw(sql);
} // }
/** /**
* ALTER EVENT * ALTER EVENT
@ -868,25 +868,25 @@ export class PostgreSQLClient extends AntaresCore {
* @returns {Array.<Object>} parameters * @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async alterEvent (params) { // async alterEvent (params) {
const { scheduler } = params; // const { scheduler } = params;
if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-')) // if (scheduler.execution === 'EVERY' && scheduler.every[0].includes('-'))
scheduler.every[0] = `'${scheduler.every[0]}'`; // scheduler.every[0] = `'${scheduler.every[0]}'`;
const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.oldName}\` // const sql = `ALTER ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.oldName}\`
ON SCHEDULE // ON SCHEDULE
${scheduler.execution === 'EVERY' // ${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}` // ? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
: `AT '${scheduler.at}'`} // : `AT '${scheduler.at}'`}
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE // ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.name}\`` : ''} // ${scheduler.name !== scheduler.oldName ? `RENAME TO \`${scheduler.name}\`` : ''}
${scheduler.state} // ${scheduler.state}
COMMENT '${scheduler.comment}' // COMMENT '${scheduler.comment}'
DO ${scheduler.sql}`; // DO ${scheduler.sql}`;
return await this.raw(sql, { split: false }); // return await this.raw(sql, { split: false });
} // }
/** /**
* CREATE EVENT * CREATE EVENT
@ -894,19 +894,19 @@ export class PostgreSQLClient extends AntaresCore {
* @returns {Array.<Object>} parameters * @returns {Array.<Object>} parameters
* @memberof PostgreSQLClient * @memberof PostgreSQLClient
*/ */
async createEvent (scheduler) { // async createEvent (scheduler) {
const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.name}\` // const sql = `CREATE ${scheduler.definer ? ` DEFINER=${scheduler.definer}` : ''} EVENT \`${scheduler.name}\`
ON SCHEDULE // ON SCHEDULE
${scheduler.execution === 'EVERY' // ${scheduler.execution === 'EVERY'
? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}` // ? `EVERY ${scheduler.every.join(' ')}${scheduler.starts ? ` STARTS '${scheduler.starts}'` : ''}${scheduler.ends ? ` ENDS '${scheduler.ends}'` : ''}`
: `AT '${scheduler.at}'`} // : `AT '${scheduler.at}'`}
ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE // ON COMPLETION${!scheduler.preserve ? ' NOT' : ''} PRESERVE
${scheduler.state} // ${scheduler.state}
COMMENT '${scheduler.comment}' // COMMENT '${scheduler.comment}'
DO ${scheduler.sql}`; // DO ${scheduler.sql}`;
return await this.raw(sql, { split: false }); // return await this.raw(sql, { split: false });
} // }
/** /**
* SELECT * FROM pg_collation * SELECT * FROM pg_collation

View File

@ -25,7 +25,7 @@
</div> </div>
</div> </div>
<div class="column col-6"> <div class="column col-6">
<div class="form-group"> <div v-if="workspace.customizations.definer" class="form-group">
<label class="form-label">{{ $t('word.definer') }}</label> <label class="form-label">{{ $t('word.definer') }}</label>
<select v-model="localView.definer" class="form-select"> <select v-model="localView.definer" class="form-select">
<option value=""> <option value="">
@ -44,7 +44,7 @@
</div> </div>
<div class="columns"> <div class="columns">
<div class="column col-4"> <div class="column col-4">
<div class="form-group"> <div v-if="workspace.customizations.viewSqlSecurity" class="form-group">
<label class="form-label">{{ $t('message.sqlSecurity') }}</label> <label class="form-label">{{ $t('message.sqlSecurity') }}</label>
<label class="form-radio"> <label class="form-radio">
<input <input
@ -67,7 +67,7 @@
</div> </div>
</div> </div>
<div class="column col-4"> <div class="column col-4">
<div class="form-group"> <div v-if="workspace.customizations.viewAlgorithm" class="form-group">
<label class="form-label">{{ $t('word.algorithm') }}</label> <label class="form-label">{{ $t('word.algorithm') }}</label>
<label class="form-radio"> <label class="form-radio">
<input <input
@ -99,7 +99,7 @@
</div> </div>
</div> </div>
<div class="column col-4"> <div class="column col-4">
<div class="form-group"> <div v-if="workspace.customizations.viewUpdateOption" class="form-group">
<label class="form-label">{{ $t('message.updateOption') }}</label> <label class="form-label">{{ $t('message.updateOption') }}</label>
<label class="form-radio"> <label class="form-radio">
<input <input

View File

@ -37,7 +37,7 @@
</div> </div>
</div> </div>
<div class="column col-auto"> <div class="column col-auto">
<div class="form-group"> <div v-if="workspace.customizations.definer" class="form-group">
<label class="form-label">{{ $t('word.definer') }}</label> <label class="form-label">{{ $t('word.definer') }}</label>
<select <select
v-if="workspace.users.length" v-if="workspace.users.length"
@ -68,7 +68,7 @@
</div> </div>
<div class="columns"> <div class="columns">
<div class="column col-auto mr-2"> <div class="column col-auto mr-2">
<div class="form-group"> <div v-if="workspace.customizations.viewSqlSecurity" class="form-group">
<label class="form-label">{{ $t('message.sqlSecurity') }}</label> <label class="form-label">{{ $t('message.sqlSecurity') }}</label>
<label class="form-radio"> <label class="form-radio">
<input <input
@ -91,7 +91,7 @@
</div> </div>
</div> </div>
<div class="column col-auto mr-2"> <div class="column col-auto mr-2">
<div class="form-group"> <div v-if="workspace.customizations.viewAlgorithm" class="form-group">
<label class="form-label">{{ $t('word.algorithm') }}</label> <label class="form-label">{{ $t('word.algorithm') }}</label>
<label class="form-radio"> <label class="form-radio">
<input <input
@ -122,7 +122,7 @@
</label> </label>
</div> </div>
</div> </div>
<div class="column col-auto mr-2"> <div v-if="workspace.customizations.viewUpdateOption" class="column col-auto mr-2">
<div class="form-group"> <div class="form-group">
<label class="form-label">{{ $t('message.updateOption') }}</label> <label class="form-label">{{ $t('message.updateOption') }}</label>
<label class="form-radio"> <label class="form-radio">