fix: 补齐不完整的 v9 商品约束 (#144)

This commit is contained in:
chengma
2026-08-11 11:30:08 +08:00
parent edb835a9ed
commit 9671202f4e
4 changed files with 17 additions and 9 deletions
+5 -2
View File
@@ -547,13 +547,16 @@ func MigrateMySQL(db *sql.DB) error {
return CheckMySQLSchema(db) return CheckMySQLSchema(db)
} }
// migrateMySQLV10 修复曾在 v8 开发中间状态记录过版本的数据库。 // migrateMySQLV10 修复曾在 v8/v9 开发中间状态记录过版本的数据库。
// v8 迁移本身逐项检查列和索引且回填只处理空值,因此可安全重放; // 两版迁移均逐项检查结构,v8 回填只处理空值,因此可安全重放;
// 历史 v8/v9 版本记录保持不变,完整自检通过后再追加 v10。 // 历史 v8/v9 版本记录保持不变,完整自检通过后再追加 v10。
func migrateMySQLV10(db *sql.DB) error { func migrateMySQLV10(db *sql.DB) error {
if err := migrateMySQLV8(db); err != nil { if err := migrateMySQLV8(db); err != nil {
return fmt.Errorf("修复商品目录 SKU v8 结构失败: %w", err) return fmt.Errorf("修复商品目录 SKU v8 结构失败: %w", err)
} }
if err := migrateMySQLV9(db); err != nil {
return fmt.Errorf("修复蝦皮商品 v9 结构失败: %w", err)
}
return nil return nil
} }
@@ -468,7 +468,7 @@ func TestMySQLMigrate_V9形状错误不记版本(t *testing.T) {
} }
} }
func TestMySQLMigrate_已记录V9但缺少SKU来源字段时由V10修复(t *testing.T) { func TestMySQLMigrate_已记录V9但缺少V8V9结构时由V10修复(t *testing.T) {
db := openMySQLMigrationTestDB(t) db := openMySQLMigrationTestDB(t)
defer db.Close() defer db.Close()
cleanMySQLTestSchema(t, db) cleanMySQLTestSchema(t, db)
@@ -486,6 +486,9 @@ func TestMySQLMigrate_已记录V9但缺少SKU来源字段时由V10修复(t *test
if err := migrateMySQLV9(db); err != nil { if err := migrateMySQLV9(db); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// 同时模拟 v9 已记录但两个图片/店铺人工标记约束尚未建立。
mustExec(t, db, `ALTER TABLE shopee_products DROP CHECK chk_shopee_products_image_manual`)
mustExec(t, db, `ALTER TABLE shopee_products DROP CHECK chk_shopee_products_shop_manual`)
mustExec(t, db, `INSERT INTO schema_migrations(version,applied_at) VALUES mustExec(t, db, `INSERT INTO schema_migrations(version,applied_at) VALUES
(8,'2026-08-11T00:00:00Z'),(9,'2026-08-11T00:00:00Z')`) (8,'2026-08-11T00:00:00Z'),(9,'2026-08-11T00:00:00Z')`)
+4 -3
View File
@@ -445,9 +445,10 @@ MySQL schema v9 为 `shopee_products` 增加 `image_url` 和 `shopee_shop_name`
商品主图,与 `syb_orders.image_url` 的历史货运单观测图片是两个独立概念。 商品主图,与 `syb_orders.image_url` 的历史货运单观测图片是两个独立概念。
MySQL schema v10(工单 #144)是兼容修复:部分数据库曾在 v8 开发中间状态提前记录 MySQL schema v10(工单 #144)是兼容修复:部分数据库曾在 v8 开发中间状态提前记录
v8/v9,实际缺少 `field_sources` 或 `field_observed_at`。v10 幂等重放 v8 的逐项建列、 v8/v9,实际缺少 `field_sources`、`field_observed_at` 或 v9 图片/店铺人工标记约束。
空值回填和唯一索引逻辑,再核对 v8/v9 完整形状;只有全部通过才记录 v10。它不删除 v10 幂等重放 v8、v9 的逐项建列、空值回填、约束和唯一索引逻辑,再核对两版完整
或改写旧迁移记录,也不清空商品、SKU 或导入记录。 形状;只有全部通过才记录 v10。它不删除或改写旧迁移记录,也不清空商品、SKU 或
导入记录。
蝦皮详情把 `syb_orders` 按 `(shopee_goods_id, spec_key)` 聚合为“顺运宝观测规格”: 蝦皮详情把 `syb_orders` 按 `(shopee_goods_id, spec_key)` 聚合为“顺运宝观测规格”:
订单数按唯一 `syb_id` 行计数,累计数量求和,最近一行提供历史台币售价和图片。 订单数按唯一 `syb_id` 行计数,累计数量求和,最近一行提供历史台币售价和图片。
+4 -3
View File
@@ -93,9 +93,10 @@ HTTP/HTTPS URL,最长 2048 字节;店铺名最长 500 个字符。Admin 只
迁移只增加列和唯一索引,既有 `sku_id` 继续作为内部主键,因此历史引用不变;若检测 迁移只增加列和唯一索引,既有 `sku_id` 继续作为内部主键,因此历史引用不变;若检测
到同商品重复 `spec_key`,迁移会停止且不记录 v8,必须人工确认,不能自动合并。 到同商品重复 `spec_key`,迁移会停止且不记录 v8,必须人工确认,不能自动合并。
若数据库已经记录 v8 或 v9,但缺少 `field_sources`、`field_observed_at` 等后加入的 若数据库已经记录 v8 或 v9,但缺少 `field_sources`、`field_observed_at` 等 v8 结构,
v8 结构,v10 会自动补齐并只回填空值。不要通过删除迁移版本、清库或手工伪造字段来 或缺少图片、店铺人工标记约束等 v9 结构,v10 会幂等重放两版迁移并只回填空值。
绕过自检;修复完成且 v8/v9 形状均正确后,程序才会记录 v10。 不要通过删除迁移版本、清库或手工伪造结构来绕过自检;修复完成且 v8/v9 形状均
正确后,程序才会记录 v10。
旧版 Admin 不理解无真实 SKU ID 的新记录。应用回退前应暂停目录接口并确认没有此类 旧版 Admin 不理解无真实 SKU ID 的新记录。应用回退前应暂停目录接口并确认没有此类
记录;不要删除 v8 列或把内部主键复制成伪造的外部 SKU ID。 记录;不要删除 v8 列或把内部主键复制成伪造的外部 SKU ID。