Skip to content

flow-multi-write-unfiltered 不判空组合子:filter: { $and: [] } + multi: true 是整表删除,却零告警 —— 身份归约在 producer 侧有三份,lint 侧不该再抄第四份 #5659

Description

@os-zhuang

范围外发现,来自 #5482(PR 见该单)的实现过程。#5482 的规则刻意只判两种可证形状,这条记录它没判的那一格,以及为什么补它需要一份共享谓词而不是第四份手抄。

事实

#5482 落地的 flow-multi-write-unfiltered 只在两种形状下告警(packages/lint/src/lint-flow-patterns.tsfilterCarriesNoCondition):

  • filter 键缺失;
  • filter 是零个自有键的普通对象({})。

空组合子数组不在其中,而其中一种确实是整表写:

形状 平台已裁定的语义 是否整表写 当前是否告警
filter: { $and: [] } TRUE(AND 恒等元,#5322/#5134) —— multi: true 下删/改每一行
filter: { $or: [] } FALSE(OR 恒等元) 否(一行都不匹配) 否(正确)
filter: { $not: {} } FALSE(NOT TRUE) 否(正确)
filter: { $or: [ {} ] } TRUE({} 是 TRUE 析取项,吸收整个 $or)

裁定不是猜的,三个 driver 都实现了它:packages/drivers/driver-sql/src/sql-driver.tsreduceFilterNode 与其上方 applyFilterCondition 的 "Boolean identities (#5134)" 注释、packages/drivers/driver-mongodb/src/mongodb-filter.ts:139 的同名函数、packages/drivers/driver-memory/src/memory-matcher.ts:44-85evaluate,并由 packages/spec/src/data/filter-logic-conformance.ts 的共享 case-set 钉住(empty $and is TRUE / empty $or is FALSE / a {} branch is a TRUE disjunct and absorbs its $or)。

所以 config: { objectName: 'lead', filter: { $and: [] }, multi: true } 今天可写、可跑、清空整表,而 authoring 期一声不响 —— 与 #5482 的原始形状同类,只是拼法更少见。

为什么 #5482 没顺手补

判「哪个恒等元」需要那套布尔身份归约。它已经存在三份(上面三个 driver),规约来源是 spec 的 case-set 而不是一个可复用的函数。在 linter 里手写第四份,正是 packages/objectql/src/engine-delete-dispatch.ts 被抽出来防的那种事故:扫描器与校验器用两个不同的谓词回答同一个问题,某天其中一个被改。#5240{ field: {} } 三个答案、#4434 的假引擎比真引擎宽松,都是同一族。

建议方向(不预设结论)

  1. 把归约提到共享层:在 packages/spec 暴露一个纯谓词(reduceFilterVerdict(node) -> 'true' | 'false' | 'clause',与 FILTER_LOGIC_CASES 同处一地并由它证明),三个 driver 各自的 reduceFilterNode 改为消费它,lint 侧 filterCarriesNoCondition 也消费它 —— 一个概念一个实现。工作量最大,但这是唯一让「declared = enforced」在四个消费者之间成立的形状。
  2. 只在 lint 侧近似:识别 $and: [] 这一种拼法。便宜,但立刻就是第四份归约的开头,且对 $or: [ {} ] 这类嵌套形状仍然沉默 —— 不建议。
  3. 不做:记录在规则的 JSDoc 里(multi: truefilter 为空的 delete_record / update_record 是「按声明清空整个对象」,authoring 期零诊断 —— #3810 的守卫按「条件被抹掉」判定,不按「条件为空」判定 #5482 已经这么记了),把这格留给 code review。

倾向 1。它同时改善另一条轴:AI 生成的 filter builder 掉光条件后 emit 的正是空组合子,而共享谓词让「空组合子等于什么」在四个消费者处只有一个答案,而不是四处各自宽容。

关联:#5482(引入这条规则的单)、#5322 / #5134(恒等元裁定)、#5240(零算子字段约束,同族先例)、#4550 / #4434(为什么共享谓词而不是手抄)。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions