fix: v0.7.4 写语句子查询 / 约束硬化 / 真惰性流式 — UPDATE-DELETE WHERE 子查询静默 0 行(四引擎,关联引用显式 NOT_SUPPORTED + EXPLAIN 同步)/ 主键 NULL-undefined 强制拒绝 / DROP INDEX 保留建表 UNIQUE(仅索引来源可解除)/ GROUP BY-DISTINCT-UNION 键类型安全编码 / UPDATE 未知列报错 / queryStream 多语句拒绝 / KVStore 后台错误跨 reopen 清理 + Hybrid begin 补偿 / RB-Tree 删除双黑修复 + LSM 死代码清理 / findStream 迭代器化真惰性(limit 早停 O(1) 内存)/ REINDEX 单次扫描 + 48 回归
This commit is contained in:
@@ -31,6 +31,36 @@ function compileLikeRegex(pattern: string): RegExp {
|
||||
// WHERE 匹配(顶层入口)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* v0.7.4: 检测 WHERE 中未解析的子查询/列引用标记($subquery / $col / $exists)。
|
||||
* QueryBuilder 等直通引擎的写路径(update/delete)不经 Executor 解析子查询,
|
||||
* 引擎层 matchWhere 对未解析标记恒 false → 静默影响 0 行。
|
||||
* 写路径预检阶段显式拒绝;SELECT 路径由 Executor 解析(不调用本函数)。
|
||||
*/
|
||||
export function containsUnresolvedSubqueries(where: WhereCondition | undefined): boolean {
|
||||
if (!where) return false;
|
||||
for (const [k, v] of Object.entries(where)) {
|
||||
if (k === '$and' || k === '$or') {
|
||||
if ((v as WhereCondition[]).some((sub) => containsUnresolvedSubqueries(sub))) return true;
|
||||
continue;
|
||||
}
|
||||
if (k === '$not') {
|
||||
if (containsUnresolvedSubqueries(v as WhereCondition)) return true;
|
||||
continue;
|
||||
}
|
||||
if (k === '$exists') return true;
|
||||
if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
|
||||
for (const [, operand] of Object.entries(v as Record<string, unknown>)) {
|
||||
if (typeof operand === 'object' && operand !== null) {
|
||||
const ops = operand as Record<string, unknown>;
|
||||
if ('$subquery' in ops || '$col' in ops) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配完整 WHERE 条件
|
||||
* @param row 当前数据行
|
||||
@@ -41,8 +71,7 @@ export function matchWhere(
|
||||
row: Record<string, unknown>,
|
||||
where: WhereCondition,
|
||||
options: { $col?: boolean } = {},
|
||||
): boolean {
|
||||
for (const [field, condition] of Object.entries(where)) {
|
||||
): boolean { for (const [field, condition] of Object.entries(where)) {
|
||||
// 顶层 $caseResult(v0.3.2):由 Executor 对 CASE WHEN 表达式逐行求值后产生
|
||||
if (field === '$caseResult') {
|
||||
if (condition !== true) return false;
|
||||
|
||||
Reference in New Issue
Block a user