1.0.553.sql 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. -- ============================================================================
  2. -- 1.0.553 · 补 mdp_inbound_grant 缺失的唯一键 uk_inbound_grant(access_key, entity_code)
  3. --
  4. -- 背景:1.0.536 里这张表是 CREATE TABLE IF NOT EXISTS。在 1.0.536 正式执行之前,
  5. -- 该表已被某个实例的 SqlSugar CodeFirst 抢先建出(CodeFirst 在容器初始化阶段跑,
  6. -- 早于 UseAutoVersionUpdate 中间件),于是 1.0.536 的建表语句整条 no-op,
  7. -- 脚本里声明的 UNIQUE KEY 从未落地。实测证据:该表无任何 COLUMN COMMENT、
  8. -- 无 DEFAULT,status 是 int 而非脚本声明的 tinyint —— 全是 CodeFirst 产物特征。
  9. --
  10. -- 为什么必须补:mdp_inbound_grant 是第三方推数入站的授权表。
  11. -- (access_key, entity_code) 是它的业务身份:同一凭证对同一实体只应有一条授权。
  12. -- 缺了这个唯一键,重复授权行可以写进去,而入站鉴权按该组合查授权,
  13. -- 出现两条就意味着限流配额、IP 白名单、batch 上限到底以哪条为准是不确定的。
  14. --
  15. -- 本脚本只做这一件事。刻意不碰 status 的类型与 DEFAULT、不碰其余四张 inbound 表 ——
  16. -- 那些是等价差异,不影响业务语义,混在一起改会让这次热修的回滚面无谓扩大。
  17. --
  18. -- 幂等与安全:
  19. -- · 索引不存在 → 创建
  20. -- · 已存在且定义正确 → no-op
  21. -- · 同名但定义不对 → SIGNAL 中止,绝不 DROP 重建(可能是别人有意改过)
  22. -- · 存在重复数据 → SIGNAL 中止(加唯一键会失败,提前给出可读原因)
  23. --
  24. -- AutoVersionUpdate 按分号拆句、无事务,故全部用 PREPARE/EXECUTE 自包含,
  25. -- 且注释内不出现会被 parser 误切的分号模式。
  26. -- ============================================================================
  27. -- ── 前置门禁 1:不能有重复数据,否则加唯一键必然失败 ────────────────────────
  28. SET @dup_groups := (
  29. SELECT COUNT(*) FROM (
  30. SELECT 1 FROM `mdp_inbound_grant` GROUP BY `access_key`, `entity_code` HAVING COUNT(*) > 1
  31. ) d
  32. );
  33. SET @sql := IF(@dup_groups <> 0,
  34. "SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '1.0.553-G1: mdp_inbound_grant 存在重复 (access_key, entity_code),无法建唯一键 — 先人工裁决保留哪条'",
  35. 'DO 0');
  36. PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
  37. -- ── 前置门禁 2:同名索引若已存在,定义必须完全正确,否则中止 ────────────────
  38. SET @idx_cols := (
  39. SELECT GROUP_CONCAT(`COLUMN_NAME` ORDER BY `SEQ_IN_INDEX` SEPARATOR ',')
  40. FROM information_schema.`STATISTICS`
  41. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'mdp_inbound_grant'
  42. AND `INDEX_NAME` = 'uk_inbound_grant'
  43. );
  44. SET @idx_unique := (
  45. SELECT MIN(`NON_UNIQUE`) FROM information_schema.`STATISTICS`
  46. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'mdp_inbound_grant'
  47. AND `INDEX_NAME` = 'uk_inbound_grant'
  48. );
  49. SET @sql := IF(@idx_cols IS NOT NULL
  50. AND (@idx_cols <> 'access_key,entity_code' OR @idx_unique <> 0),
  51. "SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '1.0.553-G2: uk_inbound_grant 已存在但定义不符预期 — 中止,不自动 DROP 重建'",
  52. 'DO 0');
  53. PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
  54. -- ── 主体:不存在才创建 ──────────────────────────────────────────────────────
  55. SET @sql := IF(@idx_cols IS NULL,
  56. 'ALTER TABLE `mdp_inbound_grant` ADD UNIQUE KEY `uk_inbound_grant` (`access_key`, `entity_code`)',
  57. 'DO 0');
  58. PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
  59. -- ── 结果断言:执行完必须存在且定义正确 ──────────────────────────────────────
  60. SET @after_cols := (
  61. SELECT GROUP_CONCAT(`COLUMN_NAME` ORDER BY `SEQ_IN_INDEX` SEPARATOR ',')
  62. FROM information_schema.`STATISTICS`
  63. WHERE `TABLE_SCHEMA` = DATABASE() AND `TABLE_NAME` = 'mdp_inbound_grant'
  64. AND `INDEX_NAME` = 'uk_inbound_grant' AND `NON_UNIQUE` = 0
  65. );
  66. SET @sql := IF(IFNULL(@after_cols, '') <> 'access_key,entity_code',
  67. "SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '1.0.553-A1: uk_inbound_grant 建后校验失败'",
  68. 'DO 0');
  69. PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
  70. SELECT @after_cols AS uk_inbound_grant_columns;