-- OBMP analytics materialized views
--
-- Applied to the live database and version-controlled here for reproducibility.
-- Safe to run against an empty database at init time: the view is created empty
-- and the pg_cron job below populates/refreshes it hourly.

-- AS adjacency: every undirected pair of consecutive ASes in an observed AS_PATH,
-- with an occurrence count. Backs the AS Relationship Map dashboard so its panels
-- read a 17k-row view instead of exploding ~4.4M base_attrs rows live.
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_as_adjacency AS
SELECT LEAST(a.asn, b.asn)    AS asn_a,
       GREATEST(a.asn, b.asn) AS asn_b,
       COUNT(*)               AS occ
FROM base_attrs ba
CROSS JOIN LATERAL unnest(ba.as_path) WITH ORDINALITY a(asn, ord)
JOIN       LATERAL unnest(ba.as_path) WITH ORDINALITY b(asn, ord) ON b.ord = a.ord + 1
WHERE ba.as_path_count >= 2 AND a.asn <> b.asn
GROUP BY 1, 2;

-- Unique index required for REFRESH ... CONCURRENTLY (no read lock during refresh).
CREATE UNIQUE INDEX IF NOT EXISTS mv_as_adjacency_pair_idx ON mv_as_adjacency (asn_a, asn_b);
CREATE INDEX IF NOT EXISTS mv_as_adjacency_occ_idx ON mv_as_adjacency (occ DESC);

-- Refresh hourly at minute 23.
SELECT cron.schedule('refresh-mv-as-adjacency', '23 * * * *',
                     'REFRESH MATERIALIZED VIEW CONCURRENTLY mv_as_adjacency');
