From 8819abd7105facbdec7c666fe88684ca08f8f391 Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Fri, 15 Nov 2024 00:42:30 -0700 Subject: [PATCH 1/2] only create triggers when create new table --- .../db/migrations/20240818024923_cert-alerting.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/db/migrations/20240818024923_cert-alerting.ts b/backend/src/db/migrations/20240818024923_cert-alerting.ts index f60ce8c02..50848ce15 100644 --- a/backend/src/db/migrations/20240818024923_cert-alerting.ts +++ b/backend/src/db/migrations/20240818024923_cert-alerting.ts @@ -13,9 +13,9 @@ export async function up(knex: Knex): Promise { t.string("name").notNullable(); t.string("description").notNullable(); }); - } - await createOnUpdateTrigger(knex, TableName.PkiCollection); + await createOnUpdateTrigger(knex, TableName.PkiCollection); + } if (!(await knex.schema.hasTable(TableName.PkiCollectionItem))) { await knex.schema.createTable(TableName.PkiCollectionItem, (t) => { @@ -28,9 +28,9 @@ export async function up(knex: Knex): Promise { t.uuid("certId").nullable(); t.foreign("certId").references("id").inTable(TableName.Certificate).onDelete("CASCADE"); }); - } - await createOnUpdateTrigger(knex, TableName.PkiCollectionItem); + await createOnUpdateTrigger(knex, TableName.PkiCollectionItem); + } if (!(await knex.schema.hasTable(TableName.PkiAlert))) { await knex.schema.createTable(TableName.PkiAlert, (t) => { @@ -45,9 +45,9 @@ export async function up(knex: Knex): Promise { t.string("recipientEmails").notNullable(); t.unique(["name", "projectId"]); }); - } - await createOnUpdateTrigger(knex, TableName.PkiAlert); + await createOnUpdateTrigger(knex, TableName.PkiAlert); + } } export async function down(knex: Knex): Promise { From d75e49dce5aca19951873632f96b1c4b474d0b6c Mon Sep 17 00:00:00 2001 From: Maidul Islam Date: Fri, 15 Nov 2024 00:52:08 -0700 Subject: [PATCH 2/2] update trigegr to only create if it doesn't exit --- .../20240818024923_cert-alerting.ts | 12 ++++---- backend/src/db/utils.ts | 30 ++++++++++++++----- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/backend/src/db/migrations/20240818024923_cert-alerting.ts b/backend/src/db/migrations/20240818024923_cert-alerting.ts index 50848ce15..f60ce8c02 100644 --- a/backend/src/db/migrations/20240818024923_cert-alerting.ts +++ b/backend/src/db/migrations/20240818024923_cert-alerting.ts @@ -13,10 +13,10 @@ export async function up(knex: Knex): Promise { t.string("name").notNullable(); t.string("description").notNullable(); }); - - await createOnUpdateTrigger(knex, TableName.PkiCollection); } + await createOnUpdateTrigger(knex, TableName.PkiCollection); + if (!(await knex.schema.hasTable(TableName.PkiCollectionItem))) { await knex.schema.createTable(TableName.PkiCollectionItem, (t) => { t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); @@ -28,10 +28,10 @@ export async function up(knex: Knex): Promise { t.uuid("certId").nullable(); t.foreign("certId").references("id").inTable(TableName.Certificate).onDelete("CASCADE"); }); - - await createOnUpdateTrigger(knex, TableName.PkiCollectionItem); } + await createOnUpdateTrigger(knex, TableName.PkiCollectionItem); + if (!(await knex.schema.hasTable(TableName.PkiAlert))) { await knex.schema.createTable(TableName.PkiAlert, (t) => { t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); @@ -45,9 +45,9 @@ export async function up(knex: Knex): Promise { t.string("recipientEmails").notNullable(); t.unique(["name", "projectId"]); }); - - await createOnUpdateTrigger(knex, TableName.PkiAlert); } + + await createOnUpdateTrigger(knex, TableName.PkiAlert); } export async function down(knex: Knex): Promise { diff --git a/backend/src/db/utils.ts b/backend/src/db/utils.ts index 68c400596..e06cdd3f1 100644 --- a/backend/src/db/utils.ts +++ b/backend/src/db/utils.ts @@ -2,6 +2,9 @@ import { Knex } from "knex"; import { TableName } from "./schemas"; +interface PgTriggerResult { + rows: Array<{ exists: boolean }>; +} export const createJunctionTable = (knex: Knex, tableName: TableName, table1Name: TableName, table2Name: TableName) => knex.schema.createTable(tableName, (table) => { table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); @@ -28,13 +31,26 @@ DROP FUNCTION IF EXISTS on_update_timestamp() CASCADE; // we would be using this to apply updatedAt where ever we wanta // remember to set `timestamps(true,true,true)` before this on schema -export const createOnUpdateTrigger = (knex: Knex, tableName: string) => - knex.raw(` -CREATE TRIGGER "${tableName}_updatedAt" -BEFORE UPDATE ON ${tableName} -FOR EACH ROW -EXECUTE PROCEDURE on_update_timestamp(); -`); +export const createOnUpdateTrigger = async (knex: Knex, tableName: string) => { + const triggerExists = await knex.raw(` + SELECT EXISTS ( + SELECT 1 + FROM pg_trigger + WHERE tgname = '${tableName}_updatedAt' + ); + `); + + if (!triggerExists?.rows?.[0]?.exists) { + return knex.raw(` + CREATE TRIGGER "${tableName}_updatedAt" + BEFORE UPDATE ON ${tableName} + FOR EACH ROW + EXECUTE PROCEDURE on_update_timestamp(); + `); + } + + return null; +}; export const dropOnUpdateTrigger = (knex: Knex, tableName: string) => knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`);