Skip to content

objectql having-filter.ts 是「无值字段」语义的第五个求值面,且带着 #5299 同款的早退守卫($nin / $notContains 不在豁免名单) #5905

Description

@os-zhuang

出自 #5298「第一棒:成本清单」的消费点清点(纯读调查),范围外发现,按 Prime Directive #10 记录,不指派。

事实(origin/main 5c94f833c,静态对读)

packages/objectql/src/having-filter.ts自己的一套 arm 求值 HAVING 子句,算子词表与 FilterCondition 同一套(having-filter.ts:35-37 列了 $eq $ne $gt $gte $lt $lte $between $in $nin $exists $null $contains $notContains $startsWith $endsWith $regex)。它是 driver-sql / driver-memory 的 mingo 面 / driver-memory 的参考匹配器 / formula.matchesFilterCondition 之外的第五个求值面,#5146 / #5299 / #5298 的清点里都没有出现过。

两处与 #5299 记录的 driver-memory 分叉形状完全相同:

  1. having-filter.ts:112
    if (value === undefined && op !== '$exists' && op !== '$ne' && op !== '$null') return false;
    —— 豁免名单里没有 $nin(也没有 $notContains),与 driver-memory 与 formula 对「字段没有值」给出三处不同答案:$notContains(null 值)、$exists(键在值为 null)、$nin(缺键) #5299 正文点名的 memory-matcher.ts 早退守卫逐字同构。
  2. having-filter.ts:137
    case '$notContains': if (typeof value !== 'string' || value.includes(target)) return false;
    —— 值不是字符串(null / undefined)一律判否,与 driver-memory 与 formula 对「字段没有值」给出三处不同答案:$notContains(null 值)、$exists(键在值为 null)、$nin(缺键) #5299 记录的 driver-memory 读法一致、与 formula 相反(formula/src/matches-filter.ts:183 判是)。

另外 having-filter.ts:126$nin 本体 if (Array.isArray(target) && target.includes(value)) return false;value === undefined 本来是「通过」的,是上面那条早退守卫先把它拦成了「不通过」—— 与 #5299 描述的机制一模一样。

为什么按 finding 记(不代 triage 定级)

HAVING 求值的输入是聚合输出行,measure 键通常总是存在,所以 value === undefined 这一格今天不太容易被真实用户撞到;$notContains 对 null 值那一格则取决于聚合是否产出 null measure。没有量化真实 dashboard 里出现这两种形状的频率。按「观察类」记,不因为「看着小」就压着不报 —— 定级请按 triage,不代表我判断它低。

与既有账的关系

关联

#5299(driver-memory vs formula 的同款三格)、#5298(非否定路径 NULL-safe 裁决)、#5146 / PR #5296(极性表)、#5239(FILTER_LOGIC_CASES —— 今天不覆盖 HAVING 路径)。

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions