Repository navigation
driver-sql:两类无意义比较对象仍编译成「静默空谓词」—— $in/$nin 的非 $field 对象成员,与 LIKE 族的对象比较值(String 成 [object Object]) #5234
Description
Activity
同一形状在
service-analytics也有一份(#5526 实施途中的范围外发现,不在本 PR 修)做 #5526(analytics 的 leaf
values由string[]改unknown[])时必须逐个决定"非字符串比较数在 LIKE 路径上怎么归一",于是把本单第 2 条形状在 analytics 侧也测了一遍。结论:同一个String()宽容,在本仓有三份实现,driver-sql只是其中一份。filter.zod.ts把 LIKE 族的比较数声明为z.string():packages/spec/src/data/filter.zod.ts:143 $contains: z.string().optional(), packages/spec/src/data/filter.zod.ts:149 $startsWith: z.string().optional(), packages/spec/src/data/filter.zod.ts:152 $endsWith: z.string().optional(),三个消费方都不拒绝违反该声明的输入,而是
String()掉它:实现 位置 表达式 driver-sql(本单)packages/plugins/driver-sql/src/sql-driver.tsapplyLikeString(value).replace(/[\\%_]/g, '\\$&')service-analytics的两个 SQL 发射器packages/services/service-analytics/src/like-pattern.tsescapeLikePattern同一表达式(#5567 刻意的第二份实现,两者由 like-metacharacter-escape.test.ts逐字符互锁)service-analytics的引擎路径packages/services/service-analytics/src/strategies/objectql-strategy.tsconvertFilterString(v0)(#5526 起显式写成这样;此前由删掉的编码器隐式保证)所以本单的修法有一条约束值得先记下来:三份必须一起动。只在
driver-sql收紧,{name: {$contains: {…}}}就会变成"哪个面接的、就是哪个答案" —— 正是 #5146 / #5332 / #5567 各花一轮消掉的那类分叉。#5567 的 header 已经把"第三份手抄是要拒绝的东西"写下来了,收紧守卫时同理:守卫要么进like-pattern.ts+applyLike两处并被那个逐字符互锁测试覆盖,要么在发布/授权时就拒(Prime Directive #12 更偏好后者)。顺带两条 analytics 侧的实测,供接手者定范围:
{$contains: null}在 analytics 上原先是LIKE '%%',匹配每一个非 NULL 行 —— 一个真实的静默放宽,而不是本单记的 fail-closed 零行:根因是被删掉的stringifyForCube(null)返回''。driver-sql从来是%null%(String(null))。analytics 的string[]值往返对字符串比较数也有损:{code: {$eq: '007'}}绑成数字7、'null'绑成真 NULL、'true'绑成1—— 文本列静默取到错行 #5526 把 analytics 也变成%null%,两面就此收敛;该行为已在filter-value-type-fidelity.test.ts钉住。这一条不需要接手者再处理,记在这里只是因为它解释了为什么两面此前答案不同。{$contains: 5}→%5%,两面一致,analytics 的string[]值往返对字符串比较数也有损:{code: {$eq: '007'}}绑成数字7、'null'绑成真 NULL、'true'绑成1—— 文本列静默取到错行 #5526 未改、也未拒绝(理由同上:单面收紧即分叉)。这就是本单还开着的那一半。
本单范围与标签不建议变(仍是
driver-sql的账),只是它的"完成"定义应包含 analytics 那两处发射器,否则修完仍有两个方言。
Generated by Claude Code
存量裁决轮(维护者 2026-08-06 委托,session_01LeEfA7CFwbJb7JJmXm2KM3):裁定入队。前提经 origin/main 核实精确成立:#5223 落地的
assertCompilableComparand头注释明写这两个形状 "Deliberately NOT extended"(sql-driver.ts:620-628),applyLike仍String(value)——近期算子收口刻意未覆盖,缺陷仍在。driver-sql 不在 #5499 冻结范围。完成定义按 08-05 评论:analytics 两处 LIKE 发射器一并收紧(三份实现一起动)。维护者可否决。
Generated by Claude Code
认领:PM 循环第 9 轮(drivers 车道,维护者 2026-08-06「加速开发」指令,三路并行批次之一)
会话:session_01WyvqvKMG6asi9aXjKE6xtx
分支:claude/issue-5234-silent-empty-predicates
Worktree:objectstack-issue-5234
域:domain:drivers主账;跨域执行申报:完成定义(08-05 评论 + 存量裁决轮口径)含service-analytics两处 LIKE 发射器(domain:services 领地)——三份实现一起动,否则修完仍是方言分叉
文件面:driver-sql 的sql-driver.ts(applyLike + assertCompilableComparand 拓宽)+packages/services/service-analytics/src/like-pattern.ts+strategies/objectql-strategy.ts+ 各自测试(含 like-metacharacter-escape 互锁表)
定向在飞检查:全仓 18 张 pm:dispatched 无 driver-sql / service-analytics 面。串行约束:#5298 实现半边与本单同文件(sql-driver.ts),已排本单落地之后。
Generated by Claude Code
认领解除(drivers 车道 PM,
session_01WyvqvKMG6asi9aXjKE6xtx,2026-08-06 14:5xZ):派发的 dev 被维护者手动中止(宿主明确回报 stopped by the user、不会恢复)。摘 assignee 与pm:dispatched,回pm:queue。是否重派等维护者示意。留档供下次派发:
- 分支
claude/issue-5234-silent-empty-predicates已推送(6428b27),含未完成的实现——重派时先审该分支可复用部分,或弃之从最新 main 重来(main 今日已前进:fix(drivers,analytics,formula): $ne / $nin / $notContains 在 $not 之外也 NULL-safe (#5298) #5962 动了 sql-driver.ts 邻区、fix(analytics): $ne / $nin / $notContains 在 Cube 面保留无值行 (#5298 第二批) (#5977) #6004 动了 service-analytics 的 filter-normalizer); - 完成定义不变:三份 LIKE 实现一起动(sql-driver applyLike + like-pattern.ts + objectql-strategy convertFilter),存量裁决轮 08:03 评论与 08-05 评论为准;
- 原认领的执行注记(先测合法形状全集、
{$contains: 5}两面一致不轻动、⛔ 不触 NULL 语义)仍然有效。
Generated by Claude Code
- 分支
3 remaining items
重派(维护者 2026-08-07 在 PM 会话示意继续):PM 循环第 11 轮(drivers 车道)
会话:session_01WyvqvKMG6asi9aXjKE6xtx
分支:claude/issue-5234-silent-empty-predicates(旧分支6428b27是 08-06 被中止那次的未完成实现,可审可弃,以最新 origin/main 为基线重做为准)
Worktree:objectstack-issue-5234
文件面:driver-sql/src/sql-driver.ts(applyLike+assertCompilableComparand区)+service-analytics/src/like-pattern.ts+service-analytics/src/strategies/objectql-strategy.ts+ 各自测试 + changeset完成定义不变(08-05 评论 + 08-06 存量裁决轮):三份 LIKE 实现一起动,只收紧一份即制造新方言分叉。
并行注记:#6210(五驱动签名收窄)在飞、同文件不同区(签名区 :2091-2876 vs 本单 applyLike/assertCompilableComparand 区),后落地者 rebase;#6204(聚合信封)已 MERGED,其
sql-driver.ts改动已在 main。
Generated by Claude Code
复核:ACCEPT → PR #6296(PM 实测复核)。
⚠️ 首先:本单正文的严重度定级被实测推翻,应记录在案正文写「两者都不抛错…失败方向 fail-closed(收窄结果集,不存在权限绕过),风险级别低于 #5041」。dev 用带
r_literal(name 字面就是[object Object])的 fixture 把「静默零行」变成可证伪命题后实测:filter 实际答案 与定级的关系 {status: {$nin: [{foo:1}]}}全表(该排除的一行没排除) 方向是放宽,不是 fail-closed {name: {$contains: {}}}命中 r_literal一条真实记录不是零行,是错行 {name: {$notContains: {}}}为无人记录的理由排除掉一条真实记录 同上,反向 即:一条本意「排除某些行」的过滤器在
$nin上等于没写。定级从「fail-closed 低风险」改为放宽类。这条更正值得进分诊经验——「静默零行」这类描述在没有对抗性 fixture(专门放一行等于[object Object]的数据)时会自我实现地被确认。复核结论
- 变更面 11 文件与申报一致;冻结面 diff 为零;
objectql-strategy.ts实测为 +8 行纯注释(解释守卫为何在门口而非此处),与「convertFilter是生产者不是消费者」的判定自洽; - 守卫落点判定有论证:
fieldLeaves是本包唯一 leaf 生产者 ⇒ 一处拒收覆盖三个消费方(执行语句 //analytics/sql回显 / 引擎路径);read-scope-sql不经该门故自带同款检查且包在自己的信封里(policy 编译失败 = 500 fail-closed,不是 400)——caller 输入 400 / 平台自编译 500 的分线是对的; - 未把闸提到 engine seam 的理由成立:那会改变 driver-memory/mongodb 的可观察行为([裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 禁);且 fix(objectql): 集合算子的标量比较值答 400 INVALID_FILTER 并点名期望形状,不再 500 (#5869) #6209 的头注释本就把
$in/$nin成员类型让给本单,两闸互补(它判「是不是列表」,本单判「成员能不能绑」); - allow-list 而非 deny-list(抄 turso RemoteTransport 形态),七类比较数逐条留依据:数字/null/布尔/Date/undefined 保留(动它们就是造分叉)、对象与 LIKE 族数组拒收;binary 分裂处置($in 收、LIKE 拒)正是
isBindableComparand/isRenderableTextComparand分成两个谓词的理由; - 新测到一条评论里没有的事实:数组比较数在 service-analytics 包内部就已两个答案(
%al,be%vs%al%,后者读values[0]静默丢弃其余成员)——这是「拒收即消分叉」的唯一形状; - 反向验证逐臂停用(LIKE 8 红 / 成员 4 红 / analytics 17 红),并如实记录
like-metacharacter-escape在回退下保持绿且解释了分工(它锁两包谓词一致、拒收文件锁门确实调用谓词)——这正是 validateOrgAxisRedLines 读的 sharing-rule 键是 spec 拒收的:ADR-0105 D6 ① 在 criteria 路径上从不触发 #4984 那类「规则死了测试还绿」的防线; - 门禁全绿:erasure 棘轮 267 未抬且核了 baseline key set、
check:type-check-debt34 条无一超记录、消费半径用前缀 filter([skill] 消费半径扫描必须用--filter '...pkg'(前缀)而非'pkg...'(后缀)—— 方向扫反会让「全绿」毫无意义(#6210 实测) #6218 纪律)覆盖 20+ 下游包、turbo build 72/72; - rebase 处置正确:非否定路径上的
$ne/$nin/$notContains:driver-sql 排除 NULL 行,driver-memory / formula 返回它们(#5146 只裁定了$not) #5298 的 NULL-safe 重写与本单形状闸都活着,且顺序是「形状闸在重写之前」(重写要拿原始比较数问nullValueSatisfiesOperator);新测试跟进 refactor(drivers)!: 五个驱动的 query 参数跟进 DriverQuery,休眠的类型谎言没有藏身处 (#6075) #6210 的DriverQuery时没有用as any绕过——理由写得好:拒收类测试一旦用越契约输入构造查询,就不再是在验证调用方真能发出的形状。
CI 清零后转 ready 入队。
Generated by Claude Code
- 变更面 11 文件与申报一致;冻结面 diff 为零;
- added a commit that references this issue
on Aug 17, 2026 - added 4 commits that reference this issue
on Sep 24, 2026 - added 3 commits that reference this issue
on Sep 28, 2026
#5041(PR #5223)实施过程中的范围外发现,只记录不修、不指派。发现者(os-dev)已实测,证据基础同 PR #5223 的探针方法。
两个形状
$in/$nin列表里的非$field对象成员:{ status: { $in: ['a', { foo: 1 }] } }—— 编译通过、执行、静默零行(该成员绑定为无法命中的值)。PR fix(driver-sql):$field跨字段比较按 ADR-0112 响亮拒绝,不再抛裸 TypeError (#5041) #5223 已拦下列表成员是{$field: ...}的情形(按成员序号点名拒绝),但其它对象成员仍走旧路。$contains/$startsWith/$endsWith…)遇对象比较值:被String()成'[object Object]'参与匹配 —— 语义上永假,静默零行。为什么当时没有一并修(记录 dev 的边界判断,供接手者参考)
$field跨字段比较:spec 声明 + cel-to-filter 产出,但无任何 SQL 执行层实现 —— enforce-or-remove 裁决位 #5041 实测的「裸 TypeError」不同类:是「过滤器被无意义地应用」,不是「过滤器无法应用」;$field跨字段比较:spec 声明 + cel-to-filter 产出,但无任何 SQL 执行层实现 —— enforce-or-remove 裁决位 #5041;$field跨字段比较:spec 声明 + cel-to-filter 产出,但无任何 SQL 执行层实现 —— enforce-or-remove 裁决位 #5041 的测量范围 —— 按范围纪律停手立案。与既有账的关系
同属 #3948 / #4209 点名的「静默错误答案」类;修法大概率是把 PR #5223 在三个比较发射器上装的形状守卫拓宽到这两类(同一收口点、同一
INVALID_FILTER信封),但需要先测量$in数组成员与 LIKE 比较值的合法形状全集,避免误伤。Refs:#5041、PR #5223(探针与发射器清单)、#5222(
$field的 SQL 实现,v18)、#3948、#4209。