Files
paliad/internal/db/migrations/092_drop_event_deadlines_tables.down.sql
mAi 29a6b58747 refactor(t-paliad-199): Slice 9 follow-up A — drop legacy event_deadlines tables
EventDeadlineService.Calculate now reads source rows from
paliad.deadline_rules directly (WHERE trigger_event_id IS NOT NULL),
joining via UUID instead of title_de string. The legacy SELECTs against
paliad.event_deadlines + paliad.event_deadline_rule_codes are gone.

Migration 092:
- Snapshots both legacy tables into _pre_092 audit anchors.
- Adds paliad.deadline_rules.rule_codes text[] and backfills the 72
  multi-code citations from event_deadline_rule_codes via the
  sequence_order = 1000 + ed.id convention from mig 085 (70 of 77
  Pipeline-C deadlines carry codes; 7 are codeless).
- Hard assertion ties source-junction-row count to backfilled
  text[]-element count — any sequence_order mismatch aborts the drop.
- Drops the mig 086 read-only trigger (orphan once event_deadlines
  goes away).
- Drops paliad.event_deadlines + paliad.event_deadline_rule_codes.
- Final assertion: >=77 active deadline_rules with trigger_event_id
  NOT NULL — Slice 3 corpus must not have collapsed.
- audit_reason wrapper at top so the deadline_rules UPDATE row-trigger
  records the reason in deadline_rule_audit.

Verified via BEGIN..ROLLBACK against the live paliad DB: 72 codes
backfilled into 70 rule_codes arrays, multi-code rules (RoP.029.a +
RoP.030 for ed_id=6) preserve their ordering, composite rules
(combine_op=max) remain intact, both tables drop cleanly, all
assertions pass.

Parity test rebound to deadline_rules — independent computation still
re-runs applyDuration against raw column values for date/composite
parity. EventDeadlineResult.ID stays int64 via the sequence_order -
1000 convention so the public /api/tools/event-deadlines wire shape
is unchanged.
2026-05-16 01:17:23 +02:00

117 lines
5.4 KiB
PL/PgSQL

-- t-paliad-199 down — reverses 092_drop_event_deadlines_tables.up.sql.
--
-- Re-creates paliad.event_deadlines + paliad.event_deadline_rule_codes
-- with the schema they had at end of mig 086 (the read-only state right
-- before mig 092 dropped them), repopulates from the _pre_092
-- snapshots, restores the mig 086 read-only trigger, and drops the
-- rule_codes column the up migration added to paliad.deadline_rules.
--
-- The snapshot tables themselves stay — they're the source of this
-- rollback's data and a permanent audit artefact. A focused
-- follow-up slice / Slice 12 cleanup drops the snapshots once
-- Slice 9 is verified in prod.
SELECT set_config(
'paliad.audit_reason',
'rollback 092: restore paliad.event_deadlines + event_deadline_rule_codes from pre-drop snapshots and drop rule_codes column',
true);
-- =============================================================================
-- 1. Recreate paliad.event_deadlines. Schema matches the live state at
-- the start of mig 092 (post-mig-086, with the notes_en column from
-- mig 036 and the legal_source column from mig 038).
-- =============================================================================
CREATE TABLE IF NOT EXISTS paliad.event_deadlines (
id bigint PRIMARY KEY,
trigger_event_id bigint NOT NULL REFERENCES paliad.trigger_events(id) ON DELETE CASCADE,
title text NOT NULL,
title_de text NOT NULL DEFAULT '',
duration_value integer NOT NULL DEFAULT 0,
duration_unit text NOT NULL DEFAULT 'days'
CHECK (duration_unit IN ('days', 'weeks', 'months', 'working_days')),
timing text NOT NULL DEFAULT 'after'
CHECK (timing IN ('before', 'after')),
notes text NOT NULL DEFAULT '',
alt_duration_value integer,
alt_duration_unit text CHECK (alt_duration_unit IS NULL OR alt_duration_unit IN ('days', 'weeks', 'months', 'working_days')),
combine_op text CHECK (combine_op IS NULL OR combine_op IN ('max', 'min')),
is_active boolean NOT NULL DEFAULT true,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
notes_en text,
legal_source text
);
CREATE INDEX IF NOT EXISTS event_deadlines_trigger_event_idx
ON paliad.event_deadlines (trigger_event_id);
CREATE INDEX IF NOT EXISTS event_deadlines_active_idx
ON paliad.event_deadlines (is_active) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS event_deadlines_legal_src_trgm
ON paliad.event_deadlines USING gin (legal_source gin_trgm_ops);
INSERT INTO paliad.event_deadlines
(id, trigger_event_id, title, title_de, duration_value, duration_unit,
timing, notes, alt_duration_value, alt_duration_unit, combine_op,
is_active, created_at, updated_at, notes_en, legal_source)
SELECT id, trigger_event_id, title, title_de, duration_value, duration_unit,
timing, notes, alt_duration_value, alt_duration_unit, combine_op,
is_active, created_at, updated_at, notes_en, legal_source
FROM paliad.event_deadlines_pre_092
ON CONFLICT (id) DO NOTHING;
-- =============================================================================
-- 2. Recreate paliad.event_deadline_rule_codes.
-- =============================================================================
CREATE TABLE IF NOT EXISTS paliad.event_deadline_rule_codes (
event_deadline_id bigint NOT NULL REFERENCES paliad.event_deadlines(id) ON DELETE CASCADE,
rule_code text NOT NULL,
sort_order integer NOT NULL DEFAULT 0,
PRIMARY KEY (event_deadline_id, rule_code)
);
CREATE INDEX IF NOT EXISTS event_deadline_rule_codes_code_idx
ON paliad.event_deadline_rule_codes (rule_code);
INSERT INTO paliad.event_deadline_rule_codes
(event_deadline_id, rule_code, sort_order)
SELECT event_deadline_id, rule_code, sort_order
FROM paliad.event_deadline_rule_codes_pre_092
ON CONFLICT (event_deadline_id, rule_code) DO NOTHING;
-- =============================================================================
-- 3. Restore the mig 086 read-only trigger + function (the rolled-back
-- state IS "Slice 3 + Slice 9 only", which had the trigger in place).
-- =============================================================================
CREATE OR REPLACE FUNCTION paliad.event_deadlines_readonly_trigger()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION
'paliad.event_deadlines is read-only after Phase 3 Slice 3 — '
'writes must go through paliad.deadline_rules (Pipeline C is '
'unified; the source table is preserved as an audit anchor '
'until Slice 9 drops it). Operation: %', TG_OP;
END;
$$;
DROP TRIGGER IF EXISTS event_deadlines_readonly ON paliad.event_deadlines;
CREATE TRIGGER event_deadlines_readonly
BEFORE INSERT OR UPDATE OR DELETE ON paliad.event_deadlines
FOR EACH ROW
EXECUTE FUNCTION paliad.event_deadlines_readonly_trigger();
-- =============================================================================
-- 4. Drop the rule_codes column the up migration added. The data is
-- preserved in paliad.event_deadline_rule_codes (just restored
-- above), so dropping the column doesn't lose history.
-- =============================================================================
ALTER TABLE paliad.deadline_rules
DROP COLUMN IF EXISTS rule_codes;