You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
packages/drivers/driver-turso/src/remote-transport.ts:1160-1169 —— 注释明写「NULL semantics are SQL's, matching what whereNot emits locally」,并 clauses.push(NOT (...));
packages/drivers/driver-turso/src/remote-transport-not-operator.test.ts:47-53 —— 有一条用例把这个语义钉住:「NULL rows follow the SQL family ... remote mode is pinned to the family it belongs to, so local and remote SQL agree」。
出自 #5298「第一棒:成本清单」的发射点清点(纯读调查),范围外发现,按 Prime Directive #10 记录,不指派。
事实(origin/main
5c94f833c,静态对读 + 现有测试自证)#5146已裁定$not取 NULL-safe 语义,PR #5296 在SqlDriver.applyFilterCondition落地(把$not的每个叶子改写成 TOTAL 谓词)。TursoDriver extends SqlDriver,所以 local 模式继承了这个修复;但 remote 模式走的是RemoteTransport.buildWhereSQL,一段完全独立的 SQL 生成器,它的$not分支逐字保留旧的三值语义:packages/drivers/driver-turso/src/remote-transport.ts:1160-1169—— 注释明写「NULL semantics are SQL's, matching whatwhereNotemits locally」,并clauses.push(NOT (...));packages/drivers/driver-turso/src/remote-transport-not-operator.test.ts:47-53—— 有一条用例把这个语义钉住:「NULL rows follow the SQL family ... remote mode is pinned to the family it belongs to, so local and remote SQL agree」。那句注释和那条 pin 是在 #5146 裁决之前写的,当时 driver-sql 的
whereNot确实也丢 NULL 行,所以「local 和 remote 一致」成立。PR #5296 之后前提失效,但 remote 侧没有跟进,pin 也没更新 —— 于是今天:{ $not: { stage: 'won' } },stage 为 NULL 的行同一个驱动、同一条 filter、按连接模式给两个答案。
为什么值得修
!expr的 RLS read scope 会 lower 成{ $not: {...} }(packages/formula/src/cel-to-filter.ts:205),所以这是「同一条权限规则按部署模式放行不同的行集」,与$not的语义在 driver-sql 与 driver-memory / formula 之间分叉:NULL 行的去留相反,$not: {}一个是 TRUE 一个是 FALSE #5146 裁决时给出的理由逐字相同。turso-filter-logic-conformance.test.ts(local)与turso-remote-filter-logic-conformance.test.ts(remote)都跑FILTER_LOGIC_CASES,但那张表刻意不含 null 行(packages/spec/src/data/filter-logic-conformance.ts:79-83自陈),所以两个模式的分叉对 conformance 不可见。packages/spec/src/data/filter-logic-conformance.ts:70-77目前写着$not的语义在 driver-sql 与 driver-memory / formula 之间分叉:NULL 行的去留相反,$not: {}一个是 TRUE 一个是 FALSE #5146 这一族「every surface answers this family the same way — no backend blocker remains」。这句话把 turso remote 漏掉了,应当一并订正。修法方向(不代裁决)
buildWhereSQL的$not分支复用sql-driver.ts的nullSafeNegationOperand/nullValueSatisfiesOperator极性表(packages/drivers/driver-sql/src/sql-driver.ts:1003-1169)。注意RemoteTransport不依赖 driver-sql 的私有函数,需要么导出、么按service-analytics/src/read-scope-sql.ts:374-525的先例第二次实现并加互钉测试。同时要改的是那条 pin:
remote-transport-not-operator.test.ts里断言 NULL 行被排除的用例,方向会反过来(before 绿 / after 红 → 改成 after 绿),这是预期的反向验证方向,不是回归。关联
#5146 / PR #5296(裁决与 driver-sql 落地)、#5298(非否定路径的同族裁决,本发现的出处)、#5239(
FILTER_LOGIC_CASES扩表 —— null 行入表后本条会自动被顶出来)、#5769(RemoteTransport 的另一条 local/remote 分叉,同一个「独立发射器没跟上」家族)。