transceiver-db/sql/113-infer-connector-type.sql
Rene Fichtmueller d1bde66e39 feat: deterministic equivalence matcher + full wavelength/connector enrichment
Replace confidence-based matcher with deterministic 6-field exact match:
- form_factor (exact), speed_gbps (±0.1G), fiber_type (exact),
  reach (±10%), wavelength_tx (±5nm), connector_type (exact)
- Complete products → confidence=1.0, never creates pending records
- Incomplete products → enhanced confidence ≥0.85, still auto_approved
- PENDING CREATED: 0 (by design, permanent)

Migrations:
- sql/113: Connector type inference from IEEE lookup + form-factor rules
  (970→479 missing connector for FX products)
- sql/114: Extend IEEE lookup with 400G/800G/1.6T OSFP/QSFP-DD standards,
  wavelength fallback (SMF→1310nm, MMF→850nm), clear pending queue to 0

Enrichment results (before→after):
- FX fully complete: 50 → 555 / 1,089 (+505)
- Total fully complete: ~3,600 → 15,431 / 18,133 (+11,800)
- FX coverage: 54.7% → 55.8% (608/1,089 matched)
- Deterministic matches: 0 → 44,596 (confidence=1.0)
- Wavelength-mismatched records rejected: 521
- Pending queue: 42 → 0 (permanent)

New match stats:
- 55,743 new deterministic auto_approved matches
- 521 legacy wavelength-mismatch records rejected
- Total active: 53,447 auto_approved + 1,987 approved
2026-05-13 17:59:08 +02:00

173 lines
7.6 KiB
SQL

-- Migration 113: Connector Type Inference
-- Füllt fehlende connector_type aus zwei Quellen:
-- 1. IEEE/MSA Lookup-Tabelle (exakt, nach reach range)
-- 2. Form-Factor + Fiber-Type Inferenz-Regeln (wenn IEEE kein Match)
-- Quelle: IEEE 802.3, SFF-8472, MSA specs, industry standard practices
-- ── Quelle 1: IEEE Lookup (reach-based, exakt) ──────────────────────────────
UPDATE transceivers t SET
connector_type = (
SELECT il.connector_type
FROM ieee_wavelength_lookup il
WHERE UPPER(il.form_factor) = UPPER(t.form_factor)
AND il.speed_gbps = ROUND(t.speed_gbps::NUMERIC, 2)
AND UPPER(il.fiber_type) = UPPER(t.fiber_type)
AND il.reach_min_m <= t.reach_meters
AND il.reach_max_m >= t.reach_meters
ORDER BY il.reach_max_m ASC -- Prefer tightest range match
LIMIT 1
)
WHERE t.connector_type IS NULL
AND t.form_factor IS NOT NULL
AND t.speed_gbps IS NOT NULL
AND t.fiber_type IS NOT NULL
AND t.reach_meters IS NOT NULL
AND t.reach_meters > 0;
DO $$
DECLARE v INTEGER;
BEGIN
SELECT COUNT(*) INTO v FROM transceivers WHERE connector_type IS NOT NULL
AND connector_type = (
SELECT il.connector_type FROM ieee_wavelength_lookup il
WHERE UPPER(il.form_factor) = UPPER(transceivers.form_factor) LIMIT 1
);
RAISE NOTICE 'After IEEE lookup: approx % connector_type values now set', v;
END $$;
-- ── Quelle 2: Form-Factor + Fiber-Type Inferenz ──────────────────────────────
-- Regeln basierend auf IEEE 802.3 und MSA Spezifikationen:
-- SFP/SFP+/SFP28/XFP + SMF/MMF → LC (dual fiber, standard single-mode)
-- QSFP+ + MMF → MPO-12 (SR4 = 4x parallel fiber)
-- QSFP+ + SMF, reach ≤ 2km → MPO-12 (PSM4 = parallel SMF)
-- QSFP+ + SMF, reach > 2km → LC (LR4 = CWDM4 on 2 fibers)
-- QSFP28 + MMF → MPO-12 (SR4)
-- QSFP28 + SMF, reach ≤ 2km → MPO-12 (DR/PSM4)
-- QSFP28 + SMF, reach > 2km → LC (LR4/CWDM4)
-- QSFP56 + MMF → MPO-16 (SR4 on 200G)
-- QSFP56 + SMF → LC (FR4/LR4)
-- QSFP-DD/QSFP-DD800 + MMF → MPO-16 (SR8)
-- QSFP-DD/QSFP-DD800 + SMF, reach ≤ 2km → MPO-12 (DR4/DR8)
-- QSFP-DD/QSFP-DD800 + SMF, reach > 2km → LC (FR4/LR4)
-- OSFP + MMF → MPO-16 (SR8)
-- OSFP + SMF, reach ≤ 2km → MPO-12 (DR8)
-- OSFP + SMF, reach > 2km → LC (FR4/LR4)
-- any + Copper → RJ45
-- any + DAC → NULL (native electrical, no fiber connector)
-- any + AOC → LC (optical fan-out)
UPDATE transceivers SET
connector_type = CASE
-- Copper BASE-T
WHEN UPPER(fiber_type) IN ('COPPER', 'COPPER/RJ45') THEN 'RJ45'
-- DAC = Direct Attach Copper, no optical connector
WHEN UPPER(fiber_type) = 'DAC' THEN 'DAC'
-- AOC = Active Optical Cable, LC fan-out connectors
WHEN UPPER(fiber_type) = 'AOC' THEN 'LC'
-- Single-lane form factors: always LC for optical
WHEN UPPER(form_factor) IN ('SFP', 'SFP+', 'SFP28', 'XFP', 'SFP56')
AND UPPER(fiber_type) IN ('SMF', 'MMF') THEN 'LC'
-- QSFP+ (40G)
WHEN UPPER(form_factor) = 'QSFP+'
AND UPPER(fiber_type) = 'MMF' THEN 'MPO-12'
WHEN UPPER(form_factor) = 'QSFP+'
AND UPPER(fiber_type) = 'SMF'
AND reach_meters IS NOT NULL AND reach_meters <= 2000 THEN 'MPO-12'
WHEN UPPER(form_factor) = 'QSFP+'
AND UPPER(fiber_type) = 'SMF'
AND (reach_meters IS NULL OR reach_meters > 2000) THEN 'LC'
-- QSFP28 (100G)
WHEN UPPER(form_factor) = 'QSFP28'
AND UPPER(fiber_type) = 'MMF' THEN 'MPO-12'
WHEN UPPER(form_factor) = 'QSFP28'
AND UPPER(fiber_type) = 'SMF'
AND reach_meters IS NOT NULL AND reach_meters <= 2000 THEN 'MPO-12'
WHEN UPPER(form_factor) = 'QSFP28'
AND UPPER(fiber_type) = 'SMF'
AND (reach_meters IS NULL OR reach_meters > 2000) THEN 'LC'
-- QSFP56 (200G)
WHEN UPPER(form_factor) = 'QSFP56'
AND UPPER(fiber_type) = 'MMF' THEN 'MPO-16'
WHEN UPPER(form_factor) = 'QSFP56'
AND UPPER(fiber_type) = 'SMF' THEN 'LC'
-- QSFP-DD / QSFP-DD800 (400G/800G)
WHEN UPPER(form_factor) IN ('QSFP-DD', 'QSFP-DD800')
AND UPPER(fiber_type) = 'MMF' THEN 'MPO-16'
WHEN UPPER(form_factor) IN ('QSFP-DD', 'QSFP-DD800')
AND UPPER(fiber_type) = 'SMF'
AND reach_meters IS NOT NULL AND reach_meters <= 2000 THEN 'MPO-12'
WHEN UPPER(form_factor) IN ('QSFP-DD', 'QSFP-DD800')
AND UPPER(fiber_type) = 'SMF'
AND (reach_meters IS NULL OR reach_meters > 2000) THEN 'LC'
-- OSFP (800G+)
WHEN UPPER(form_factor) = 'OSFP'
AND UPPER(fiber_type) = 'MMF' THEN 'MPO-16'
WHEN UPPER(form_factor) = 'OSFP'
AND UPPER(fiber_type) = 'SMF'
AND reach_meters IS NOT NULL AND reach_meters <= 2000 THEN 'MPO-12'
WHEN UPPER(form_factor) = 'OSFP'
AND UPPER(fiber_type) = 'SMF'
AND (reach_meters IS NULL OR reach_meters > 2000) THEN 'LC'
-- CFP/CFP2/CFP4 (100G coherent)
WHEN UPPER(form_factor) IN ('CFP', 'CFP2', 'CFP4') THEN 'LC'
ELSE NULL
END
WHERE connector_type IS NULL
AND form_factor IS NOT NULL
AND fiber_type IS NOT NULL;
-- ── Completeness neu berechnen ───────────────────────────────────────────────
UPDATE transceivers SET
data_completeness = calc_data_completeness(
form_factor, speed_gbps, fiber_type,
reach_meters, wavelength_tx_nm, connector_type
),
enrichment_needed = (
form_factor IS NULL OR speed_gbps IS NULL OR
fiber_type IS NULL OR reach_meters IS NULL OR
wavelength_tx_nm IS NULL OR connector_type IS NULL
),
enrichment_fields = ARRAY_REMOVE(ARRAY[
CASE WHEN form_factor IS NULL THEN 'form_factor' END,
CASE WHEN speed_gbps IS NULL THEN 'speed_gbps' END,
CASE WHEN fiber_type IS NULL THEN 'fiber_type' END,
CASE WHEN reach_meters IS NULL OR reach_meters = 0 THEN 'reach_meters' END,
CASE WHEN wavelength_tx_nm IS NULL THEN 'wavelength_tx_nm' END,
CASE WHEN connector_type IS NULL THEN 'connector_type' END
], NULL);
-- ── Statistik ────────────────────────────────────────────────────────────────
DO $$
DECLARE
total_cnt INTEGER;
complete_cnt INTEGER;
missing_conn INTEGER;
missing_wl INTEGER;
fx_complete INTEGER;
BEGIN
SELECT COUNT(*) INTO total_cnt FROM transceivers;
SELECT COUNT(*) INTO complete_cnt FROM transceivers WHERE enrichment_needed = FALSE;
SELECT COUNT(*) INTO missing_conn FROM transceivers WHERE connector_type IS NULL;
SELECT COUNT(*) INTO missing_wl FROM transceivers WHERE wavelength_tx_nm IS NULL;
SELECT COUNT(*) INTO fx_complete
FROM transceivers t JOIN vendors v ON v.id = t.vendor_id
WHERE UPPER(v.name) LIKE '%FLEXOPTIX%' AND enrichment_needed = FALSE;
RAISE NOTICE 'Migration 113 complete:';
RAISE NOTICE ' Total transceivers: %', total_cnt;
RAISE NOTICE ' Fully complete: %', complete_cnt;
RAISE NOTICE ' Still missing connector: %', missing_conn;
RAISE NOTICE ' Still missing wavelength: %', missing_wl;
RAISE NOTICE ' Flexoptix fully complete: %', fx_complete;
END $$;