Commit Graph
3 Commits
Author SHA1 Message Date
thzxx b20d47bd93 feat(B-3): 单管线 —— QueryBuilder 只产出 AST,执行一律经 Executor
背景(PLAN-v0.7.5.md 根因 2/4):
三个 builder 的 execute() 各自执行写入/查询,与 SQL 路径构成**两条管线**:
  - SelectQueryBuilder:无 JOIN 时直接调 engine.find(只有 JOIN 才走 executor)
  - UpdateQueryBuilder / DeleteQueryBuilder:直接调 engine.update/delete

于是同一条语义在两条路径上规则各写一份,实测差异:
  - `db.table('t').select(['t.n'])` 行键保留 `t.n`,SQL 路径归一化为 `n`
  - `select(['nope'])` 静默产出 `[{},{},{}]`(引擎不校验列存在性)
  - 不受 maxRowsPerQuery 约束
  - UPDATE/DELETE 的 `$subquery`/`$col`/`$exists` 无人解析 → 引擎判 UNKNOWN
    → **静默影响 0 行**(引擎层此前为此加了"检测到未解析标记就抛 NOT_SUPPORTED"
    的防御 —— 那是把"管线缺失"暴露成用户错误,方向错了)

改动:
1. SelectQueryBuilder / UpdateQueryBuilder / DeleteQueryBuilder 的 execute()
   统一为 `executor.execute(toAST())`;构造函数不再接收 engine。
   删掉 `if (joins.length > 0 && executor)` 的分支 —— executor 自己会在安全时
   下推到引擎,不需要 builder 代劳。
2. 生命周期钩子(beforeUpdate/afterUpdate/beforeDelete/afterDelete + onWrite
   广播)改由 Table 以回调形式注入 builder,顺序与修复前一致
   (before → executor → onWrite → after)。回调接收**实际语句**,
   因此 beforeUpdate 的 `query.where` 不再是空对象 —— 修复前 builder 路径的
   钩子能拿到 where,现在仍然能(新增测试锁定)。
3. Table 新增 requireExecutor():拿不到执行器时**明确报错**,不再静默退化为
   "直接调引擎"。Transaction.table() 相应构造绑定同一引擎的 QueryExecutor
   (事务原子性仍由引擎的 begin/commit/rollback 提供)。
4. 删除引擎层 4 处 `containsUnresolvedSubqueries → NOT_SUPPORTED` 防御:
   写路径已不可能出现未解析标记(builder 与 SQL 都经 Executor),
   留着它会让后来者误以为"这里需要防御"。

验证:新增 tests/v080-single-pipeline.test.ts(TABLE API 与 SQL API 逐值等价,
4 引擎 × 12 项 + 跨引擎 1 项,共 57 断言);全量 84 套件 / 1646 测试通过;
typecheck(src+tests) 与 lint 零错误。
2026-09-15 00:15:41 +08:00
thzxx 0dba1abf2a test(P0): v0.8.0 验证基座与工程门禁根治
工作流 C-1 / C-3 前半 + 测试代码类型检查。

【故障注入基座】新增 tests/helpers/storage-harness.ts + faulty-backend.ts
- TransactionalFileStore:忠实 OPFS 提交语义(close 才可见)+ 字节级故障注入
  (failNextWrite/Append/Delete、truncateAppendTo 撕裂写、crashPending 真崩溃)
- 删除旧 opfs-mock:读返回内部引用、keepExistingData:false 不截断、close 空实现
  导致"提交前可见"等真实缺陷无法被测出(31 个测试文件迁移至新 harness)
- 删除 aria-opfs-backend 内的第三份重复 mock(含从未被断言使用的 writeCalls 死代码
  与 entry.content.subarray 恒等分支)
- FaultyBackend:包装任意 IStorageBackend 注入故障;crash() 明确区别于 close()
  (后者是优雅停机,会刷完写队列 —— 这正是此前所有"崩溃恢复"测试的真相)
- 16 条基座自测证明注入真的生效(含 close 不能当崩溃的对照组)

【覆盖率口径】jest.config.cjs
- 移除 '!src/**/index.ts'(该 glob 把 AriaEngine 主实现等 15 个实现文件整体
  排除出统计,与 v0.2.6 曾承认过的问题同源),改为只排除纯类型声明文件并附理由
- 新增 coverageThreshold 门禁(此前完全不存在)
- 真实基线:语句 90.66% / 分支 82.94% / 函数 94.36% / 行 93.43%
- 修正 testMatch 使 tests/helpers 下的测试可被发现

【测试代码类型检查】tsconfig.test.json + npm run typecheck:tests
- 修复 103 个测试代码类型错误(此前 babel 剥离类型 + tsconfig 排除 tests,全部隐藏)
- 新增 tests/helpers/assertions.ts:nonNull/decode/rows/object/engineMethod/expectCode
  以断言收窄替代 as any
- 消除 21 个 lint warning(含 v043-hardening 中定义后从未调用的 mockOPFS 死代码)
- parser.test.ts 12 处 toBeDefined() 空断言升级为结构断言(并新增 AND/OR 优先级用例,
  当前红灯,对应总账第 11 项,将在工作流 A 修复)

【版本契约】新增 tests/version-contract.test.ts
- 校验 src VERSION / package.json / dist 三者一致,替代两处硬编码版本字面量

【CI 门禁】.gitea/workflows/ci.yml
- lint 去掉 continue-on-error(此前永远不让 CI 变红)
- 新增 tests 类型检查、--coverage 覆盖率门禁、dist 与源码同步校验
- 版本 0.7.4 升至 0.8.0
2026-09-14 21:03:06 +08:00
thzxx e2a590c5b1 feat: metona-sqlark v0.1.12 — 前端TypeScript关系型数据库
- 4种存储引擎:Memory / IndexedDB / OPFS / Hybrid
- 完整SQL支持:SELECT/INSERT/UPDATE/DELETE/JOIN/GROUP BY/HAVING/DISTINCT
- Query Builder链式API + TypeScript泛型支持
- 聚合函数:COUNT/SUM/AVG/MIN/MAX
- 事务、插件系统(14 hooks)、发布订阅、数据迁移、导入导出
- React/Vue框架集成
- 264个测试用例,93.46%覆盖率
- 零运行时依赖
2026-07-26 15:00:01 +08:00