19 active fristenrechner codes renamed from UPPER_SNAKE to the lowercase three-position dot-separated taxonomy ratified by m on 2026-05-18 (see docs/design-proceeding-code-taxonomy-2026-05-18.md). IDs are stable; only the `code` STRING changes. Adds upc.ccr.cfi as an illustrative peer of upc.inf.cfi (is_active=true, no rules — Go code routes cascade hits back to inf.cfi with with_ccr=true). Also updates the soft `proceeding_type_code` references on paliad.event_category_concepts so the soft-join through proceeding_types.code keeps resolving, refreshes the deadline_search materialized view, and installs the paliad_proceeding_code_shape CHECK constraint enforcing `^[a-z]+\\.[a-z]+\\.[a-z]+$` on every active row. Idempotent: every UPDATE is guarded on the OLD code; INSERT uses WHERE NOT EXISTS; CHECK is dropped-then-recreated by name. Backup snapshot lives in paliad.proceeding_types_pre_096. Dry-run on the live youpc DB (BEGIN; … ROLLBACK) confirmed 20 active rows on the new shape, 0 old codes left, 1 active upc.ccr.cfi.
227 lines
12 KiB
SQL
227 lines
12 KiB
SQL
-- t-paliad-206 / proceeding-code rename — replace the historical
|
|
-- UPPER_SNAKE proceeding codes with the lowercase dot-separated
|
|
-- taxonomy ratified by m on 2026-05-18 (see
|
|
-- docs/design-proceeding-code-taxonomy-2026-05-18.md).
|
|
--
|
|
-- IDs are stable. Only the `code` STRING changes. FKs
|
|
-- (deadline_rules.proceeding_type_id, projects.proceeding_type_id,
|
|
-- deadline_rules.spawn_proceeding_type_id) reference IDs, so the
|
|
-- existing rule corpus and spawn wiring continue to work unchanged
|
|
-- (incl. mig 095's spawn_proceeding_type_id=11 which becomes
|
|
-- 'upc.apl.merits' after this migration).
|
|
--
|
|
-- Soft references on `code` (text column on event_category_concepts) are
|
|
-- updated row-for-row to keep the soft join through proceeding_types.code
|
|
-- resolving.
|
|
--
|
|
-- The materialized view paliad.deadline_search projects pt.code as
|
|
-- proceeding_code; mig 096 REFRESHes it at the bottom so the new codes
|
|
-- show up in search results immediately.
|
|
--
|
|
-- Idempotent:
|
|
-- * UPDATEs are guarded by `WHERE code = '<OLD>'`. Re-running after a
|
|
-- successful first apply is a no-op.
|
|
-- * INSERT of upc.ccr.cfi uses `WHERE NOT EXISTS` keyed on the new
|
|
-- code (bohr noted in t-paliad-205 that a UNIQUE constraint on the
|
|
-- code column is not present, hence WHERE NOT EXISTS rather than
|
|
-- ON CONFLICT).
|
|
-- * CHECK constraint is dropped-then-recreated under the same name
|
|
-- (paliad_proceeding_code_shape) so reapplication doesn't error.
|
|
-- * Snapshot table uses CREATE TABLE IF NOT EXISTS.
|
|
--
|
|
-- audit_reason wrapper required by the mig 079 audit trigger.
|
|
|
|
SELECT set_config(
|
|
'paliad.audit_reason',
|
|
'mig 096: t-paliad-206 proceeding-code rename — lowercase dot-separated taxonomy + new upc.ccr.cfi illustrative peer; see docs/design-proceeding-code-taxonomy-2026-05-18.md',
|
|
true);
|
|
|
|
-- =============================================================================
|
|
-- 1. Backup snapshot of paliad.proceeding_types BEFORE the rename. The
|
|
-- rename is forward-only in code (the Go + frontend sweeps reference
|
|
-- the new strings) but the DB snapshot is the audit anchor and the
|
|
-- source for the down migration.
|
|
-- =============================================================================
|
|
|
|
CREATE TABLE IF NOT EXISTS paliad.proceeding_types_pre_096 AS
|
|
SELECT *, now() AS snapshotted_at
|
|
FROM paliad.proceeding_types;
|
|
|
|
COMMENT ON TABLE paliad.proceeding_types_pre_096 IS
|
|
'Snapshot of paliad.proceeding_types taken before mig 096 renamed '
|
|
'the `code` strings to the lowercase dot-separated taxonomy '
|
|
'(t-paliad-206, 2026-05-18). Source-of-truth for the down '
|
|
'migration; persists post-rename as the permanent audit record.';
|
|
|
|
-- =============================================================================
|
|
-- 2. Drop any prior shape CHECK so we can recreate it post-rename. The
|
|
-- constraint name is stable so reapplication idempotently drops it.
|
|
-- =============================================================================
|
|
|
|
ALTER TABLE paliad.proceeding_types
|
|
DROP CONSTRAINT IF EXISTS paliad_proceeding_code_shape;
|
|
|
|
-- =============================================================================
|
|
-- 3. The 19 renames. Order-independent — every UPDATE is guarded by
|
|
-- `WHERE code = '<OLD>'` so re-application is a no-op. id values in
|
|
-- the trailing comment for cross-reference with the design doc.
|
|
-- =============================================================================
|
|
|
|
-- UPC
|
|
UPDATE paliad.proceeding_types SET code = 'upc.inf.cfi' WHERE code = 'UPC_INF'; -- id=8
|
|
UPDATE paliad.proceeding_types SET code = 'upc.rev.cfi' WHERE code = 'UPC_REV'; -- id=9
|
|
UPDATE paliad.proceeding_types SET code = 'upc.pi.cfi' WHERE code = 'UPC_PI'; -- id=10
|
|
UPDATE paliad.proceeding_types SET code = 'upc.apl.merits' WHERE code = 'UPC_APP'; -- id=11
|
|
UPDATE paliad.proceeding_types SET code = 'upc.dmgs.cfi' WHERE code = 'UPC_DAMAGES'; -- id=17
|
|
UPDATE paliad.proceeding_types SET code = 'upc.disc.cfi' WHERE code = 'UPC_DISCOVERY'; -- id=18
|
|
UPDATE paliad.proceeding_types SET code = 'upc.apl.cost' WHERE code = 'UPC_COST_APPEAL';-- id=19
|
|
UPDATE paliad.proceeding_types SET code = 'upc.apl.order' WHERE code = 'UPC_APP_ORDERS'; -- id=20
|
|
|
|
-- DE
|
|
UPDATE paliad.proceeding_types SET code = 'de.inf.lg' WHERE code = 'DE_INF'; -- id=12
|
|
UPDATE paliad.proceeding_types SET code = 'de.inf.olg' WHERE code = 'DE_INF_OLG'; -- id=25
|
|
UPDATE paliad.proceeding_types SET code = 'de.inf.bgh' WHERE code = 'DE_INF_BGH'; -- id=26
|
|
UPDATE paliad.proceeding_types SET code = 'de.null.bpatg' WHERE code = 'DE_NULL'; -- id=13
|
|
UPDATE paliad.proceeding_types SET code = 'de.null.bgh' WHERE code = 'DE_NULL_BGH'; -- id=27
|
|
|
|
-- EPA
|
|
UPDATE paliad.proceeding_types SET code = 'epa.grant.exa' WHERE code = 'EP_GRANT'; -- id=16
|
|
UPDATE paliad.proceeding_types SET code = 'epa.opp.opd' WHERE code = 'EPA_OPP'; -- id=14
|
|
UPDATE paliad.proceeding_types SET code = 'epa.opp.boa' WHERE code = 'EPA_APP'; -- id=15
|
|
|
|
-- DPMA
|
|
UPDATE paliad.proceeding_types SET code = 'dpma.opp.dpma' WHERE code = 'DPMA_OPP'; -- id=28
|
|
UPDATE paliad.proceeding_types SET code = 'dpma.appeal.bpatg' WHERE code = 'DPMA_BPATG_BESCHWERDE';-- id=29
|
|
UPDATE paliad.proceeding_types SET code = 'dpma.appeal.bgh' WHERE code = 'DPMA_BGH_RB'; -- id=30
|
|
|
|
-- =============================================================================
|
|
-- 4. Update soft references on event_category_concepts.proceeding_type_code.
|
|
-- Same OLD→NEW table as above; the column has a UNIQUE NULLS NOT
|
|
-- DISTINCT constraint on (event_category_id, concept_id, proceeding_type_code)
|
|
-- but no row has the NEW string yet so the UPDATEs cannot collide.
|
|
-- =============================================================================
|
|
|
|
-- UPC
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.inf.cfi' WHERE proceeding_type_code = 'UPC_INF';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.rev.cfi' WHERE proceeding_type_code = 'UPC_REV';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.pi.cfi' WHERE proceeding_type_code = 'UPC_PI';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.apl.merits' WHERE proceeding_type_code = 'UPC_APP';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.dmgs.cfi' WHERE proceeding_type_code = 'UPC_DAMAGES';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.disc.cfi' WHERE proceeding_type_code = 'UPC_DISCOVERY';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.apl.cost' WHERE proceeding_type_code = 'UPC_COST_APPEAL';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'upc.apl.order' WHERE proceeding_type_code = 'UPC_APP_ORDERS';
|
|
|
|
-- DE
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'de.inf.lg' WHERE proceeding_type_code = 'DE_INF';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'de.inf.olg' WHERE proceeding_type_code = 'DE_INF_OLG';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'de.inf.bgh' WHERE proceeding_type_code = 'DE_INF_BGH';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'de.null.bpatg' WHERE proceeding_type_code = 'DE_NULL';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'de.null.bgh' WHERE proceeding_type_code = 'DE_NULL_BGH';
|
|
|
|
-- EPA
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'epa.grant.exa' WHERE proceeding_type_code = 'EP_GRANT';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'epa.opp.opd' WHERE proceeding_type_code = 'EPA_OPP';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'epa.opp.boa' WHERE proceeding_type_code = 'EPA_APP';
|
|
|
|
-- DPMA
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'dpma.opp.dpma' WHERE proceeding_type_code = 'DPMA_OPP';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'dpma.appeal.bpatg' WHERE proceeding_type_code = 'DPMA_BPATG_BESCHWERDE';
|
|
UPDATE paliad.event_category_concepts SET proceeding_type_code = 'dpma.appeal.bgh' WHERE proceeding_type_code = 'DPMA_BGH_RB';
|
|
|
|
-- =============================================================================
|
|
-- 5. Insert the new illustrative peer `upc.ccr.cfi`. is_active=true so it
|
|
-- surfaces in the determinator + dropdowns; no rules attached.
|
|
-- proceeding_mapping.go routes cascade hits on this code back to
|
|
-- upc.inf.cfi (id=8) with the with_ccr default flag — see design doc S1.
|
|
--
|
|
-- WHERE NOT EXISTS gates the insert on the new code so re-application
|
|
-- is a no-op even though there's no UNIQUE constraint on (code).
|
|
-- =============================================================================
|
|
|
|
INSERT INTO paliad.proceeding_types
|
|
(code, category, jurisdiction, is_active, name, name_en, description)
|
|
SELECT
|
|
'upc.ccr.cfi',
|
|
'fristenrechner',
|
|
'UPC',
|
|
true,
|
|
'Widerklage auf Nichtigkeit',
|
|
'Counterclaim for Revocation',
|
|
'Illustrativer Peer von upc.inf.cfi für Widerklagen auf Nichtigkeit. Regeln liegen auf upc.inf.cfi (with_ccr=true); der Fristenrechner leitet bei Auswahl dorthin weiter. Keine eigenen Fristregeln.'
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM paliad.proceeding_types
|
|
WHERE code = 'upc.ccr.cfi');
|
|
|
|
-- =============================================================================
|
|
-- 6. CHECK constraint on the code shape. Active rows must conform to the
|
|
-- new lowercase dot-separated form; the carve-out for
|
|
-- `_archived_litigation` keeps the Pipeline-A bucket addressable.
|
|
-- =============================================================================
|
|
|
|
ALTER TABLE paliad.proceeding_types
|
|
ADD CONSTRAINT paliad_proceeding_code_shape
|
|
CHECK (
|
|
code ~ '^[a-z]+\.[a-z]+\.[a-z]+$'
|
|
OR code ~ '^_archived_'
|
|
);
|
|
|
|
-- =============================================================================
|
|
-- 7. Refresh the deadline_search materialized view so search hits return
|
|
-- the new proceeding_code strings immediately.
|
|
-- =============================================================================
|
|
|
|
REFRESH MATERIALIZED VIEW paliad.deadline_search;
|
|
|
|
-- =============================================================================
|
|
-- 8. Hard assertions. Half-applied migrations would leave the rule corpus
|
|
-- inconsistent with the new shape; assert every active fristenrechner
|
|
-- code conforms and that no old codes leak.
|
|
-- =============================================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
v_new_shape integer;
|
|
v_old_codes integer;
|
|
v_ccr_row integer;
|
|
BEGIN
|
|
-- 8.1 Every active fristenrechner row matches the new shape regex.
|
|
-- 20 = 19 renamed rows + 1 newly inserted upc.ccr.cfi. The check
|
|
-- uses >= so an additional row added in a follow-up migration
|
|
-- doesn't trip the assertion.
|
|
SELECT count(*) INTO v_new_shape
|
|
FROM paliad.proceeding_types
|
|
WHERE category = 'fristenrechner'
|
|
AND is_active = true
|
|
AND code ~ '^[a-z]+\.[a-z]+\.[a-z]+$';
|
|
IF v_new_shape < 20 THEN
|
|
RAISE EXCEPTION
|
|
'mig 096: expected >= 20 active fristenrechner rows on the new shape, got %',
|
|
v_new_shape;
|
|
END IF;
|
|
|
|
-- 8.2 No old UPPER_SNAKE codes remain on any row.
|
|
SELECT count(*) INTO v_old_codes
|
|
FROM paliad.proceeding_types
|
|
WHERE code LIKE 'UPC\_%' ESCAPE '\'
|
|
OR code LIKE 'DE\_%' ESCAPE '\'
|
|
OR code LIKE 'EPA\_%' ESCAPE '\'
|
|
OR code LIKE 'EP\_%' ESCAPE '\'
|
|
OR code LIKE 'DPMA\_%' ESCAPE '\';
|
|
IF v_old_codes <> 0 THEN
|
|
RAISE EXCEPTION
|
|
'mig 096: expected 0 old UPPER_SNAKE codes after rename, got %',
|
|
v_old_codes;
|
|
END IF;
|
|
|
|
-- 8.3 The new ccr peer exists and is active.
|
|
SELECT count(*) INTO v_ccr_row
|
|
FROM paliad.proceeding_types
|
|
WHERE code = 'upc.ccr.cfi'
|
|
AND is_active = true;
|
|
IF v_ccr_row <> 1 THEN
|
|
RAISE EXCEPTION
|
|
'mig 096: expected 1 active upc.ccr.cfi row, got %',
|
|
v_ccr_row;
|
|
END IF;
|
|
END $$;
|