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
+10 -3
View File
@@ -16,6 +16,7 @@ import { Table } from './table/table';
import { createSchema } from './table/schema';
import { QueryExecutor } from './query/executor';
import { parseAll } from './sql/parser';
import { bindParameters } from './sql/params';
import { TransactionManager } from './transaction/index';
import { PluginManager } from './plugin/index';
import type { Statement } from './query/ast';
@@ -186,8 +187,12 @@ export class MetonaSqlark {
// ---- SQL 查询 ----
/** 执行 SQL 字符串查询 */
async query(sql: string): Promise<unknown> {
/**
* 执行 SQL 字符串查询。
* v0.7.0: 支持位置参数(`?`)—— `db.query('SELECT * FROM t WHERE id = ?', ['1'])`。
* 参数按 SQL 字面量安全编码(字符串 '' 转义),杜绝 SQL 注入。
*/
async query(sql: string, params?: unknown[]): Promise<unknown> {
this.ensureReady();
const startTime = this.debug ? Date.now() : 0;
@@ -195,8 +200,10 @@ export class MetonaSqlark {
let result: unknown;
try {
// v0.7.0: 参数绑定(仅替换字符串字面量之外的 ?)
const boundSql = bindParameters(sql, params);
// v0.3.0: 支持分号分隔的多语句,逐条顺序执行,返回最后一条的结果
const statements: Statement[] = parseAll(sql);
const statements: Statement[] = parseAll(boundSql);
for (const stmt of statements) {
// v0.5.1: SQL 写语句触发 CRUD 生命周期钩子(与 Table API 路径一致)
await this.triggerStatementHooks(stmt, 'before');