Skip to content

非否定路径上的 $ne / $nin / $notContains:driver-sql 排除 NULL 行,driver-memory / formula 返回它们(#5146 只裁定了 $not) #5298

Closed

Description

@os-zhuang

修 #5146 时实测到的邻接分叉,不在该单范围内(维护者的拍板明确只覆盖 $not)。
这里按 Prime Directive #10 记录。

事实(实测,main@88b9b2d5c + PR #5296 的分支;这几条路径 PR #5296 未改动)

fixture:1: stage='won'、2: stage='lost'、3: stage=NULL、4: stage=NULL。

filter driver-sql 编译 driver-sql 返回 driver-memory formula matchesFilterCondition
{ stage: { $ne: 'won' } } stage <> 'won' 2 2,3,4 2,3,4
{ stage: { $nin: ['won'] } } stage not in ('won') 2 2,3,4 2,3,4
{ stage: { $notContains: 'w' } } stage NOT LIKE '%w%' 2 2(另一处分叉,另单) 2,3,4

成因与 #5146 同源:SQL 里 NULL <> 'won' 是 UNKNOWN 而不是 TRUE,WHERE 只留 TRUE;
JS 家族用两值逻辑求值,undefined !== 'won' 直接为真。区别只在于 #5146 的宿主是
$not,这里是算子本身。

为什么单独记

PR #5296 只把 $not 内部的叶子编译成全域谓词(这是 #5146 拍板的范围),$not
之外的比较逐字符未变 —— 刻意的:改动非否定路径会影响每一条普通查询的 SQL 形状与
索引利用,属于另一个量级的决定,需要单独拍板。所以今天的状态是:

  • { $not: { stage: 'won' } } → 三家一致(NULL 行返回);
  • { stage: { $ne: 'won' } } → 仍然分叉(SQL 少三行)。

对使用者而言,这个不一致是可见的:同一条「不是 won」的列表过滤,SQL 数据源上看不到
stage 为空的记录,内存数据源上看得到;RLS 写侧 check(formula)与读侧 SQL 也会对
同一条规则给出不同答案。

需要拍板的

$ne / $nin / $notContains 是否也采用 NULL-safe 语义(col IS NULL OR col <> v)?

建议与 #5146 的 spec 半边、#5239 的 FILTER_LOGIC_CASES 扩表一并考虑:无论选哪个,
跨驱动 case 都应该把 null 行的去留写进那张表(它今天刻意不含 null 处理,所以这类
分叉现在没有任何门禁能发现)。

关联

#5146($not 的同源分叉,已拍板 NULL-safe)、PR #5296(实现,含逐算子极性表可直接
复用)、#5239(conformance 表)、#5240({ field: {} } 的三个答案)、cloud#1076。

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 5, 2026
  2. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    分诊(backlog sweep,主 backlog 代扫):挂 finding + domain:engine。理由:$ne / $nin / $notContains 对 NULL 行的取舍在 driver-sql 与 driver-memory / formula 之间相反是实锤,但正文自己点明 #5146 只裁定了 $not——非否定路径缺一次语义裁决,裁决前没有可派发的验收判据,按 finding 持有。晋级路径:与 #5299 同一次裁决处理(engine 车道起 [决策] 单或并入发现分诊轮)。不构成认领。会话:session_01N3uGFF8teXbpgtbEJ1aYXu


    Generated by Claude Code

  3. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    范围注记(2026-08-05,维护者裁决,锚点 #5499):driver-memory 投入已冻结,本单的 driver-memory 半边随之冻结;但 driver-sql 与 formula 的 NULL 行取舍分歧仍是活问题,故保留 finding 不转 on-hold。下次发现分诊轮请按「driver-sql vs formula」重新框定范围与验收判据($not 之外的非否定路径语义裁决仍缺)。会话:session_01N3uGFF8teXbpgtbEJ1aYXu


    Generated by Claude Code

  4. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 5, 2026
  5. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊轮判级(按 08-05 14:24 范围注记重框):晋级为决策载体 —— 摘 finding 换 needs-user-decision,本单作为 NULL/无值语义一族的唯一裁决入口,并案覆盖:

    三单同源(两值 JS vs 三值 SQL、键存在 vs 有值),分开裁只会多付三次上下文成本;正文与 #5296 的逐算子极性表、#5299/#5369 的实测矩阵已足够裁决。裁决后:driver-sql / formula 半边入队,driver-memory / mongodb 半边按 #5499 挂 hold,并把结论写进 #5239 的 FILTER_LOGIC_CASES 扩表(今天刻意不含 null 处理,无门禁可发现此类分叉)。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  6. claude commented on Aug 6, 2026

    @claude
    Contributor

    裁决(2026-08-06):方案 A——$ne / $nin / $notContains 非否定路径 NULL-safe。

    driver-sql 编译改为 NULL-safe(col IS NULL OR col <> v;优先用方言等价物 IS DISTINCT FROM / IS NOT / <=>,逐方言处理以控索引代价),向作者直觉语义收敛——!= 'won' 包含无值行;formula 现行为即目标语义。与 #5146 对 $not 的 NULL-safe 裁决同向,消除 RLS 写侧 check 与读侧 SQL 对同一规则答案不同的安全一致性问题;#5296 的逐算子极性表直接复用。

    本裁决按分诊并案口径覆盖 #5299(「字段没有值」三格)与 #5369($exists 非布尔比较值,套用 #5347-A)。交付物必须含 FILTER_LOGIC_CASES 的 null 用例扩表——否则同族分叉继续零门禁。driver-memory / mongodb 半边按 #5499 投入冻结:pin 现状即可,不改行为。量级 M。

    经办:PM 会话 session_01GcjbQLUQKysMU9uXB34iyv;维护者 2026-08-06 审阅决策简报后授权按建议执行(否决窗口:可评论/重开推翻)。


    Generated by Claude Code

  7. added
    pm:queueReady for the PM dispatch loop
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Aug 6, 2026
  8. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    【裁决落地】维护者 2026-08-06 批复全舰队决策箱评估报告(批复「同意」),本单(NULL/无值语义族唯一裁决入口,并案 #5299/#5369)裁定:

    裁方向 ①(NULL-safe)——非否定路径 $ne/$nin/$notContains 全驱动统一排除 NULL 行,与 #5146 的 $not 裁决同向:同族同答案,消灭 RLS 写读两侧语义分叉。并案 #5299/#5369 按同口径收敛,结论写进 #5239 FILTER_LOGIC_CASES。

    第一棒(落地前置):drivers 座位先出一页成本清单——普通查询 SQL 形状/索引影响面(NULL-safe 谓词对现有索引命中的影响);量级无意外即落实现,发现量级意外则回报维护者再确认后动工。

    范围约束:driver-memory / driver-mongodb 半边维持 #5499 冻结(其行为修正随解冻批次);driver-sql + formula 是本裁决的实施面。

    流转:摘 needs-user-decision → pm:queue,归 drivers 车道。

    评估与落地会话:session_01N3uGFF8teXbpgtbEJ1aYXu


    Generated by Claude Code

  9. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 6, 2026
  10. 13 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

pm:dispatchedDispatched to a dev agent by /pm-dispatchtarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions