新增: 项目归档

This commit is contained in:
lxy
2026-10-05 14:59:12 +08:00
parent 63c5c3d4f0
commit 24d6803ecc
19 changed files with 250 additions and 17 deletions
+34 -6
View File
@@ -1,4 +1,5 @@
//! 数据库迁移 — 建表 SQL 与版本管理
//! 数据库迁移 — 建表 SQL 与版本管理
use crate::migrations_helpers::column_exists;
use anyhow::Result;
@@ -55,7 +56,8 @@ pub fn run(conn: &Connection) -> Result<()> {
// 发起时一次声明存续期生效,随会话同亡)。
// V46/V47 = 任务/灵感归档(archived INTEGER NOT NULL DEFAULT 0,归档功能 P1,
// 对标 ai_conversations.archived V4;归档与软删正交:回收站=删除缓冲,归档=低频可见保检索)。
let steps: [(i32, fn(&Connection) -> Result<()>); 47] = [
// V48 = 项目归档(projects.archived 列,归档功能 P2,同款三方对齐)。
let steps: [(i32, fn(&Connection) -> Result<()>); 48] = [
(1, migrate_v1),
(2, migrate_v2),
(3, migrate_v3),
@@ -105,6 +107,8 @@ pub fn run(conn: &Connection) -> Result<()> {
// V47 = 灵感归档(ideas.archived 列,同款)。归档与软删正交:回收站=删除缓冲,归档=低频可见保检索。
(46, migrate_v46),
(47, migrate_v47),
// V48 = 项目归档(projects.archived 列,归档功能 P2,对标 V46/V47 同款)。
(48, migrate_v48),
];
for (version, migrate_fn) in steps {
@@ -1404,6 +1408,25 @@ fn migrate_v47(conn: &Connection) -> Result<()> {
Ok(())
}
/// V48: 幂等补 projects.archived 列(项目归档,归档功能 P2)
///
/// 对标 V46 tasks / V47 ideas 同款:归档与软删正交(回收站=删除缓冲,归档=低频可见保检索)。
/// archived 不进 update_field 通用白名单,走专用 set_archived(布尔语义 + 防旁路)。
/// 活跃查询(list_active/list_active_with_activity/list_by_query)恒带 `archived = 0`。
/// - **幂等**:column_exists 守卫;**可逆**:`ALTER TABLE projects DROP COLUMN archived`。
fn migrate_v48(conn: &Connection) -> Result<()> {
if !column_exists(conn, "projects", "archived") {
conn.execute(
"ALTER TABLE projects ADD COLUMN archived INTEGER NOT NULL DEFAULT 0",
[],
)?;
tracing::info!("v48: 补建 projects.archived 列(项目归档)");
}
conn.execute("INSERT OR IGNORE INTO schema_version (version) VALUES (?)", [48])?;
tracing::info!("迁移 v48 完成: projects 加 archived 列");
Ok(())
}
/// V21 建表 SQL — 消息拆分存储 ai_messages 表
///
/// 与 V9_SQL 中的 ai_messages 镜像(V9 给新库,此 const 给老库 V21 迁移用 IF NOT EXISTS)。
@@ -2417,8 +2440,13 @@ mod tests {
column_exists(&conn, "ideas", "archived"),
"ideas.archived 列缺失(V47 加)"
);
// projects.archived(V48 项目归档 P2)
assert!(
column_exists(&conn, "projects", "archived"),
"projects.archived 列缺失(V48 加)"
);
// 3. schema_version 应推进到 45(全量迁移成功落版本号)
// 3. schema_version 应推进到 48(全量迁移成功落版本号)
let max_version: i64 = conn
.query_row(
"SELECT COALESCE(MAX(version), 0) FROM schema_version",
@@ -2427,8 +2455,8 @@ mod tests {
)
.expect("查 schema_version 应成功");
assert_eq!(
max_version, 47,
"全量迁移后 schema_version 应为 47(实际 {}),说明某条 migrate_vN 链路断在中间",
max_version, 48,
"全量迁移后 schema_version 应为 48(实际 {}),说明某条 migrate_vN 链路断在中间",
max_version
);
@@ -2505,7 +2533,7 @@ mod tests {
|r| r.get(0),
)
.unwrap();
assert_eq!(max_v, 47, "首轮应推进到 47");
assert_eq!(max_v, 48, "首轮应推进到 48");
// 清空版本表强制全链第二遍(每步 execute 第二次)
conn.execute("DELETE FROM schema_version", []).unwrap();
@@ -2517,7 +2545,7 @@ mod tests {
|r| r.get(0),
)
.unwrap();
assert_eq!(max_v2, 47, "重跑后应重新推进到 47");
assert_eq!(max_v2, 48, "重跑后应重新推进到 48");
}
// ============================================================