1.0.544.verify.sql 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. -- 1.0.544.verify.sql — HARD ASSERTIONS,每条 SELECT 都必须返回 1
  2. --
  3. -- ⚠️ AutoVersionUpdate 按分号切分本文件,并把【每一个切片】都当断言、要求返回 1。因此:
  4. -- ① 不得放"仅供排查"的 informational 查询
  5. -- ② 文件必须以最后一条断言的分号结尾,末尾不能留纯注释块
  6. -- ③ 注释里不得出现任何字面分号
  7. --
  8. -- 口径:只断言本批 Writer 独占产出的 mdp_std_purchase_order_completion。
  9. -- 结构断言迁移后即可全过;数据断言在表为空时也成立,Writer 跑过之后才真正有判别力。
  10. -- ── ① 表与 Canonical 唯一键就位 ─────────────────────────────────────────────────────
  11. SELECT (SELECT COUNT(*) FROM `information_schema`.`TABLES`
  12. WHERE `TABLE_SCHEMA` = DATABASE()
  13. AND `TABLE_NAME` = 'mdp_std_purchase_order_completion') = 1;
  14. SELECT (SELECT GROUP_CONCAT(`COLUMN_NAME` ORDER BY `SEQ_IN_INDEX`)
  15. FROM `information_schema`.`STATISTICS`
  16. WHERE `TABLE_SCHEMA` = DATABASE()
  17. AND `TABLE_NAME` = 'mdp_std_purchase_order_completion'
  18. AND `INDEX_NAME` = 'uk_mdp_std_po_completion') = 'tenant_id,po_no,po_line';
  19. -- ①b provenance 列绝不得混进业务唯一键
  20. SELECT (SELECT COUNT(*) FROM `information_schema`.`STATISTICS`
  21. WHERE `TABLE_SCHEMA` = DATABASE()
  22. AND `TABLE_NAME` = 'mdp_std_purchase_order_completion'
  23. AND `INDEX_NAME` = 'uk_mdp_std_po_completion'
  24. AND `COLUMN_NAME` IN ('domain','source_row_id','source_id','potype')) = 0;
  25. -- ── ② Canonical 无重复:一条采购行只能一行 ──────────────────────────────────────────
  26. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`) =
  27. (SELECT COUNT(DISTINCT `tenant_id`, `po_no`, `po_line`)
  28. FROM `mdp_std_purchase_order_completion`);
  29. -- ── ③ 租户合法:绝不落无主 Fact ─────────────────────────────────────────────────────
  30. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  31. WHERE `tenant_id` IS NULL OR `tenant_id` <= 0) = 0;
  32. -- ── ④ completion_status 取值域封闭 ──────────────────────────────────────────────────
  33. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  34. WHERE `completion_status` NOT IN ('COMPLETED','NOT_COMPLETED','UNKNOWN')) = 0;
  35. -- ── ⑤ 映射必须严格由 raw_status 派生 ────────────────────────────────────────────────
  36. -- ⑤a raw_status 不是 'C' 就绝不能是 COMPLETED(IFNULL 是必需的,NULL 比较不会为真)
  37. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  38. WHERE `completion_status` = 'COMPLETED'
  39. AND IFNULL(`raw_status`, '#') <> 'C') = 0;
  40. -- ⑤b raw_status='C' 必须 COMPLETED
  41. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  42. WHERE `raw_status` = 'C' AND `completion_status` <> 'COMPLETED') = 0;
  43. -- ⑤c raw_status 为空串必须 NOT_COMPLETED
  44. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  45. WHERE `raw_status` = '' AND `completion_status` <> 'NOT_COMPLETED') = 0;
  46. -- ⑤d raw_status 为 NULL 绝不能滑成 NOT_COMPLETED —— 未知不得当未完成
  47. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  48. WHERE `raw_status` IS NULL AND `completion_status` <> 'UNKNOWN') = 0;
  49. -- ⑤e 既非 'C' 也非空串的已知值一律 UNKNOWN
  50. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  51. WHERE `raw_status` IS NOT NULL AND `raw_status` NOT IN ('C','')
  52. AND `completion_status` <> 'UNKNOWN') = 0;
  53. -- ── ⑥ provenance 必须完整:Fact 只能由实际观测到的 Source B 行产生 ──────────────────
  54. -- 由 Source A 反向捏造的行拿不到 source_row_id,本条即是 NOT_OBSERVED 不得物化的结构守卫
  55. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion`
  56. WHERE IFNULL(`source_system`, '') = ''
  57. OR IFNULL(`source_row_id`, '') = ''
  58. OR `observed_at` IS NULL
  59. OR IFNULL(`sync_batch_id`, '') = '') = 0;
  60. -- ⑥b source_system 必须是已登记且启用的数据源
  61. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion` c
  62. WHERE NOT EXISTS (SELECT 1 FROM `mdp_source` s
  63. WHERE s.`source_code` = c.`source_system`
  64. AND s.`status` = 1)) = 0;
  65. -- ── ⑦ 每条 Fact 必须同租户命中唯一的本地采购行 ──────────────────────────────────────
  66. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion` c
  67. WHERE NOT EXISTS (SELECT 1 FROM `mdp_std_purchase_order` o
  68. WHERE o.`tenant_id` = c.`tenant_id`
  69. AND o.`po_no` = c.`po_no`
  70. AND o.`po_line` = c.`po_line`)) = 0;
  71. -- ⑦b 禁止跨租户错配:同一 (po_no, po_line) 不得在 Fact 与本地 PO 之间分属不同租户
  72. SELECT (SELECT COUNT(*) FROM `mdp_std_purchase_order_completion` c
  73. JOIN `mdp_std_purchase_order` o
  74. ON o.`po_no` = c.`po_no` AND o.`po_line` = c.`po_line`
  75. WHERE o.`tenant_id` <> c.`tenant_id`) = 0;
  76. -- ── ⑧ 本批不得引入完成时间列 —— 当前无权威 ──────────────────────────────────────────
  77. SELECT (SELECT COUNT(*) FROM `information_schema`.`COLUMNS`
  78. WHERE `TABLE_SCHEMA` = DATABASE()
  79. AND `TABLE_NAME` = 'mdp_std_purchase_order_completion'
  80. AND `COLUMN_NAME` IN ('completion_time','completed_at','procurement_completion_time')) = 0;
  81. -- ── ⑨ 本批不得建 Stage-3 聚合 / Read Model ──────────────────────────────────────────
  82. SELECT (SELECT COUNT(*) FROM `information_schema`.`TABLES`
  83. WHERE `TABLE_SCHEMA` = DATABASE()
  84. AND `TABLE_NAME` IN ('mdp_std_stage3_completion','dwd_stage3_completion',
  85. 'dwd_procurement_completion')) = 0;
  86. -- ── ⑩ 上游批次资产不得回归 ──────────────────────────────────────────────────────────
  87. -- 1.0.541:IQC 标准事实层仍在且 Grain 未被改动
  88. SELECT (SELECT GROUP_CONCAT(`COLUMN_NAME` ORDER BY `SEQ_IN_INDEX`)
  89. FROM `information_schema`.`STATISTICS`
  90. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'mdp_std_iqc_inspection'
  91. AND `INDEX_NAME` = 'uk_mdp_std_iqc_insp') = 'tenant_id,source_row_id';
  92. -- 1.0.540:分录上的采购单号列仍在且仍可空
  93. SELECT (SELECT COUNT(*) FROM `information_schema`.`COLUMNS`
  94. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'qms_qcp_insappnentry'
  95. AND `COLUMN_NAME` = 'purchase_order_no' AND `IS_NULLABLE` = 'YES') = 1;
  96. -- Source A 基础事实的唯一键不得被本批改动
  97. SELECT (SELECT GROUP_CONCAT(`COLUMN_NAME` ORDER BY `SEQ_IN_INDEX`)
  98. FROM `information_schema`.`STATISTICS`
  99. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'mdp_std_purchase_order'
  100. AND `INDEX_NAME` = 'uk_po_line') = 'tenant_id,po_no,po_line';