mirror of https://github.com/Fabio286/antares.git
feat(PostgreSQL): procedures management
This commit is contained in:
parent
d0b3e1b1b8
commit
3dde1c109e
|
@ -51,5 +51,6 @@ module.exports = {
|
||||||
viewUpdateOption: false,
|
viewUpdateOption: false,
|
||||||
procedureDeterministic: false,
|
procedureDeterministic: false,
|
||||||
procedureDataAccess: false,
|
procedureDataAccess: false,
|
||||||
procedureSql: false
|
procedureSql: false,
|
||||||
|
parametersLength: false
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,5 +46,9 @@ module.exports = {
|
||||||
onUpdate: true,
|
onUpdate: true,
|
||||||
viewAlgorithm: true,
|
viewAlgorithm: true,
|
||||||
viewSqlSecurity: true,
|
viewSqlSecurity: true,
|
||||||
viewUpdateOption: true
|
viewUpdateOption: true,
|
||||||
|
procedureDeterministic: true,
|
||||||
|
procedureDataAccess: true,
|
||||||
|
procedureSql: 'BEGIN\r\n\r\nEND',
|
||||||
|
parametersLength: true
|
||||||
};
|
};
|
||||||
|
|
|
@ -556,7 +556,7 @@ export class PostgreSQLClient extends AntaresCore {
|
||||||
const sql = `SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${routine}'));`;
|
const sql = `SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${routine}'));`;
|
||||||
const results = await this.raw(sql);
|
const results = await this.raw(sql);
|
||||||
|
|
||||||
return results.rows.map(row => {
|
return results.rows.map(async row => {
|
||||||
if (!row.pg_get_functiondef) {
|
if (!row.pg_get_functiondef) {
|
||||||
return {
|
return {
|
||||||
definer: null,
|
definer: null,
|
||||||
|
@ -570,30 +570,37 @@ export class PostgreSQLClient extends AntaresCore {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const parameters = row.pg_get_functiondef
|
const sql = `SELECT proc.specific_schema AS procedure_schema,
|
||||||
.match(/(\([^()]*(?:(?:\([^()]*\))[^()]*)*\)\s*)/s)[0]
|
proc.specific_name,
|
||||||
.replaceAll('\r', '')
|
proc.routine_name AS procedure_name,
|
||||||
.replaceAll('\t', '')
|
proc.external_language,
|
||||||
.slice(1, -1)
|
args.parameter_name,
|
||||||
.split(',')
|
args.parameter_mode,
|
||||||
.map(el => {
|
args.data_type
|
||||||
const param = el.split(' ');
|
FROM information_schema.routines proc
|
||||||
const type = param[2] ? param[2].replace(')', '').split('(') : ['', null];
|
LEFT JOIN information_schema.parameters args
|
||||||
return {
|
ON proc.specific_schema = args.specific_schema
|
||||||
name: param[1] ? param[1].replaceAll('`', '') : '',
|
AND proc.specific_name = args.specific_name
|
||||||
type: type[0].replaceAll('\n', ''),
|
WHERE proc.routine_schema not in ('pg_catalog', 'information_schema')
|
||||||
length: +type[1] ? +type[1].replace(/\D/g, '') : '',
|
AND proc.routine_type = 'PROCEDURE'
|
||||||
context: param[0] ? param[0].replace('\n', '') : ''
|
AND proc.routine_name = '${routine}'
|
||||||
};
|
AND proc.specific_schema = '${schema}'
|
||||||
}).filter(el => el.name);
|
ORDER BY procedure_schema,
|
||||||
|
specific_name,
|
||||||
|
procedure_name,
|
||||||
|
args.ordinal_position
|
||||||
|
`;
|
||||||
|
|
||||||
let dataAccess = 'CONTAINS SQL';
|
const results = await this.raw(sql);
|
||||||
if (row.pg_get_functiondef.includes('NO SQL'))
|
|
||||||
dataAccess = 'NO SQL';
|
const parameters = results.rows.map(row => {
|
||||||
if (row.pg_get_functiondef.includes('READS SQL DATA'))
|
return {
|
||||||
dataAccess = 'READS SQL DATA';
|
name: row.parameter_name,
|
||||||
if (row.pg_get_functiondef.includes('MODIFIES SQL DATA'))
|
type: row.data_type.toUpperCase(),
|
||||||
dataAccess = 'MODIFIES SQL DATA';
|
length: '',
|
||||||
|
context: row.parameter_mode
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
definer: '',
|
definer: '',
|
||||||
|
@ -601,9 +608,9 @@ export class PostgreSQLClient extends AntaresCore {
|
||||||
parameters: parameters || [],
|
parameters: parameters || [],
|
||||||
name: routine,
|
name: routine,
|
||||||
comment: '',
|
comment: '',
|
||||||
security: row.pg_get_functiondef.includes('SECURITY INVOKER') ? 'INVOKER' : 'DEFINER',
|
security: row.pg_get_functiondef.includes('SECURITY DEFINER') ? 'DEFINER' : 'INVOKER',
|
||||||
deterministic: null,
|
deterministic: null,
|
||||||
dataAccess,
|
dataAccess: null,
|
||||||
language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0]
|
language: row.pg_get_functiondef.match(/(?<=LANGUAGE )(.*)(?<=[\S+\n\r\s])/gm)[0]
|
||||||
};
|
};
|
||||||
})[0];
|
})[0];
|
||||||
|
@ -656,6 +663,9 @@ export class PostgreSQLClient extends AntaresCore {
|
||||||
}, []).join(',')
|
}, []).join(',')
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
if (this._schema !== 'public')
|
||||||
|
this.use(this._schema);
|
||||||
|
|
||||||
const sql = `CREATE PROCEDURE ${this._schema}.${routine.name}(${parameters})
|
const sql = `CREATE PROCEDURE ${this._schema}.${routine.name}(${parameters})
|
||||||
LANGUAGE SQL
|
LANGUAGE SQL
|
||||||
SECURITY ${routine.security}
|
SECURITY ${routine.security}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { NUMBER, FLOAT } from 'common/fieldTypes';
|
||||||
import ConfirmModal from '@/components/BaseConfirmModal';
|
import ConfirmModal from '@/components/BaseConfirmModal';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -57,7 +58,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
localRoutine: Object
|
localRoutine: Object,
|
||||||
|
client: String
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -82,7 +84,22 @@ export default {
|
||||||
},
|
},
|
||||||
runRoutine () {
|
runRoutine () {
|
||||||
const valArr = Object.keys(this.values).reduce((acc, curr) => {
|
const valArr = Object.keys(this.values).reduce((acc, curr) => {
|
||||||
const value = isNaN(this.values[curr]) ? `"${this.values[curr]}"` : this.values[curr];
|
let qc;
|
||||||
|
switch (this.client) {
|
||||||
|
case 'maria':
|
||||||
|
case 'mysql':
|
||||||
|
qc = '"';
|
||||||
|
break;
|
||||||
|
case 'pg':
|
||||||
|
qc = '\'';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qc = '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
const param = this.localRoutine.parameters.find(param => param.name === curr);
|
||||||
|
|
||||||
|
const value = [...NUMBER, ...FLOAT].includes(param.type) ? this.values[curr] : `${qc}${this.values[curr]}${qc}`;
|
||||||
acc.push(value);
|
acc.push(value);
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.definer" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('word.definer') }}
|
{{ $t('word.definer') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.comment" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('word.comment') }}
|
{{ $t('word.comment') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.comment" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('message.dataAccess') }}
|
{{ $t('message.dataAccess') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.procedureDeterministic" class="form-group">
|
||||||
<div class="col-4" />
|
<div class="col-4" />
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<label class="form-checkbox form-inline">
|
<label class="form-checkbox form-inline">
|
||||||
|
@ -117,7 +117,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
localRoutine: {
|
localRoutine: {
|
||||||
definer: '',
|
definer: '',
|
||||||
sql: 'BEGIN\r\n\r\nEND',
|
sql: '',
|
||||||
parameters: [],
|
parameters: [],
|
||||||
name: '',
|
name: '',
|
||||||
comment: '',
|
comment: '',
|
||||||
|
@ -131,9 +131,14 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
schema () {
|
schema () {
|
||||||
return this.workspace.breadcrumbs.schema;
|
return this.workspace.breadcrumbs.schema;
|
||||||
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.workspace.customizations;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
if (this.customizations.procedureSql)
|
||||||
|
this.localRoutine.sql = this.customizations.procedureSql;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.firstInput.focus();
|
this.$refs.firstInput.focus();
|
||||||
}, 20);
|
}, 20);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<ModalAskParameters
|
<ModalAskParameters
|
||||||
v-if="isAskingParameters"
|
v-if="isAskingParameters"
|
||||||
:local-routine="localElement"
|
:local-routine="localElement"
|
||||||
|
:client="workspace.client"
|
||||||
@confirm="runElement"
|
@confirm="runElement"
|
||||||
@close="hideAskParamsModal"
|
@close="hideAskParamsModal"
|
||||||
/>
|
/>
|
||||||
|
@ -205,13 +206,13 @@ export default {
|
||||||
case 'maria':
|
case 'maria':
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
case 'pg':
|
case 'pg':
|
||||||
sql = `CALL \`${this.localElement.name}\` (${params.join(',')})`;
|
sql = `CALL ${this.localElement.name}(${params.join(',')})`;
|
||||||
break;
|
break;
|
||||||
case 'mssql':
|
case 'mssql':
|
||||||
sql = `EXEC ${this.localElement.name} ${params.join(',')}`;
|
sql = `EXEC ${this.localElement.name} ${params.join(',')}`;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sql = `CALL \`${this.localElement.name}\` (${params.join(',')})`;
|
sql = `CALL \`${this.localElement.name}\`(${params.join(',')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newTab({ uid: this.workspace.uid, content: sql, autorun: true });
|
this.newTab({ uid: this.workspace.uid, content: sql, autorun: true });
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.definer" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('word.definer') }}
|
{{ $t('word.definer') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.comment" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('word.comment') }}
|
{{ $t('word.comment') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.procedureDataAccess" class="form-group">
|
||||||
<label class="form-label col-4">
|
<label class="form-label col-4">
|
||||||
{{ $t('message.dataAccess') }}
|
{{ $t('message.dataAccess') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.procedureDeterministic" class="form-group">
|
||||||
<div class="col-4" />
|
<div class="col-4" />
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<label class="form-checkbox form-inline">
|
<label class="form-checkbox form-inline">
|
||||||
|
@ -124,6 +124,9 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
isTableNameValid () {
|
isTableNameValid () {
|
||||||
return this.optionsProxy.name !== '';
|
return this.optionsProxy.name !== '';
|
||||||
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.workspace.customizations;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div v-if="customizations.parametersLength" class="form-group">
|
||||||
<label class="form-label col-3">
|
<label class="form-label col-3">
|
||||||
{{ $t('word.length') }}
|
{{ $t('word.length') }}
|
||||||
</label>
|
</label>
|
||||||
|
@ -199,6 +199,9 @@ export default {
|
||||||
},
|
},
|
||||||
isChanged () {
|
isChanged () {
|
||||||
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
return JSON.stringify(this.localParameters) !== JSON.stringify(this.parametersProxy);
|
||||||
|
},
|
||||||
|
customizations () {
|
||||||
|
return this.workspace.customizations;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
@ -235,10 +238,10 @@ export default {
|
||||||
addParameter () {
|
addParameter () {
|
||||||
this.parametersProxy = [...this.parametersProxy, {
|
this.parametersProxy = [...this.parametersProxy, {
|
||||||
_id: uidGen(),
|
_id: uidGen(),
|
||||||
name: `Param${this.i++}`,
|
name: `param${this.i++}`,
|
||||||
type: 'INT',
|
type: this.workspace.dataTypes[0].types[0].name,
|
||||||
context: 'IN',
|
context: 'IN',
|
||||||
length: 10
|
length: ''
|
||||||
}];
|
}];
|
||||||
|
|
||||||
if (this.parametersProxy.length === 1)
|
if (this.parametersProxy.length === 1)
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
<ModalAskParameters
|
<ModalAskParameters
|
||||||
v-if="isAskingParameters"
|
v-if="isAskingParameters"
|
||||||
:local-routine="localFunction"
|
:local-routine="localFunction"
|
||||||
|
:client="workspace.client"
|
||||||
@confirm="runFunction"
|
@confirm="runFunction"
|
||||||
@close="hideAskParamsModal"
|
@close="hideAskParamsModal"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
<ModalAskParameters
|
<ModalAskParameters
|
||||||
v-if="isAskingParameters"
|
v-if="isAskingParameters"
|
||||||
:local-routine="localRoutine"
|
:local-routine="localRoutine"
|
||||||
|
:client="workspace.client"
|
||||||
@confirm="runRoutine"
|
@confirm="runRoutine"
|
||||||
@close="hideAskParamsModal"
|
@close="hideAskParamsModal"
|
||||||
/>
|
/>
|
||||||
|
@ -281,13 +282,13 @@ export default {
|
||||||
case 'maria':
|
case 'maria':
|
||||||
case 'mysql':
|
case 'mysql':
|
||||||
case 'pg':
|
case 'pg':
|
||||||
sql = `CALL \`${this.originalRoutine.name}\` (${params.join(',')})`;
|
sql = `CALL ${this.originalRoutine.name}(${params.join(',')})`;
|
||||||
break;
|
break;
|
||||||
case 'mssql':
|
case 'mssql':
|
||||||
sql = `EXEC ${this.originalRoutine.name} ${params.join(',')}`;
|
sql = `EXEC ${this.originalRoutine.name} ${params.join(',')}`;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sql = `CALL \`${this.originalRoutine.name}\` (${params.join(',')})`;
|
sql = `CALL \`${this.originalRoutine.name}\`(${params.join(',')})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
|
this.newTab({ uid: this.connection.uid, content: sql, autorun: true });
|
||||||
|
|
Loading…
Reference in New Issue