diff --git a/backend/src/db/utils.ts b/backend/src/db/utils.ts index 68c4005963..ee66e88565 100644 --- a/backend/src/db/utils.ts +++ b/backend/src/db/utils.ts @@ -1,40 +1,82 @@ import { Knex } from "knex"; - import { TableName } from "./schemas"; -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()); - table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1 - table.uuid(`${table2Name}Id`).unsigned().notNullable(); // Foreign key for table2 - table.foreign(`${table1Name}Id`).references("id").inTable(table1Name).onDelete("CASCADE"); - table.foreign(`${table2Name}Id`).references("id").inTable(table2Name).onDelete("CASCADE"); - }); +interface JunctionTableOptions { + table1PrimaryKey?: string; + table2PrimaryKey?: string; + indexForeignKeys?: boolean; +} + +export const createJunctionTable = async ( + knex: Knex, + tableName: TableName, + table1Name: TableName, + table2Name: TableName, + options: JunctionTableOptions = {} +): Promise => { + const { + table1PrimaryKey = 'id', + table2PrimaryKey = 'id', + indexForeignKeys = false + } = options; + + // Check if the table already exists + const tableExists = await knex.schema.hasTable(tableName); + + if (!tableExists) { + await knex.schema.createTable(tableName, (table) => { + table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid()); + + // Create foreign key columns + table.uuid(`${table1Name}Id`).unsigned().notNullable(); + table.uuid(`${table2Name}Id`).unsigned().notNullable(); + + // Set up foreign key constraints + table.foreign(`${table1Name}Id`) + .references(table1PrimaryKey) + .inTable(table1Name) + .onDelete("CASCADE"); + + table.foreign(`${table2Name}Id`) + .references(table2PrimaryKey) + .inTable(table2Name) + .onDelete("CASCADE"); + + // Add indexes on foreign key columns if specified + if (indexForeignKeys) { + table.index(`${table1Name}Id`); + table.index(`${table2Name}Id`); + } + }); + } +}; // one time logic // this is a postgres function log to set updateAt to present time whenever row gets updated -export const createUpdateAtTriggerFunction = (knex: Knex) => - knex.raw(` -CREATE OR REPLACE FUNCTION on_update_timestamp() RETURNS TRIGGER AS $$ BEGIN NEW."updatedAt" = NOW(); -RETURN NEW; -END; -$$ LANGUAGE plpgsql; -`); +export const createUpdateAtTriggerFunction = async (knex: Knex): Promise => { + await knex.raw(` + CREATE OR REPLACE FUNCTION on_update_timestamp() RETURNS TRIGGER AS $$ BEGIN NEW."updatedAt" = NOW(); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + `); +}; -export const dropUpdatedAtTriggerFunction = (knex: Knex) => - knex.raw(` -DROP FUNCTION IF EXISTS on_update_timestamp() CASCADE; -`); +export const dropUpdatedAtTriggerFunction = async (knex: Knex): Promise => { + await knex.raw(` + 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): Promise => { + await knex.raw(` + CREATE TRIGGER "${tableName}_updatedAt" + BEFORE UPDATE ON ${tableName} + FOR EACH ROW + EXECUTE PROCEDURE on_update_timestamp(); + `); +}; -export const dropOnUpdateTrigger = (knex: Knex, tableName: string) => - knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`); +export const dropOnUpdateTrigger = async (knex: Knex, tableName: string): Promise => { + await knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`); +};