feat(schema): v19 卡片/分组组合表与迁移回填
- 新增 card / card_group:卡片只存标题与顺序,内容由勾选分组组成,支持混合格式 - v18→v19 迁移:按现有 section_block 回填卡片与分组勾选(card-<section>) - 新库 seed 完成后同样回填,旧界面暂不受影响 - 测试 59 passed(含 15→19 迁移)
This commit is contained in:
+2
-1
@@ -600,8 +600,9 @@ mod tests {
|
||||
let fresh = Connection::open_in_memory().expect("内存库应能打开");
|
||||
fresh
|
||||
.execute_batch(
|
||||
"CREATE TABLE node (key TEXT PRIMARY KEY, parent_key TEXT, kind TEXT, view_mode TEXT);
|
||||
"CREATE TABLE node (key TEXT PRIMARY KEY, parent_key TEXT, title TEXT, kind TEXT, view_mode TEXT);
|
||||
CREATE TABLE entry (key TEXT PRIMARY KEY, node_key TEXT NOT NULL, name TEXT NOT NULL);
|
||||
CREATE TABLE section_block (id INTEGER PRIMARY KEY, node_key TEXT NOT NULL, title TEXT, preview_limit INTEGER, sort INTEGER NOT NULL DEFAULT 0);
|
||||
PRAGMA user_version = 15;",
|
||||
)
|
||||
.expect("应能造出 v15 老库");
|
||||
|
||||
+66
-1
@@ -141,6 +141,44 @@ CREATE TABLE IF NOT EXISTS audit (
|
||||
target TEXT,
|
||||
detail TEXT
|
||||
);
|
||||
|
||||
-- ========== v19:首页卡片(展示层组合) ==========
|
||||
|
||||
-- 一张卡片 = 标题 + 顺序;内容由 card_group 勾选分组组成,卡片不拥有数据
|
||||
CREATE TABLE IF NOT EXISTS card (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
sort INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
-- 卡片包含哪些分组(可混合格式),每个分组可单独设预览条数
|
||||
CREATE TABLE IF NOT EXISTS card_group (
|
||||
card_id INTEGER NOT NULL REFERENCES card(id) ON DELETE CASCADE,
|
||||
group_key TEXT NOT NULL REFERENCES node(key) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
preview_limit INTEGER,
|
||||
PRIMARY KEY (card_id, group_key)
|
||||
);
|
||||
"#;
|
||||
|
||||
/// 把老的「分区 → 一个展示块」迁移成「卡片 → 多个分组」。
|
||||
const BACKFILL_CARDS_SQL: &str = r#"
|
||||
INSERT OR IGNORE INTO card (key, title, sort)
|
||||
SELECT 'card-' || COALESCE(p.key, n.key),
|
||||
COALESCE(b.title, COALESCE(p.title, n.title)),
|
||||
MIN(b.sort)
|
||||
FROM section_block b
|
||||
JOIN node n ON n.key = b.node_key
|
||||
LEFT JOIN node p ON p.key = n.parent_key
|
||||
GROUP BY COALESCE(p.key, n.key);
|
||||
|
||||
INSERT OR IGNORE INTO card_group (card_id, group_key, sort, preview_limit)
|
||||
SELECT c.id, b.node_key, b.sort, b.preview_limit
|
||||
FROM section_block b
|
||||
JOIN node n ON n.key = b.node_key
|
||||
LEFT JOIN node p ON p.key = n.parent_key
|
||||
JOIN card c ON c.key = 'card-' || COALESCE(p.key, n.key);
|
||||
"#;
|
||||
|
||||
/// v16 → v17:条目加 `updated_at`(乐观锁),新增审计表。
|
||||
@@ -172,6 +210,24 @@ WHERE kind = 'section' AND key IN (
|
||||
);
|
||||
"#;
|
||||
|
||||
/// v18 → v19:首页卡片改为「卡片 + 勾选分组」。
|
||||
const V19_SQL: &str = r#"
|
||||
CREATE TABLE IF NOT EXISTS card (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
key TEXT NOT NULL UNIQUE,
|
||||
title TEXT NOT NULL,
|
||||
sort INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS card_group (
|
||||
card_id INTEGER NOT NULL REFERENCES card(id) ON DELETE CASCADE,
|
||||
group_key TEXT NOT NULL REFERENCES node(key) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
sort INTEGER NOT NULL DEFAULT 0,
|
||||
preview_limit INTEGER,
|
||||
PRIMARY KEY (card_id, group_key)
|
||||
);
|
||||
"#;
|
||||
|
||||
/// v15 → v16 的增量(老库升级用;新库直接走 SCHEMA_SQL)。
|
||||
const V16_SQL: &str = r#"
|
||||
CREATE TABLE IF NOT EXISTS admin (
|
||||
@@ -213,7 +269,7 @@ pub struct SeedReport {
|
||||
///
|
||||
/// 从 v16 起有了第一套迁移:`migrate` 会把老库逐级升上来,
|
||||
/// 只有「比程序更新」或「没有迁移路径」的版本才拒绝启动。
|
||||
pub const SCHEMA_VERSION: i64 = 18;
|
||||
pub const SCHEMA_VERSION: i64 = 19;
|
||||
|
||||
fn current_version(conn: &Connection) -> Result<i64, StashError> {
|
||||
conn.pragma_query_value(None, "user_version", |row| row.get(0))
|
||||
@@ -262,6 +318,12 @@ pub fn migrate(conn: &Connection) -> Result<i64, StashError> {
|
||||
version = 18;
|
||||
}
|
||||
|
||||
if version == 18 {
|
||||
conn.execute_batch(V19_SQL).map_err(map_error)?;
|
||||
conn.execute_batch(BACKFILL_CARDS_SQL).map_err(map_error)?;
|
||||
version = 19;
|
||||
}
|
||||
|
||||
conn.pragma_update(None, "user_version", version)
|
||||
.map_err(map_error)?;
|
||||
|
||||
@@ -371,6 +433,9 @@ pub fn seed(conn: &mut Connection) -> Result<SeedReport, StashError> {
|
||||
report.blocks += 1;
|
||||
}
|
||||
|
||||
// 老结构(分区 → 展示块)同步生成卡片,保证新首页立刻有内容
|
||||
tx.execute_batch(BACKFILL_CARDS_SQL).map_err(map_error)?;
|
||||
|
||||
tx.commit().map_err(map_error)?;
|
||||
|
||||
Ok(report)
|
||||
|
||||
Reference in New Issue
Block a user