-- Migration 120: conservative form_factor recovery (provably-wrong rows only) -- ───────────────────────────────────────────────────────────────────────────── -- Problem: some scrapers default form_factor to 'SFP'/'SFP+', so a 400G QSFP-DD -- DAC ends up tagged 'SFP+'. We only ever correct a form_factor that is -- PROVABLY wrong — i.e. its max electrical speed (form_factors.max_speed_gbps) -- is below the row's actual speed_gbps — and only when the part_number carries -- an explicit form-factor token that CAN carry that speed. Opaque part numbers -- (e.g. 'EOLS-1303-40-D') are left untouched; we never guess a form factor. -- -- The scraped original is preserved in form_factor_raw for audit/rollback. -- Ingest-time self-healing is added to the tip_transceivers_biu() trigger. -- Idempotent. -- ───────────────────────────────────────────────────────────────────────────── -- 1. Preserve the scraped original --------------------------------------------- ALTER TABLE transceivers ADD COLUMN IF NOT EXISTS form_factor_raw TEXT; COMMENT ON COLUMN transceivers.form_factor_raw IS 'Form factor exactly as scraped, before tip_recover_form_factor() correction. Audit/rollback only.'; UPDATE transceivers SET form_factor_raw = form_factor WHERE form_factor_raw IS NULL; -- 2. Explicit form-factor token extraction (most-specific first) ---------------- CREATE OR REPLACE FUNCTION tip_extract_ff_token(p_part_number TEXT) RETURNS TEXT LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT CASE WHEN p_part_number ~* 'qsfp-?dd-?800|qdd-?800' THEN 'QSFP-DD800' -- Q56DD / QSFP56-DD is the 400G double-density QSFP connector (Dell naming) → QSFP-DD WHEN p_part_number ~* 'q56dd|qsfp56-?dd' THEN 'QSFP-DD' WHEN p_part_number ~* 'osfp-?xd' THEN 'OSFP-XD' WHEN p_part_number ~* 'osfp224' THEN 'OSFP224' WHEN p_part_number ~* 'osfp112' THEN 'OSFP112' WHEN p_part_number ~* '\mosfp\M' THEN 'OSFP' WHEN p_part_number ~* 'qsfp112' THEN 'QSFP112' WHEN p_part_number ~* 'qsfp-?dd|\mqdd\M|qsfpdd' THEN 'QSFP-DD' WHEN p_part_number ~* 'qsfp56|\mq56\M' THEN 'QSFP56' WHEN p_part_number ~* 'qsfp28|\mq28\M' THEN 'QSFP28' WHEN p_part_number ~* 'qsfp\+|qsfp-?plus' THEN 'QSFP+' WHEN p_part_number ~* 'sfp-?dd|sfpdd' THEN 'SFP-DD' WHEN p_part_number ~* 'sfp112' THEN 'SFP112' WHEN p_part_number ~* 'sfp56' THEN 'SFP56' WHEN p_part_number ~* 'sfp28' THEN 'SFP28' WHEN p_part_number ~* 'sfp\+|sfp-?plus' THEN 'SFP+' WHEN p_part_number ~* 'cfp2-?dco' THEN 'CFP2-DCO' WHEN p_part_number ~* 'cfp2' THEN 'CFP2' WHEN p_part_number ~* 'cfp8' THEN 'CFP8' WHEN p_part_number ~* 'cfp4' THEN 'CFP4' WHEN p_part_number ~* '\mcfp\M' THEN 'CFP' WHEN p_part_number ~* '\mxfp\M' THEN 'XFP' ELSE NULL END; $$; -- 3. Recovery: return corrected FF only when the current one is PROVABLY wrong --- CREATE OR REPLACE FUNCTION tip_recover_form_factor( p_part_number TEXT, p_form_factor TEXT, p_speed_gbps NUMERIC ) RETURNS TEXT LANGUAGE plpgsql STABLE PARALLEL SAFE AS $$ DECLARE v_token TEXT := tip_extract_ff_token(p_part_number); v_cur_max NUMERIC; v_tok_max NUMERIC; BEGIN IF v_token IS NULL OR p_form_factor IS NULL OR p_speed_gbps IS NULL THEN RETURN p_form_factor; END IF; IF upper(v_token) = upper(p_form_factor) THEN RETURN p_form_factor; -- already correct END IF; SELECT max_speed_gbps INTO v_cur_max FROM form_factors WHERE upper(name) = upper(p_form_factor); SELECT max_speed_gbps INTO v_tok_max FROM form_factors WHERE name = v_token; -- current provably wrong for the speed, and the token can actually carry it IF v_cur_max IS NOT NULL AND v_tok_max IS NOT NULL AND p_speed_gbps > v_cur_max AND v_tok_max >= p_speed_gbps THEN RETURN v_token; END IF; RETURN p_form_factor; -- not confident → leave as-is END; $$; -- 4. Backfill the confidently-recoverable rows --------------------------------- UPDATE transceivers SET form_factor = tip_recover_form_factor(part_number, form_factor, speed_gbps) WHERE form_factor IS DISTINCT FROM tip_recover_form_factor(part_number, form_factor, speed_gbps); -- 5. Extend the ingest trigger with FF self-healing ---------------------------- CREATE OR REPLACE FUNCTION tip_transceivers_biu() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN -- product_type: recompute only when a classification input changed IF TG_OP = 'INSERT' OR NEW.product_type IS NULL OR NEW.part_number IS DISTINCT FROM OLD.part_number OR NEW.category IS DISTINCT FROM OLD.category OR NEW.reach_label IS DISTINCT FROM OLD.reach_label THEN NEW.product_type := tip_classify_product_type(NEW.part_number, NEW.category, NEW.reach_label); END IF; -- form_factor: preserve the scraped original, then correct only provably-wrong values NEW.form_factor_raw := COALESCE(NEW.form_factor_raw, NEW.form_factor); NEW.form_factor := tip_recover_form_factor(NEW.part_number, NEW.form_factor, NEW.speed_gbps); RETURN NEW; END; $$; -- (trigger trg_transceivers_biu already bound in migration 119 — replacing the -- function body above is sufficient.) INSERT INTO _migrations (filename) VALUES ('120-form-factor-recovery.sql') ON CONFLICT (filename) DO NOTHING; -- 6. Report -------------------------------------------------------------------- DO $$ DECLARE v_fixed INT; v_left INT; BEGIN SELECT count(*) INTO v_fixed FROM transceivers WHERE form_factor IS DISTINCT FROM form_factor_raw; SELECT count(*) INTO v_left FROM transceivers t JOIN form_factors f ON upper(f.name)=upper(t.form_factor) WHERE t.speed_gbps > f.max_speed_gbps; RAISE NOTICE 'form_factor corrected on % rows; % provably-wrong rows left untouched (opaque, not guessed).', v_fixed, v_left; END; $$;