Skip to content

Commit

Permalink
perf(PostgreSQL): improved dump file
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabio286 committed Mar 27, 2022
1 parent a8ca8f2 commit 408dded
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 21 deletions.
83 changes: 64 additions & 19 deletions src/main/libs/exporters/sql/PostgreSQLExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ SET row_security = off;\n\n\n`;
.run();

for (const index of indexes)
createSql += `${index.indexdef};\n`;
createSql += `${index.indexdef.replaceAll(`${this.schemaName}.`, '')};\n`;

// Table foreigns
const { rows: foreigns } = await this._client.raw(`
Expand Down Expand Up @@ -147,8 +147,8 @@ SET row_security = off;\n\n\n`;
`);

for (const foreign of foreigns) {
createSql += `\nALTER TABLE ONLY "${tableName}"
ADD CONSTRAINT "${foreign.constraint_name}" FOREIGN KEY ("${foreign.column_name}") REFERENCES "${foreign.table_schema}"."${foreign.table_name}" ("${foreign.foreign_column_name}") ON UPDATE ${foreign.update_rule} ON DELETE ${foreign.delete_rule};\n`;
this._postTablesSql += `\nALTER TABLE ONLY "${tableName}"
ADD CONSTRAINT "${foreign.constraint_name}" FOREIGN KEY ("${foreign.column_name}") REFERENCES "${foreign.foreign_table_name}" ("${foreign.foreign_column_name}") ON UPDATE ${foreign.update_rule} ON DELETE ${foreign.delete_rule};\n`;
}

return createSql;
Expand Down Expand Up @@ -304,24 +304,79 @@ SET row_security = off;\n\n\n`;
return sqlString;
}

async getCreateAggregates () {
let sqlString = '';

const { rows: aggregates } = await this._client.raw(`
SELECT proname
FROM pg_proc
WHERE prokind = 'a'
AND pronamespace::regnamespace::text = '${this.schemaName}'
ORDER BY 1;
`);

if (aggregates.length) {
for (const aggregate of aggregates) {
const { rows: aggregateDef } = await this._client.raw(
`SELECT
format(
E'CREATE AGGREGATE %s (\n%s\n);'
, (pg_identify_object('pg_proc'::regclass, aggfnoid, 0)).identity
, array_to_string(
ARRAY[
format(E'\tSFUNC = %s', aggtransfn::regproc)
, format(E'\tSTYPE = %s', format_type(aggtranstype, NULL))
, CASE aggfinalfn WHEN '-'::regproc THEN NULL ELSE format(E'\tFINALFUNC = %s',aggfinalfn::text) END
, CASE aggsortop WHEN 0 THEN NULL ELSE format(E'\tSORTOP = %s', oprname) END
, CASE WHEN agginitval IS NULL THEN NULL ELSE format(E'\tINITCOND = %s', agginitval) END
]
, E',\n'
)
)
FROM pg_aggregate
LEFT JOIN pg_operator ON pg_operator.oid = aggsortop
WHERE aggfnoid = '${this.schemaName}.${aggregate.proname}'::regproc;`
);

if (aggregateDef.length)
sqlString += '\n\n' + aggregateDef[0].format.replaceAll(`${this.schemaName}.`, '');
}
}

return sqlString + '\n\n\n';
}

async getViews () {
const { rows: views } = await this._client.raw(`SELECT * FROM "pg_views" WHERE "schemaname"='${this.schemaName}'`);
let sqlString = '';

for (const view of views) {
sqlString += `\nDROP VIEW IF EXISTS '${view.viewname}';\n`;
sqlString += `\nDROP VIEW IF EXISTS "${view.viewname}";\n`;
sqlString += `\nCREATE VIEW "${view.viewname}" AS \n${view.definition}\n`;
}

return sqlString;
}

async getTriggers () {
let sqlString = '';

// Trigger functions
const { rows: triggerFunctions } = await this._client.raw(
`SELECT DISTINCT routine_name AS name FROM information_schema.routines WHERE routine_type = 'FUNCTION' AND routine_schema = '${this.schemaName}' AND data_type = 'trigger'`
);

for (const func of triggerFunctions) {
const { rows: functionDef } = await this._client.raw(
`SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${func.name}')) AS definition`
);
sqlString += `\n${functionDef[0].definition.replaceAll(`${this.schemaName}.`, '')};\n`;
}

const { rows: triggers } = await this._client.raw(
`SELECT * FROM "information_schema"."triggers" WHERE "trigger_schema"='${this.schemaName}'`
);

let sqlString = '';
const remappedTriggers = triggers.reduce((acc, trigger) => {
const i = acc.findIndex(t => t.trigger_name === trigger.trigger_name && t.event_object_table === trigger.event_object_table);
if (i === -1) {
Expand All @@ -337,18 +392,6 @@ SET row_security = off;\n\n\n`;
for (const trigger of remappedTriggers)
sqlString += `\nCREATE TRIGGER "${trigger.trigger_name}" ${trigger.action_timing} ${trigger.events.join(' OR ')} ON "${trigger.event_object_table}" FOR EACH ${trigger.action_orientation} ${trigger.action_statement};\n`;

// Trigger functions
const { rows: triggerFunctions } = await this._client.raw(
`SELECT DISTINCT routine_name AS name FROM information_schema.routines WHERE routine_type = 'FUNCTION' AND routine_schema = '${this.schemaName}' AND data_type = 'trigger'`
);

for (const func of triggerFunctions) {
const { rows: functionDef } = await this._client.raw(
`SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${func.name}')) AS definition`
);
sqlString += `\n${functionDef[0].definition};\n`;
}

return sqlString;
}

Expand All @@ -362,9 +405,11 @@ SET row_security = off;\n\n\n`;
const { rows: functionDef } = await this._client.raw(
`SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${func.name}')) AS definition`
);
sqlString += `\n${functionDef[0].definition};\n`;
sqlString += `\n${functionDef[0].definition.replaceAll(`${this.schemaName}.`, '')};\n`;
}

sqlString += await this.getCreateAggregates();

return sqlString;
}

Expand All @@ -378,7 +423,7 @@ SET row_security = off;\n\n\n`;
const { rows: functionDef } = await this._client.raw(
`SELECT pg_get_functiondef((SELECT oid FROM pg_proc WHERE proname = '${func.name}')) AS definition`
);
sqlString += `\n${functionDef[0].definition};\n`;
sqlString += `\n${functionDef[0].definition.replaceAll(`${this.schemaName}.`, '')};\n`;
}

return sqlString;
Expand Down
9 changes: 8 additions & 1 deletion src/main/libs/exporters/sql/SqlExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export class SqlExporter extends BaseExporter {
constructor (client, tables, options) {
super(tables, options);
this._client = client;
this._commentChar = '#';
this._commentChar = '--';
this._postTablesSql = '';
}

get schemaName () {
Expand Down Expand Up @@ -90,6 +91,12 @@ export class SqlExporter extends BaseExporter {
this.writeString('\n\n');
}

// SQL to execute after tables creation
if (this._postTablesSql) {
this.writeString(this._postTablesSql);
this.writeString('\n\n');
}

for (const item of extraItems) {
const processingMethod = `get${item.charAt(0).toUpperCase() + item.slice(1)}`;
exportState.currentItemIndex++;
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/components/ModalExportSchema.vue
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ export default {
includeDropStatement: true
}));
const structure = ['views', 'triggers', 'routines', 'functions', 'schedulers'];
const structure = ['functions', 'views', 'triggers', 'routines', 'schedulers'];
structure.forEach(feat => {
const val = customizations[this.currentWorkspace.client][feat];
Expand Down

0 comments on commit 408dded

Please sign in to comment.