← back to Newmor Onboard

scripts/merge-v2-REAL-RUN.sql

95 lines

-- TK-10670 REAL-RUN MERGE (in-place on canonical newmor_catalog), keyed by id.
-- Decisions locked 2026-09-14: #1 NEW dw_sku=NULL (mint later), #2 ABSENT flag-only (no Shopify cascade),
-- #3 keep bare-color mfr_sku, #4 GO. Snapshot rollback anchor: newmor_catalog_snap_20260909.
-- DRY by default (ROLLBACK). Real run: psql -v apply=1. Mirrors merge-v2-into-canonical.sql logic exactly.
\set ON_ERROR_STOP on
\if :{?apply}
\else
  \set apply 0
\endif
BEGIN;

-- GUARD: snapshot rollback-anchor must exist and equal 1294, else abort.
DO $$
DECLARE snap int;
BEGIN
  SELECT count(*) INTO snap FROM newmor_catalog_snap_20260909;
  IF snap <> 1294 THEN RAISE EXCEPTION 'ABORT: snapshot anchor missing/wrong (% != 1294)', snap; END IF;
END $$;

-- key mapping for canonical rows (id -> mkey), no column added to the real table
DROP TABLE IF EXISTS _km;
CREATE TEMP TABLE _km AS
SELECT id, CASE WHEN mfr_sku ~ '[0-9]'
  THEN 'C:'||upper(regexp_replace(mfr_sku,'[^A-Za-z0-9]','','g'))
  ELSE 'N:'||upper(regexp_replace(pattern_name,'[^A-Za-z0-9]','','g'))||'|'||upper(regexp_replace(coalesce(color_name,''),'[^A-Za-z0-9]','','g')) END AS mkey
FROM newmor_catalog;

-- v2 keyed + deduped (one row per mkey; prefer most-complete)
DROP TABLE IF EXISTS _v2;
CREATE TEMP TABLE _v2 AS
SELECT * FROM (
  SELECT *,
    CASE WHEN mfr_sku ~ '[0-9]' AND code_source='vendor_code'
      THEN 'C:'||upper(regexp_replace(mfr_sku,'[^A-Za-z0-9]','','g'))
      ELSE 'N:'||upper(regexp_replace(pattern_name,'[^A-Za-z0-9]','','g'))||'|'||upper(regexp_replace(coalesce(color_name,''),'[^A-Za-z0-9]','','g')) END AS mkey,
    row_number() OVER (PARTITION BY (CASE WHEN mfr_sku ~ '[0-9]' AND code_source='vendor_code'
      THEN 'C:'||upper(regexp_replace(mfr_sku,'[^A-Za-z0-9]','','g'))
      ELSE 'N:'||upper(regexp_replace(pattern_name,'[^A-Za-z0-9]','','g'))||'|'||upper(regexp_replace(coalesce(color_name,''),'[^A-Za-z0-9]','','g')) END)
      ORDER BY (CASE WHEN image_url<>'' THEN 1 ELSE 0 END + CASE WHEN color_name<>'' THEN 1 ELSE 0 END) DESC) rn
  FROM newmor_catalog_refresh_20260909_v2
) q WHERE rn=1;

DROP TABLE IF EXISTS _pre; CREATE TEMP TABLE _pre AS
  SELECT count(*) n, count(dw_sku) FILTER (WHERE dw_sku<>'') dwsku FROM newmor_catalog;

-- OP1 MATCHED: update raw fields only; discontinued=false
UPDATE newmor_catalog t SET
  pattern_name=v.pattern_name, color_name=v.color_name, collection=v.collection,
  product_type=v.product_type, width=v.width, length=v.length, repeat_v=v.repeat_v,
  image_url=v.image_url, product_url=v.product_url, in_stock=v.in_stock, material=v.material,
  match_type=v.match_type, last_scraped=now(), updated_at=now(), discontinued=false
FROM _v2 v, _km k WHERE k.id=t.id AND k.mkey=v.mkey;

-- OP2 ABSENT: flag discontinued=true; touch nothing else
UPDATE newmor_catalog t SET discontinued=true, updated_at=now()
FROM _km k WHERE k.id=t.id AND k.mkey NOT IN (SELECT mkey FROM _v2);

-- fix id sequence (last_value was behind max(id) -> would collide on INSERT)
SELECT setval('newmor_catalog_id_seq', (SELECT max(id) FROM newmor_catalog));

-- OP3 NEW: insert raw fields; dw_sku NULL (minting stays gated). No mkey column on real table.
INSERT INTO newmor_catalog (mfr_sku, pattern_name, color_name, collection, product_type, width, length,
  repeat_v, image_url, product_url, in_stock, material, match_type,
  last_scraped, created_at, updated_at, discontinued, dw_sku)
SELECT v.mfr_sku, v.pattern_name, v.color_name, v.collection, v.product_type, v.width, v.length,
  v.repeat_v, v.image_url, v.product_url, v.in_stock, v.material, v.match_type,
  now(), now(), now(), false, NULL
FROM _v2 v WHERE v.mkey NOT IN (SELECT mkey FROM _km);

-- PROOF
SELECT 'pre_rows' lbl, n::text val FROM _pre
UNION ALL SELECT 'pre_dwsku',       dwsku::text FROM _pre
UNION ALL SELECT 'post_rows',       count(*)::text FROM newmor_catalog
UNION ALL SELECT 'post_dwsku',      (count(dw_sku) FILTER (WHERE dw_sku<>''))::text FROM newmor_catalog
UNION ALL SELECT 'flagged_discont', (count(*) FILTER (WHERE discontinued))::text FROM newmor_catalog
UNION ALL SELECT 'new_dwsku_null',  (count(*) FILTER (WHERE dw_sku IS NULL))::text FROM newmor_catalog;

-- ASSERTS: dw_sku preserved, no deletes, post_rows == 1594
DO $$
DECLARE pre_dw int; post_dw int; pre_n int; post_n int;
BEGIN
  SELECT dwsku,n INTO pre_dw,pre_n FROM _pre;
  SELECT count(*) FILTER (WHERE dw_sku<>''), count(*) INTO post_dw,post_n FROM newmor_catalog;
  IF post_dw < pre_dw THEN RAISE EXCEPTION 'ASSERT FAIL: dw_sku dropped % -> %', pre_dw, post_dw; END IF;
  IF post_n < pre_n THEN RAISE EXCEPTION 'ASSERT FAIL: rows deleted % -> %', pre_n, post_n; END IF;
  IF post_n <> 1594 THEN RAISE EXCEPTION 'ASSERT FAIL: expected 1594 rows, got %', post_n; END IF;
  RAISE NOTICE 'ASSERTS PASS: rows %->%  dw_sku %->% (preserved)', pre_n, post_n, pre_dw, post_dw;
END $$;

\if :apply
COMMIT;
\else
ROLLBACK;
\endif