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