From 1d73bb944de0f4c9bb4ba964978b9774e4e86d7f Mon Sep 17 00:00:00 2001 From: Ed1s0nZ Date: Sat, 10 Oct 2026 20:37:12 +0800 Subject: [PATCH] docs: design SQLite schema reconciliation --- .../startup-schema-reconcile/design.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 docs/feature/startup-schema-reconcile/design.md diff --git a/docs/feature/startup-schema-reconcile/design.md b/docs/feature/startup-schema-reconcile/design.md new file mode 100644 index 00000000..37ebbf66 --- /dev/null +++ b/docs/feature/startup-schema-reconcile/design.md @@ -0,0 +1,31 @@ +# SQLite 启动结构补齐设计 + +输入:已确认 requirements.md。仅影响 internal/database,不改变公开 API 或配置。 + +## 结构来源与流程 + +将现有初始化及迁移后最终表定义收敛为随二进制嵌入的 schemas/*.sql,作为最新结构的唯一来源。启动在临时内存 SQLite 中执行定义,使用 SQLite 自身解析 SQL,再从 sqlite_master / pragma_table_xinfo 读取期望表、列、索引。在真实数据库事务中先创建缺表、再按最新列定义 ADD COLUMN,最后创建索引。已有字段、额外表及数据不删除。 + +```mermaid +flowchart LR + A[嵌入的最新 SQL] --> B[内存 SQLite 解析] + B --> C[对比实际表和列] + C --> D[事务补表和补字段] + D --> E[创建索引与历史数据处理] + E --> F[开始接收请求] +``` + +## 边界与失败 + +- 结构对象:table(name, ddl, columns)、column(name, definition)、index(name, ddl)。它们只在启动期间存在,无新增业务对象。 +- 列定义保留最新 SQL 的类型、默认值和内联约束;拆分器尊重引号、注释和嵌套括号,避免以简单逗号切割 SQL。 +- 不重建表、不凭空为旧数据编造必填值。SQLite 不支持安全 ADD COLUMN 的主键、唯一约束或缺默认值的必填字段,明确报错并回滚结构补齐事务;修复定义/数据后可重新启动。 +- 表级约束不自动改变。结构补齐独立于历史数据回填和既有漏洞外键语义迁移;保留外键迁移时应保留额外字段与数据,避免固定列复制造成损失。 +- 全部结构补齐必须在索引及业务 SQL 之前完成;任一步失败阻止启动。现有连接保持外键配置;内存参考库用单连接并在结束时关闭。 +- 新字段仅更新 SQL 定义即可,不新增手写补字段列表。历史兼容函数可暂保留供既有测试使用,启动不调用纯字段迁移。 + +## 兼容与验证 + +保证已有字段不被改写;默认值用于新列的已有行,未知表/字段保留。针对空库、旧库、重复启动、带引号和复杂默认值、失败回滚、非迁移列表字段、额外字段及外键数据保留做测试。已有时间回填继续保持兼容。 + +维护性门禁选择 adapter_extraction:从 1,822 行 database.go 提取静态 DDL 与补齐行为,旧入口薄委托;不进行无关重构。