-- ============================================================================
-- S6-DISPLAY-FIX-B1 · D-04 存量订正：mdp_std_ipqc_inspection 字面量 'null' → SQL NULL
--
-- 背景（根因已在同批代码修复）：
--   IpqcInspectionMdpSyncService.TransformHeadStandardAsync 原先对字符串列使用裸
--   JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.x'))。MySQL 下 JSON null 经 JSON_UNQUOTE
--   会产出**长度为 4 的字面量字符串 'null'**（实测：其 IS NULL = 0），
--   于是 API 返回 "formNo":"null"，前端 `|| '-'` 兜底对真值字符串无效，页面直接显示 null。
--   同文件的 detail transform 因使用 MdpJsonSql.Str()（= NULLIF(...,'null')）从未受影响。
--   代码侧已改为统一走 MdpJsonSql.Str/Dec/DateTimeSec，此后不再产生新污染；
--   本脚本只订正**已经落库的存量**。
--
-- 证据（aidopdev，2026-09-02 只读取证）：
--   ① 受影响 10 列，7/8 行命中（form_no / version_no / inspec_standard_code /
--      inspec_standard_version / production_person / attachment 各 7 行，remark 3 行，
--      process_code / process_name / production_work_order 各 2 行）。
--   ② 逐行 JOIN 回源表 qms_gcjyd 证明：凡 STD 为 'null' 者，其源列**均为 SQL NULL**，
--      不存在"业务真的存了文本 null"的反例。
--   ③ 全表扫描 qms_gcjyd 的 17 个对应源列，**没有任何一列持有字面量文本 'null'**。
--   故 'null' 100% 来自转换污染，可安全归一为 SQL NULL。
--
-- 写入范围（INSERT 0 · UPDATE ≤8 行 · DELETE 0 · DDL 0）：
--   表：mdp_std_ipqc_inspection（仅标准层，不碰任何业务源表）
--   列白名单（10 列，均为可空展示列；不含 NOT NULL 列，不含身份键）：
--     attachment, form_no, inspec_standard_code, inspec_standard_version,
--     process_code, process_name, production_person, production_work_order,
--     remark, version_no
--   行范围：仅限**能回溯到源单**的行（EXISTS qms_gcjyd 同 id 同 tenant_id）。
--
-- 刻意不处理（无法自证，遵循"证明不了就不清洗"）：
--   2 行孤儿 STD（source_row_id 在 qms_gcjyd 无对应行）——
--   id=22（source_system=WMS_API 契约测试夹具，tenant 1300000000001）与
--   id=32（tenant_id=0，本身即已知脏行）。
--   这两行的贴源记录仍在 mdp_stg_ipqc_pull 中，**下一次 inbound 会由已修复的转换代码
--   自动 upsert 订正**，无需在此强行 UPDATE。
--
-- 幂等：WHERE col='null' 决定重复执行为 0 行影响。
-- 回滚：本操作把污染值归一为源真值(NULL)，属**数据订正而非数据变更**，不提供反向脚本
--       （反向写回 'null' 只会复原缺陷）。如确需还原，可对同一行集执行
--       UPDATE ... SET col='null' WHERE col IS NULL，但需先确认该列源值确为 NULL。
-- ============================================================================

-- ── 执行前计数（期望：与上文证据一致）──
SELECT 'BEFORE' AS phase,
       SUM(attachment              = 'null') AS attachment,
       SUM(form_no                 = 'null') AS form_no,
       SUM(inspec_standard_code    = 'null') AS inspec_standard_code,
       SUM(inspec_standard_version = 'null') AS inspec_standard_version,
       SUM(process_code            = 'null') AS process_code,
       SUM(process_name            = 'null') AS process_name,
       SUM(production_person       = 'null') AS production_person,
       SUM(production_work_order   = 'null') AS production_work_order,
       SUM(remark                  = 'null') AS remark,
       SUM(version_no              = 'null') AS version_no
FROM mdp_std_ipqc_inspection;

-- ── 订正：仅可回溯到源单的行，且仅当该列恰为字面量 'null' ──
UPDATE mdp_std_ipqc_inspection m
SET m.attachment              = NULLIF(m.attachment,              'null'),
    m.form_no                 = NULLIF(m.form_no,                 'null'),
    m.inspec_standard_code    = NULLIF(m.inspec_standard_code,    'null'),
    m.inspec_standard_version = NULLIF(m.inspec_standard_version, 'null'),
    m.process_code            = NULLIF(m.process_code,            'null'),
    m.process_name            = NULLIF(m.process_name,            'null'),
    m.production_person       = NULLIF(m.production_person,       'null'),
    m.production_work_order   = NULLIF(m.production_work_order,   'null'),
    m.remark                  = NULLIF(m.remark,                  'null'),
    m.version_no              = NULLIF(m.version_no,              'null')
WHERE EXISTS (
        SELECT 1 FROM qms_gcjyd s
        WHERE s.id = m.source_row_id AND s.tenant_id = m.tenant_id
      )
  AND (m.attachment = 'null' OR m.form_no = 'null'
    OR m.inspec_standard_code = 'null' OR m.inspec_standard_version = 'null'
    OR m.process_code = 'null' OR m.process_name = 'null'
    OR m.production_person = 'null' OR m.production_work_order = 'null'
    OR m.remark = 'null' OR m.version_no = 'null');

-- ── 执行后计数（期望：可回溯行全部归零；仅可能残留上文声明的 2 行孤儿）──
SELECT 'AFTER' AS phase,
       SUM(attachment              = 'null') AS attachment,
       SUM(form_no                 = 'null') AS form_no,
       SUM(inspec_standard_code    = 'null') AS inspec_standard_code,
       SUM(inspec_standard_version = 'null') AS inspec_standard_version,
       SUM(process_code            = 'null') AS process_code,
       SUM(process_name            = 'null') AS process_name,
       SUM(production_person       = 'null') AS production_person,
       SUM(production_work_order   = 'null') AS production_work_order,
       SUM(remark                  = 'null') AS remark,
       SUM(version_no              = 'null') AS version_no
FROM mdp_std_ipqc_inspection;
