From db6cb6cf7d1efc64b61d541470f212f602a5fa77 Mon Sep 17 00:00:00 2001 From: Raj Nandan Sharma Date: Sat, 28 Mar 2026 11:07:13 +0530 Subject: [PATCH] refactor: improve SQLite migration for monitor_alerts_config to ensure monitor_tag is nullable --- .../20260325120000_multi_monitor_alerts.ts | 85 ++++++++++--------- ...x_sqlite_monitor_alerts_config_nullable.ts | 18 ++-- 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/migrations/20260325120000_multi_monitor_alerts.ts b/migrations/20260325120000_multi_monitor_alerts.ts index c9b89994..0def4768 100644 --- a/migrations/20260325120000_multi_monitor_alerts.ts +++ b/migrations/20260325120000_multi_monitor_alerts.ts @@ -98,47 +98,50 @@ export async function up(knex: Knex): Promise { if (dbClient === "sqlite3" || dbClient === "better-sqlite3") { // SQLite cannot ALTER COLUMN, so we rebuild the table with monitor_tag nullable - await knex.raw("PRAGMA foreign_keys = OFF"); - await knex.raw(` - CREATE TABLE monitor_alerts_config_new ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - monitor_tag VARCHAR(255), - alert_for VARCHAR(50) NOT NULL, - alert_value VARCHAR(255) NOT NULL, - failure_threshold INTEGER NOT NULL DEFAULT 1, - success_threshold INTEGER NOT NULL DEFAULT 1, - alert_description TEXT, - create_incident VARCHAR(10) NOT NULL DEFAULT 'NO', - is_active VARCHAR(10) NOT NULL DEFAULT 'YES', - severity VARCHAR(50) NOT NULL DEFAULT 'WARNING', - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP - ) - `); - await knex.raw(` - INSERT INTO monitor_alerts_config_new - (id, monitor_tag, alert_for, alert_value, failure_threshold, - success_threshold, alert_description, create_incident, - is_active, severity, created_at, updated_at) - SELECT - id, NULL, alert_for, alert_value, failure_threshold, - success_threshold, alert_description, create_incident, - is_active, severity, created_at, updated_at - FROM monitor_alerts_config - `); - await knex.raw("DROP TABLE monitor_alerts_config"); - await knex.raw("ALTER TABLE monitor_alerts_config_new RENAME TO monitor_alerts_config"); - try { - await knex.raw("CREATE INDEX idx_monitor_alerts_config_monitor_tag ON monitor_alerts_config (monitor_tag)"); - } catch (_e) { - /* index may already exist */ - } - try { - await knex.raw("CREATE INDEX idx_monitor_alerts_config_is_active ON monitor_alerts_config (is_active)"); - } catch (_e) { - /* index may already exist */ - } - await knex.raw("PRAGMA foreign_keys = ON"); + await knex.transaction(async (trx) => { + await trx.raw("PRAGMA foreign_keys = OFF"); + await trx.raw("DROP TABLE IF EXISTS monitor_alerts_config_new"); + await trx.raw(` + CREATE TABLE monitor_alerts_config_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + monitor_tag VARCHAR(255), + alert_for VARCHAR(50) NOT NULL, + alert_value VARCHAR(255) NOT NULL, + failure_threshold INTEGER NOT NULL DEFAULT 1, + success_threshold INTEGER NOT NULL DEFAULT 1, + alert_description TEXT, + create_incident VARCHAR(10) NOT NULL DEFAULT 'NO', + is_active VARCHAR(10) NOT NULL DEFAULT 'YES', + severity VARCHAR(50) NOT NULL DEFAULT 'WARNING', + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) + `); + await trx.raw(` + INSERT INTO monitor_alerts_config_new + (id, monitor_tag, alert_for, alert_value, failure_threshold, + success_threshold, alert_description, create_incident, + is_active, severity, created_at, updated_at) + SELECT + id, NULL, alert_for, alert_value, failure_threshold, + success_threshold, alert_description, create_incident, + is_active, severity, created_at, updated_at + FROM monitor_alerts_config + `); + await trx.raw("DROP TABLE monitor_alerts_config"); + await trx.raw("ALTER TABLE monitor_alerts_config_new RENAME TO monitor_alerts_config"); + try { + await trx.raw("CREATE INDEX idx_monitor_alerts_config_monitor_tag ON monitor_alerts_config (monitor_tag)"); + } catch (_e) { + /* index may already exist */ + } + try { + await trx.raw("CREATE INDEX idx_monitor_alerts_config_is_active ON monitor_alerts_config (is_active)"); + } catch (_e) { + /* index may already exist */ + } + await trx.raw("PRAGMA foreign_keys = ON"); + }); } else { try { await knex.schema.alterTable("monitor_alerts_config", (table) => { diff --git a/migrations/20260328120000_fix_sqlite_monitor_alerts_config_nullable.ts b/migrations/20260328120000_fix_sqlite_monitor_alerts_config_nullable.ts index d48b20eb..a2ac2d9a 100644 --- a/migrations/20260328120000_fix_sqlite_monitor_alerts_config_nullable.ts +++ b/migrations/20260328120000_fix_sqlite_monitor_alerts_config_nullable.ts @@ -4,8 +4,7 @@ * The earlier migration 20260325120000_multi_monitor_alerts nulled out data in * monitor_alerts_config.monitor_tag for SQLite but could not alter the column * constraint (SQLite doesn't support ALTER COLUMN). This migration recreates - * the table with monitor_tag as nullable, preserving all data, indexes, and - * foreign keys. + * the table with monitor_tag as nullable, preserving all data and indexes. * * Only runs on SQLite/better-sqlite3; other databases already had the column * altered in the previous migration. @@ -28,10 +27,10 @@ export async function up(knex: Knex): Promise { } // Column is still NOT NULL — rebuild the table to make it nullable - await knex.raw("PRAGMA foreign_keys = OFF"); - try { await knex.transaction(async (trx) => { + await trx.raw("PRAGMA foreign_keys = OFF"); + await trx.raw("DROP TABLE IF EXISTS monitor_alerts_config_new"); await trx.raw(` CREATE TABLE monitor_alerts_config_new ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -74,9 +73,11 @@ export async function up(knex: Knex): Promise { } catch (_e) { /* index may already exist */ } + await trx.raw("PRAGMA foreign_keys = ON"); }); - } finally { + } catch (e) { await knex.raw("PRAGMA foreign_keys = ON"); + throw e; } } @@ -87,10 +88,9 @@ export async function down(knex: Knex): Promise { } // Revert: make monitor_tag NOT NULL again via table rebuild - await knex.raw("PRAGMA foreign_keys = OFF"); - try { await knex.transaction(async (trx) => { + await trx.raw("PRAGMA foreign_keys = OFF"); await trx.raw(` CREATE TABLE monitor_alerts_config_old ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -135,8 +135,10 @@ export async function down(knex: Knex): Promise { } catch (_e) { /* index may already exist */ } + await trx.raw("PRAGMA foreign_keys = ON"); }); - } finally { + } catch (e) { await knex.raw("PRAGMA foreign_keys = ON"); + throw e; } }