Browse Source

fix(backend): meal_configs 唯一键改用生成列 config_date_eff 修复 COALESCE 索引语法

MySQL 8.0.34 不支持在索引定义中使用 COALESCE() 函数表达式,
迁移314 的 UNIQUE KEY uk_config (family_id, COALESCE(config_date, ...)) 每次启动都报语法错误,
导致唯一约束从未建立, 存在重复共餐配置风险。

改为 STORED 生成列 config_date_eff (COALESCE(config_date, '9999-12-31')) 承载相同语义,
唯一键建立在生成列上, 同时补齐缺失的 idx_config_date 索引。
Xiaogang Liao 1 month ago
parent
commit
2485177021

+ 13 - 1
cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java

@@ -10886,6 +10886,12 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
         } catch (Exception e) {
             log.warn("迁移314: meal_configs 添加 config_date 列失败(可能已存在): {}", e.getMessage());
         }
+        try {
+            jdbcTemplate.execute("ALTER TABLE meal_configs ADD COLUMN config_date_eff DATE GENERATED ALWAYS AS (COALESCE(config_date, '9999-12-31')) STORED COMMENT '生效日期(NULL映射为9999-12-31,用于唯一约束)'");
+            log.info("迁移314: meal_configs 已添加生成列 config_date_eff");
+        } catch (Exception e) {
+            log.warn("迁移314: meal_configs 添加 config_date_eff 生成列失败(可能已存在): {}", e.getMessage());
+        }
         try {
             jdbcTemplate.execute("ALTER TABLE meal_configs DROP INDEX uk_config");
             log.info("迁移314: meal_configs 已删除旧 UNIQUE KEY uk_config");
@@ -10893,11 +10899,17 @@ log.info("迁移298: 已为无 openid 的 child 账号补齐 family_members 记
             log.warn("迁移314: 删除旧 UNIQUE KEY 失败(可能不存在): {}", e.getMessage());
         }
         try {
-            jdbcTemplate.execute("ALTER TABLE meal_configs ADD UNIQUE KEY uk_config (family_id, COALESCE(config_date, '9999-12-31'), meal_type)");
+            jdbcTemplate.execute("ALTER TABLE meal_configs ADD UNIQUE KEY uk_config (family_id, config_date_eff, meal_type)");
             log.info("迁移314: meal_configs 已添加新 UNIQUE KEY uk_config(支持当天临时配置)");
         } catch (Exception e) {
             log.warn("迁移314: 添加新 UNIQUE KEY 失败: {}", e.getMessage());
         }
+        try {
+            jdbcTemplate.execute("ALTER TABLE meal_configs ADD INDEX idx_config_date (config_date)");
+            log.info("迁移314: meal_configs 已添加索引 idx_config_date");
+        } catch (Exception e) {
+            log.warn("迁移314: meal_configs 添加索引 idx_config_date 失败(可能已存在): {}", e.getMessage());
+        }
 
 // 迁移315: membership_levels 新增 BASIC 体验会员等级(9.9元/月)
         try {

+ 2 - 1
cfc-backend/src/main/resources/schema.sql

@@ -4626,12 +4626,13 @@ CREATE TABLE IF NOT EXISTS meal_configs (
     family_id BIGINT NOT NULL COMMENT '家庭ID',
     config_date_type VARCHAR(20) NOT NULL COMMENT '工作日/周末/节假日',
     config_date DATE DEFAULT NULL COMMENT '当天临时配置日期(NULL=默认工作日/周末配置)',
+    config_date_eff DATE GENERATED ALWAYS AS (COALESCE(config_date, '9999-12-31')) STORED COMMENT '生效日期(NULL映射为9999-12-31,用于唯一约束)',
     meal_type VARCHAR(20) NOT NULL COMMENT 'breakfast/lunch/dinner',
     participant_member_ids JSON NOT NULL COMMENT '参与成员ID列表',
     notes VARCHAR(255) DEFAULT NULL COMMENT '备注',
     created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
     updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    UNIQUE KEY uk_config (family_id, COALESCE(config_date, '9999-12-31'), meal_type),
+    UNIQUE KEY uk_config (family_id, config_date_eff, meal_type),
     INDEX idx_family (family_id),
     INDEX idx_config_date (config_date)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='共餐配置表';