fix(P0): v0.6.2 数据正确性专项 — 深度审计 6 项修复 + 22 回归
- 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
This commit is contained in:
+16
-4
@@ -183,11 +183,23 @@ export class QueryExecutor {
|
||||
private async executeExplain(stmt: { query: Statement }): Promise<Record<string, unknown>> {
|
||||
const startTime = Date.now();
|
||||
let result: unknown = null;
|
||||
try {
|
||||
result = await this.execute(stmt.query);
|
||||
} catch { /* explain 即使执行失败也返回计划 */ }
|
||||
let rows = 0;
|
||||
|
||||
// v0.6.2-fix: EXPLAIN 不得真实执行写语句 —— 此前 EXPLAIN DELETE/UPDATE 会产生
|
||||
// 真实副作用(删/改数据)。仅 SELECT 类语句执行(只读);UPDATE/DELETE 用
|
||||
// count 估算影响行数(无副作用);INSERT/DDL 仅输出计划不执行。
|
||||
if (stmt.query.type === 'SELECT' || stmt.query.type === 'SELECT_UNION') {
|
||||
try {
|
||||
result = await this.execute(stmt.query);
|
||||
} catch { /* explain 即使执行失败也返回计划 */ }
|
||||
rows = Array.isArray(result) ? result.length : 0;
|
||||
} else if (stmt.query.type === 'UPDATE' || stmt.query.type === 'DELETE') {
|
||||
try {
|
||||
const plan = compileStatement(stmt.query);
|
||||
rows = await this.engine.count(plan.table, plan);
|
||||
} catch { rows = 0; }
|
||||
}
|
||||
const elapsed = Date.now() - startTime;
|
||||
const rows = Array.isArray(result) ? result.length : 0;
|
||||
|
||||
// v0.5.1: 仅 SELECT/DELETE/UPDATE 有引擎查询计划;其他语句输出基本信息
|
||||
let plan: import('../constants').QueryPlan | null = null;
|
||||
|
||||
Reference in New Issue
Block a user