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
This commit is contained in:
thzxx
2026-08-13 10:57:26 +08:00
parent f97c5a6001
commit 57415975ea
20 changed files with 1542 additions and 69 deletions
+12 -8
View File
@@ -1,10 +1,10 @@
# MetonaSqlark
<p align="center">
<img src="https://img.shields.io/badge/version-0.6.3-blue?style=flat-square" alt="version">
<img src="https://img.shields.io/badge/version-0.7.0-blue?style=flat-square" alt="version">
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="license">
<img src="https://img.shields.io/badge/coverage-89.7%25-brightgreen?style=flat-square" alt="coverage">
<img src="https://img.shields.io/badge/tests-1126%20passed-success?style=flat-square" alt="tests">
<img src="https://img.shields.io/badge/coverage-89.8%25-brightgreen?style=flat-square" alt="coverage">
<img src="https://img.shields.io/badge/tests-1147%20passed-success?style=flat-square" alt="tests">
</p>
> 基于 TypeScript 的**前端关系型数据库**:完整 SQL + Query Builder 双 API
@@ -116,6 +116,10 @@ await db.defineTable('orders', {
await db.query("INSERT INTO users VALUES ('1', 'Alice', 30, 'alice@demo.com')");
const rows = await db.query('SELECT * FROM users WHERE age > 18 ORDER BY name');
// 参数化查询(v0.7.0)— 位置参数 `?`,安全编码杜绝 SQL 注入
await db.query("INSERT INTO users VALUES (?, ?, ?, ?)", ['2', "O'Brien", 25, 'ob@demo.com']);
const row2 = await db.query('SELECT * FROM users WHERE name = ?', ["O'Brien"]);
// Query Builder
const result = await db.table('users')
.select(['name', 'age'])
@@ -213,7 +217,7 @@ await db2.disconnect(); // 引用计数 -1
| 方法 | 说明 |
|------|------|
| `db.query(sql)` | 执行 SQL(支持分号多语句 |
| `db.query(sql)` / `db.query(sql, params)` | 执行 SQL(支持分号多语句;v0.7.0 位置参数 `?` 绑定 |
| `db.queryStream(sql, onRow)` | 流式查询(逐行回调,不物化) |
| `db.table(name)` | 获取表操作对象(`insert` / `select` / `update` / `delete` / `count` / `stream` / `clear` / `drop` |
| `db.defineTable(name, cols)` | 定义表结构 |
@@ -233,7 +237,7 @@ await db2.disconnect(); // 引用计数 -1
| 语句 | 说明 | 支持引擎 |
|------|------|----------|
| `EXPLAIN SELECT ...` | 输出查询计划(type/table/where/estimatedRows/actualTimeMs | 全部 |
| `EXPLAIN SELECT ...` | 输出查询计划(type/table/where/usingIndex/estimatedRows/actualTimeMs | 全部 |
| `ANALYZE [TABLE] name` | 收集表统计信息(行数/行大小/索引深度/列基数) | Aria |
| `REINDEX [TABLE] name` | 重建表二级索引 | Aria |
| `VACUUM` | 压缩 LSM + 清理 MVCC 碎片 | Aria |
@@ -397,7 +401,7 @@ const { data, loading, error, refresh } = useSqlarkQuery(db, 'SELECT * FROM user
npm install # 安装依赖
npm run dev # 开发模式(localhost:3001
npm run build # 生产构建(生成 dist/
npm test # 运行测试(1126 用例 · 71 套件)
npm test # 运行测试(1147 用例 · 72 套件)
npm run test:e2e # Playwright e2e(真实 Chromium + OPFS + 崩溃注入,需先 build
npm run lint # 代码检查
npm run typecheck # 类型检查
@@ -409,9 +413,9 @@ npm run typecheck # 类型检查
| 指标 | 数值 |
|------|------|
| 测试用例 | 1126+12 Playwright e2e |
| 测试用例 | 1147+12 Playwright e2e |
| 测试套件 | 70 |
| 行覆盖率 | 89.7% |
| 行覆盖率 | 89.8% |
| SQL 关键字 | 72 |
| 存储引擎 | 5Memory / KVStore / OPFS / Hybrid / Aria |
| 运行时依赖 | 0 |