Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a14b154a3c |
+27
-2
@@ -142,12 +142,18 @@ func InitDB(cfg *config.Config) *gorm.DB {
|
||||
// files 表,type 一律标记为 "attachments"。仅当 attachments 表仍存在时
|
||||
// 执行——新安装从未创建过该表,而已经切换的部署会将其删除。
|
||||
//
|
||||
// 幂等策略:以主键 id 对齐——files 中已存在同 id 的行视为已迁移并跳过,
|
||||
// 因此 InitDB 每次启动重复执行也不会产生重复数据(含软删除行一并复制)。
|
||||
// 幂等与异常恢复策略:
|
||||
// 1. 按主键 id 对齐——files 中已存在同 id 的行视为已迁移并跳过;
|
||||
// 2. 若 attachments 表被重建(例如中途部署过旧版二进制,AutoMigrate 把表
|
||||
// 从 id=1 重新编号),旧 id 已被其他内容占用,改用 stored_name(内容
|
||||
// SHA-256)比对补齐,避免新上传被静默漏搬。
|
||||
// 含软删除行一并复制;重复执行不会产生重复数据。
|
||||
func migrateAttachmentsToFiles(db *gorm.DB) {
|
||||
if !db.Migrator().HasTable("attachments") {
|
||||
return
|
||||
}
|
||||
|
||||
// 1) id 对齐迁移(常规升级路径)。
|
||||
res := db.Exec(`
|
||||
INSERT INTO files
|
||||
(id, type, article_id, session_token, uploader_id, filename, stored_name, ext, mime, size, category, created_at, updated_at, deleted_at)
|
||||
@@ -163,4 +169,23 @@ WHERE NOT EXISTS (SELECT 1 FROM files f WHERE f.id = a.id)`)
|
||||
if res.RowsAffected > 0 {
|
||||
log.Printf("Migration: copied %d attachment(s) into files table (type=attachments)", res.RowsAffected)
|
||||
}
|
||||
|
||||
// 2) 内容补齐:id 已存在但指向不同内容(重建表后 id 撞号)的行,
|
||||
// 省略 id 让数据库重新分配,且跳过内容已在 files 中登记的行(去重)。
|
||||
res = db.Exec(`
|
||||
INSERT INTO files
|
||||
(type, article_id, session_token, uploader_id, filename, stored_name, ext, mime, size, category, created_at, updated_at, deleted_at)
|
||||
SELECT
|
||||
'attachments', a.article_id, a.session_token, a.uploader_id, a.filename,
|
||||
a.stored_name, a.ext, a.mime, a.size, a.category, a.created_at, a.updated_at, a.deleted_at
|
||||
FROM attachments a
|
||||
WHERE EXISTS (SELECT 1 FROM files f WHERE f.id = a.id AND f.stored_name <> a.stored_name)
|
||||
AND NOT EXISTS (SELECT 1 FROM files f WHERE f.stored_name = a.stored_name)`)
|
||||
if res.Error != nil {
|
||||
log.Printf("Migration attachments -> files (content fallback) failed: %v", res.Error)
|
||||
return
|
||||
}
|
||||
if res.RowsAffected > 0 {
|
||||
log.Printf("Migration: recovered %d colliding attachment(s) into files table by content", res.RowsAffected)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user