// run any post migration checks or side effects
// so far, this is just adding the updated_at_sync_tick column and trigger to all new tables
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get runPostMigration () {
        return runPostMigration;
    },
    get runPreMigration () {
        return runPreMigration;
    }
});
const _config = /*#__PURE__*/ _interop_require_default(require("config"));
const _sequelize = require("sequelize");
const _selectFacilityIds = require("@tamanu/utils/selectFacilityIds");
const _constants = require("./constants");
const _constants1 = require("../../sync/constants");
const _utils = require("../../utils");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
async function runPreMigration(log, sequelize) {
    // remove sync tick trigger before migrations
    // migrations are deterministic, so updating the sync tick just creates useless churn
    for (const { schema, table } of (await (0, _utils.tablesWithTrigger)(sequelize, 'set_', '_updated_at_sync_tick', [
        ..._constants.GLOBAL_EXCLUDE_TABLES,
        ..._constants.NON_SYNCING_TABLES
    ]))){
        // we need to keep the updated_at_sync_tick trigger on the changes table
        if (schema === 'logs' && table === 'changes') {
            continue;
        }
        log.info(`Removing updated_at_sync_tick trigger from ${schema}.${table}`);
        await sequelize.query(`DROP TRIGGER set_${table}_updated_at_sync_tick ON "${schema}"."${table}"`);
    }
}
async function runPostMigration(log, sequelize) {
    // add column: holds last update tick, default to 0 (will be caught in any initial sync) on central server
    // and SYNC_TICK_FLAGS.UPDATED_ELSEWHERE (not marked for sync) on facility
    // triggers will overwrite the default for future data, but this works for existing data
    const isFacilityServer = !!(0, _selectFacilityIds.selectFacilityIds)(_config.default);
    const initialValue = isFacilityServer ? _constants1.SYNC_TICK_FLAGS.LAST_UPDATED_ELSEWHERE : 0;
    for (const { schema, table } of (await (0, _utils.tablesWithoutColumn)(sequelize, 'updated_at_sync_tick', [
        ..._constants.GLOBAL_EXCLUDE_TABLES,
        ..._constants.NON_SYNCING_TABLES
    ]))){
        log.info(`Adding updated_at_sync_tick column to ${schema}.${table}`);
        await sequelize.query(`
      ALTER TABLE "${schema}"."${table}" ADD COLUMN updated_at_sync_tick BIGINT NOT NULL DEFAULT ${initialValue};
    `);
        await sequelize.query(`
      CREATE INDEX ${table}_updated_at_sync_tick_index ON "${schema}"."${table}" (updated_at_sync_tick);
    `);
    }
    const functionExists = (name)=>sequelize.query('select count(*) as count from pg_catalog.pg_proc where proname = $name', {
            type: _sequelize.QueryTypes.SELECT,
            bind: {
                name
            }
        }).then((rows)=>rows?.[0]?.count > 0);
    // add trigger: before update, update updated_at when the data in the row changed
    if (await functionExists('set_updated_at')) {
        for (const { schema, table } of (await (0, _utils.tablesWithoutTrigger)(sequelize, 'set_', '_updated_at', [
            ..._constants.GLOBAL_EXCLUDE_TABLES,
            ..._constants.NON_SYNCING_TABLES
        ]))){
            log.info(`Adding updated_at trigger to ${schema}.${table}`);
            await sequelize.query(`
      CREATE TRIGGER set_${table}_updated_at
      BEFORE INSERT OR UPDATE ON "${schema}"."${table}"
      FOR EACH ROW
      EXECUTE FUNCTION public.set_updated_at();
    `);
        }
    }
    // add trigger: before insert or update, set updated_at_sync_tick (overriding any that is passed in)
    if (await functionExists('set_updated_at_sync_tick')) {
        for (const { schema, table } of (await (0, _utils.tablesWithoutTrigger)(sequelize, 'set_', '_updated_at_sync_tick', [
            ..._constants.GLOBAL_EXCLUDE_TABLES,
            ..._constants.NON_SYNCING_TABLES
        ]))){
            log.info(`Adding updated_at_sync_tick trigger to ${schema}.${table}`);
            await sequelize.query(`
      CREATE TRIGGER set_${table}_updated_at_sync_tick
      BEFORE INSERT OR UPDATE ON "${schema}"."${table}"
      FOR EACH ROW
      EXECUTE FUNCTION public.set_updated_at_sync_tick();
    `);
        }
    }
    // add trigger to table for pg notify
    if (await functionExists('notify_table_changed')) {
        for (const { schema, table } of (await (0, _utils.tablesWithoutTrigger)(sequelize, 'notify_', '_changed', [
            ..._constants.GLOBAL_EXCLUDE_TABLES,
            ..._constants.NON_SYNCING_TABLES
        ]))){
            log.info(`Adding notify change trigger to ${schema}.${table}`);
            await sequelize.query(`
      CREATE TRIGGER notify_${table}_changed
      AFTER INSERT OR UPDATE OR DELETE ON "${schema}"."${table}"
      FOR EACH ROW
      EXECUTE FUNCTION public.notify_table_changed();
    `);
        }
    }
    // add trigger to table for changelogs
    if (await functionExists('record_change')) {
        for (const { schema, table } of (await (0, _utils.tablesWithoutTrigger)(sequelize, 'record_', '_changelog', [
            ..._constants.GLOBAL_EXCLUDE_TABLES,
            ..._constants.NON_LOGGED_TABLES
        ]))){
            log.info(`Adding changelog trigger to ${schema}.${table}`);
            await sequelize.query(`
      CREATE CONSTRAINT TRIGGER record_${table}_changelog
      AFTER INSERT OR UPDATE ON "${schema}"."${table}"
      DEFERRABLE INITIALLY DEFERRED
      FOR EACH ROW
      EXECUTE FUNCTION logs.record_change();
    `);
        }
    }
}

//# sourceMappingURL=migrationHooks.js.map