Commit Graph
9 Commits
Author SHA1 Message Date
thzxx 2a109ef933 feat(B-1): 统一行校验 choke point —— 消除三份分叉的校验实现(A12/A17)
背景(PLAN-v0.7.5.md 根因 1):
修复前有**三份**行校验实现,覆盖面各不相同:

  位置                                        类型 required PK非空 maxLength min/max 未知列
  engine/memory.ts(disk/hybrid 共用)          ✓     ✓       ✓      ✗        ✗     静默丢弃
  engine/aria/index.ts → checkFieldType         ✓     ✓       ✓      ✓        ✓     静默丢弃
  table/schema.ts                               ✓     ✓       ✓      ✓        ✓     静默丢弃

后果一(A12):同一份 schema、同一条 INSERT 是否报约束错误取决于引擎选择 ——
`CREATE TABLE t (name STRING(3))` + 插入 'abcdef' 在 Aria 抛错,在
memory/disk/hybrid 静默写入超长值。

后果二(A17):四个引擎对未知列一律静默丢弃。`INSERT INTO t (id, nope) VALUES
('1',2)` 报成功,随后 `SELECT nope` 报 COLUMN_NOT_FOUND —— 同一列名在写路径与
读路径得到**相反结论**。TABLE API 直通路径尤其明显(executor 按 schema 列序
构造行,nope 那个位置根本没有值,所以连"校验 stmt.columns"都拦不住)。

根治方式:
1. 新增 src/table/validation.ts —— 唯一校验定义 `compileValidator(schema)`,
   约束覆盖面取三者并集,并把**规范化**(default 填充、undefined 跳过、
   __proto__ 防污染)与校验放在同一处。
   三种载荷形态刻意分成三个显式入口,不合成带 options 的函数:
     - validateRow(row, knownColumns?)  INSERT 语义(default 生效、缺列合法)
     - validatePartial(row)             UPDATE 语义(只校验出现的列)
     - assertNoUnknownColumns           独立可复用的列名存在性检查
   混成一个函数会让"required 是否生效"取决于调用方参数,重新引入跨路径差异。
2. MemoryEngine / AriaEngine 的私有 validateRow 改为委托;schema.ts 的公开
   validateRow 同样委托(API 不变,实现只剩一份)。
3. 四个引擎新增 validatePayload(table, rows, mode)(IStorageEngine 契约),
   Executor 在**任何副作用之前**调用:多行批量整体判定,错误消息一次列出全部
   未知列与已知列清单。
4. executeInsert 显式校验 stmt.columns 全部存在(A17)。
5. UPDATE 的外键级联写入(applyUpdateCascade)从"直接赋值"改为过
   validatePartial —— 此前 CASCADE 把新主键写进引用列时绕过 maxLength/min/max,
   与 A12 属同一类"校验只在部分写入路径生效"。

连带修正(测试夹具本身不忠实,B-1 使其暴露):
  - tests/engine/aria-cache.test.ts 的 makeRows 无条件返回 {id,name,age},
    部分用例的表只有 {id,name} —— 多余列被静默丢弃所以"通过"。新增 rowsFor()
    按 schema 裁剪,让夹具忠实反映表结构(而不是放宽校验)。
  - tests/v073-fixes.test.ts "schema 外列不持久化" 改为断言写路径即拒绝,
    并保留"合法行落盘后不含额外列"的检查。

验证:
  - 新增 tests/v080-unified-validation.test.ts:8 项 × 4 引擎 + 9 项校验器
    单元契约,共 41 断言;
  - 全量 84 套件 / 1499 测试通过;typecheck(src+tests) 与 lint 零错误。
2026-09-14 23:38:58 +08:00
thzxx 50468b9b0e fix: v0.7.3 数据正确性与边界窗口收尾 — INSERT 语句级原子(三引擎+Aria PK 批内重复)/ 索引列 IS NULL 恒空 / delete RESTRICT 破坏索引 / queryStream 子查询静默空结果 / ALTER DROP 索引残留 / UNIQUE INDEX 存量校验 / SELECT * 别名投影 / WAL BEGIN/ROLLBACK 事务边界 / aria $in 与级联重复扫描性能 / $and 等值下推 / ANALYZE 索引统计 / React-Vue hooks 生命周期 / 迁移主键兜底 + 58 回归
CI / test (18.x) (push) Successful in 17m43s
CI / test (22.x) (push) Successful in 13m45s
CI / test (20.x) (push) Successful in 15m33s
CI / test (24.x) (push) Successful in 24m46s
CI / e2e (push) Successful in 52s
2026-08-14 22:53:46 +08:00
thzxx 05e6823bf1 fix: v0.7.2 语句级原子性 + 事务 DDL 拒绝 + 约束/绑定硬化 — 6 项修复 + 43 回归 + CI 重型套件串行
CI / test (22.x) (push) Successful in 24m26s
CI / e2e (push) Successful in 10m0s
CI / test (18.x) (push) Successful in 27m14s
CI / test (20.x) (push) Failing after 1h19m9s
CI / test (24.x) (push) Successful in 37m49s
- UPDATE 语句级部分提交(P1,四引擎):两阶段全量预检后执行,批内唯一互查,
  任何一行失败整句不执行(aria 场景 WAL 与内存不再错位)
- 事务内 ALTER/CREATE INDEX/DROP INDEX 残留(P1):Memory/KVStore 显式拒绝
  (对齐 Aria),createTable/dropTable 保持可回滚
- SET NULL 级联绕过 required 约束(P1):预检阶段整体拒绝 FOREIGN_KEY_VIOLATION
- bindParameters 注释误判(P2):行注释/块注释中的 ? 与引号不再参与绑定
- 未闭合字符串静默接受 → lexer 抛 PARSE_ERROR;未知 where 操作符抛 QUERY_ERROR
- UPDATE undefined 覆盖列值 → 语义化为不更新(null 仍置空)
- Hybrid 写穿透非原子(P1):磁盘失败自动重载内存对齐磁盘再抛原错误
- CI:Run tests 拆常规并行 + 重型串行(runInBand),重型测试超时余量提升,
  性能护栏 kv 120→240s / opfs 150→300s(仍拦截悬崖回归)
- 测试 1155 → 1198(74 套件),覆盖率 89.82% 保持
2026-08-13 15:31:16 +08:00
thzxx cbe407eb49 fix: v0.7.1 API 修复与防御统一 — static create / 未 open 防护 / 原型污染 / lint 清零
CI / test (22.x) (push) Successful in 17m24s
CI / e2e (push) Successful in 10m39s
CI / test (18.x) (push) Successful in 19m5s
CI / test (20.x) (push) Successful in 18m4s
CI / test (24.x) (push) Successful in 23m19s
- MetonaSqlark.create 静态工厂(README 示例在 ESM/Node 下此前 TypeError),
  独立 create 函数委托静态实现
- close 未初始化防御(engine undefined 不再崩溃)
- AriaEngine hasTable/getTableNames/getTableSchema 统一 ensureOpen
- 事务回滚失败不掩盖原始错误
- __proto__ 列名防护:Executor 列映射 Object.create(null) + schema 校验拒绝
- lint 清零(移除 5 处未使用导入)

测试 1147 → 1155(73 套件);行覆盖率 89.8%;版本 0.7.1
2026-08-13 11:14:42 +08:00
thzxx 57415975ea feat: v0.7.0 参数化查询 + 事务增量 flush + 复合主键语义硬化 + EXPLAIN 真实索引信息
CI / test (22.x) (push) Successful in 17m29s
CI / test (24.x) (push) Failing after 17m32s
CI / e2e (push) Successful in 9m53s
CI / test (18.x) (push) Successful in 19m17s
CI / test (20.x) (push) Successful in 18m15s
- 参数化查询 db.query(sql, params):词法层 ? 绑定 + SQL 字面量安全编码
  ('' 转义/注入防护);参数计数不匹配 PARAM_ERROR;对象参数显式拒绝
- KVStoreEngine 事务增量 flush:行级变更追踪,commit 仅写改动行
  (1000 行表改 1 行:日志 1 条目 vs 整表 1000 条目);级联影响表漏写修复
  (txFullTables 同步加入 txDirtyTables);移除每次 commit 全量 checkpoint
  (阈值自动 checkpoint + close 统一截断)
- 复合主键显式拒绝:createSchema 校验期 SCHEMA_ERROR + ALTER ADD 主键列防护
  (此前静默取第一个主键,其余标记失效)
- EXPLAIN usingIndex 真实命中信息:pk / index:col / none

测试 1126 → 1147(72 套件);行覆盖率 89.8%;版本 0.7.0
2026-08-13 10:57:26 +08:00
thzxx f97c5a6001 fix(P2): v0.6.3 原子性/一致性/资源治理 — 8 项修复 + 12 回归
CI / test (18.x) (push) Successful in 19m13s
CI / test (20.x) (push) Successful in 18m8s
CI / test (22.x) (push) Successful in 17m18s
CI / test (24.x) (push) Successful in 22m57s
CI / e2e (push) Successful in 9m53s
- KVStore 混合写单记录原子:新增 writeBatch(put+delete 同一条日志记录),
  KVStoreEngine 全部混合写路径统一(兑现真原子宣称,崩溃无新旧行并存)
- WAL full 模式写入失败抛错(此前 console.warn 吞错 → 崩溃即丢且无感知)
- MemoryEngine SET NULL 级联索引残留:复用 removeIndexEntries(消除虚假 UNIQUE_VIOLATION)
- delete 级联两阶段:先全量 RESTRICT 预检(沿 CASCADE 链递归)再执行,无部分级联
  (Memory/Aria 对齐)
- BufferPool 驱逐同步清理 pages Map(EvictionManager onRemove 回调,内存预算真实生效)
- MVCC commit 清理已提交版本(版本链仅作事务内 undo,消除行数据双份常驻)
- LSM.flush 重复入链修复(入链即置空 immutable)+ frozenMemtables 可见性时序
- rollbackToSavepoint 重建受影响表二级索引(消除过期索引条目)

测试 1114 → 1126(71 套件);行覆盖率 89.7%;版本 0.6.3
2026-08-13 10:30:39 +08:00
thzxx ef1934a38c fix(P0): v0.6.2 数据正确性专项 — 深度审计 6 项修复 + 22 回归
CI / test (22.x) (push) Successful in 17m6s
CI / test (18.x) (push) Failing after 17m45s
CI / test (20.x) (push) Successful in 18m7s
CI / test (24.x) (push) Failing after 14m40s
CI / e2e (push) Successful in 9m54s
- KVStoreEngine 数值主键 update 丢行(P0):String 化主键回查不命中 → 误删 KV 行
  (重启丢数据);改为单次全表扫描 + 受影响集合过滤(兼消 O(N×M) 回查开销)
- update 主键撞已有主键静默覆盖(P0,Memory/Aria):抛 DUPLICATE_KEY,事务路径同拦截
- Aria 二级索引范围查询边界算法错误(P1):Number(v)±1 构造 key 漏小数/字符串数据;
  改全索引扫描 + matchWhere 过滤,边界语义统一
- Aria 索引列 IS NULL 返回空(P1):null 等值/含 null 的 IN 不走索引(回退全表)
- AriaEngine unique 约束未强制(P1):insert 整批预检(批内互查+索引扫描,失败整批
  不落库)+ update 排除自身旧条目检查;新增 LSM.prefetchPrefixRanges 批量预加载
- 非主键 update 索引旧值残留:统一传旧行清理(消除唯一性误报与索引膨胀)
- EXPLAIN 写语句产生真实副作用(P2):仅 SELECT 执行,UPDATE/DELETE 用 count 估算

测试 1092 → 1114(70 套件);行覆盖率 89.6%;版本 0.6.2
2026-08-13 09:51:26 +08:00
thzxx 8a78f27f7d fix: v0.6.1 生产可用性深度审查 — MemoryEngine 级联环无限递归(P0)/ KVStore 多表事务与级联原子化 / 未open防护统一 / 27 个异常场景测试 + aria级联回归
CI / test (18.x) (push) Successful in 10m59s
CI / test (20.x) (push) Successful in 10m59s
CI / test (22.x) (push) Successful in 10m49s
CI / test (24.x) (push) Successful in 10m47s
CI / e2e (push) Successful in 10m4s
2026-08-10 14:29:40 +08:00
thzxx 24b3ca1079 release: v0.6.0 — 完全移除 IndexedDB,自研 KVStore 事务存储引擎(多key原子写/快照日志恢复/CRC自愈)+ KVStoreEngine + 旧库迁移工具 + 10万级压力验证 + 崩溃注入e2e
CI / test (20.x) (push) Successful in 10m53s
CI / test (22.x) (push) Successful in 10m47s
CI / test (24.x) (push) Successful in 10m42s
CI / e2e (push) Successful in 10m27s
CI / test (18.x) (push) Successful in 11m1s
2026-08-10 13:56:04 +08:00