-- 136 Make speed_gbps nullable + one-time reversible cleanup of junk speed. -- Requires 135 (tip_speed_is_implausible, trg_speed_plausibility) applied first. -- -- speed_gbps was NOT NULL, which (a) forced meaningless values onto cables/accessories -- and (b) made the guard trigger unusable: NULLing junk on write would abort the insert. -- "Unknown speed" is honestly NULL, so we drop the constraint, then NULL the ~4708 -- unambiguous-junk rows (sub-0.09 fragments incl. <=0, and >1600 cable-part-number -- integers). 87% are dac/aoc/accessory where speed is meaningless anyway. The old value -- is snapshotted by primary key so the change is fully reversible. The 0.09..1600 gray -- band (~355 legit FC/SDI/CPRI/OTN line rates) is intentionally left untouched. -- -- PREVIEW before running (nothing legit should appear): -- SELECT speed_gbps, count(*) FROM transceivers -- WHERE tip_speed_is_implausible(speed_gbps) GROUP BY 1 ORDER BY 1; BEGIN; ALTER TABLE transceivers ALTER COLUMN speed_gbps DROP NOT NULL; CREATE TABLE IF NOT EXISTS tip_speed_gbps_rollback ( id uuid PRIMARY KEY, old_speed_gbps numeric, backed_up_at timestamptz DEFAULT now() ); INSERT INTO tip_speed_gbps_rollback (id, old_speed_gbps) SELECT id, speed_gbps FROM transceivers WHERE tip_speed_is_implausible(speed_gbps) ON CONFLICT (id) DO NOTHING; UPDATE transceivers SET speed_gbps = NULL WHERE tip_speed_is_implausible(speed_gbps); COMMIT; -- REVERSE (maintenance window, no concurrent writers). Disable the guard so it does -- not re-NULL the junk being restored: -- BEGIN; -- ALTER TABLE transceivers DISABLE TRIGGER trg_speed_plausibility; -- UPDATE transceivers t SET speed_gbps = r.old_speed_gbps -- FROM tip_speed_gbps_rollback r -- WHERE t.id = r.id AND t.speed_gbps IS NULL; -- ALTER TABLE transceivers ENABLE TRIGGER trg_speed_plausibility; -- -- optional, only if every row is non-null again: -- -- ALTER TABLE transceivers ALTER COLUMN speed_gbps SET NOT NULL; -- COMMIT;