Skip to content

driver-memory analytics 面的 generateSql 对 in/notIn/set/notSet 输出错误 SQL:回退成 = 且只取第一个值($in: ['100','200'] → WHERE code = '100') #5433

Description

@os-zhuang

做 #5373(cube 比较数往返有损)时,为了钉住 generateSql 这个出口,逐个实测了它对各算子输出的 WHERE 子句。发现的这一条不属于 #5373 的范围面 —— #5373 裁的是比较数(值)层面的编码,而这一条在算子层面,修复前后都存在,与那个编码无关。按 Prime Directive #10 单独记在这里,unassigned。

位置

packages/plugins/driver-memory/src/memory-analytics.ts:

  • operatorToSql(约 :790)—— 映射表里只有 8 个算子:equals / notEquals / contains / notContains / gt / gte / lt / lte,并以 return opMap[operator] || '=' 兜底;
  • generateSql 的 WHERE 构建循环(约 :450)—— 只取 values[0]。

MONGO_TO_CUBE_OPERATOR 声明本面支持 11 个算子,其中 in($in)、notIn($nin)、set($exists)在 operatorToSql 里一个都没有。

现象(实测)

3 行固定数据,code 是 TEXT 列,分别存 '100' / '200' / '100':

where query() 取到 generateSql() 输出的 WHERE 该 SQL 若执行会取到
{code: {$in: ['100','200']}} 3 行(正确) WHERE code = '100' 2 行
{code: {$nin: ['100']}} 1 行(正确) WHERE code = '100' 2 行
{code: {$exists: true}} 3 行(正确) WHERE code = 1 —

两个缺陷叠在一起:

  1. 算子被兜底成 =。in / notIn 没有映射,|| '=' 把它们全变成等值比较 —— notIn 因此输出了与 in 完全相同的子句,语义正好相反。set($exists)同理,WHERE code = 1 与「该字段存在」毫无关系。
  2. 只取第一个比较数。values[0] 让 $in 的其余候选值直接消失,即使算子映射对了也还是错的。

注意方向:query() 那一半是对的($in/$nin 有各自的分支,$exists 也有),所以这是同一个 driver 的两个出口对同一个 where 给出不同含义 —— #5240 为本包立下的不变量所禁止的形状,只是这次分叉在 generateSql 一侧。

为什么是 bug

generateSql 是 IAnalyticsService 的公开方法,其返回值也是 AnalyticsResult.sql 承诺的「生成的 SQL」。它的用途是调试/透明性 —— 让作者看懂自己的查询到底问了什么。一个把 notIn 显示成 in、把三个候选值显示成一个的 SQL,恰恰在作者最需要它说实话的时候说了假话。

同时这是 declared ≠ enforced 的又一处:MONGO_TO_CUBE_OPERATOR 声明本面支持这些算子,query() 也确实支持,只有这一个出口没跟上。

未验证的部分

建议(不代裁决)

两条都在 generateSql 一侧,建议一起裁:补齐 operatorToSql 的映射(in → IN、notIn → NOT IN、set → IS NOT NULL、notSet → IS NULL),并让 WHERE 构建循环按算子决定用 values[0] 还是整个 values 列表。若认为「调试用 SQL 不值得维护」,那另一条路是让 generateSql 对无法忠实表达的算子拒收,与 #5345 同款 —— 但那会拒掉本面 query() 明明能算的查询,恐怕不是想要的答案。

关联:#5373(同函数、同一轮核对里发现;它裁的是比较数层,本条是算子层)、#5374(同为本面算子层缺陷,那条在 mingo 出口)、#5345(本面算子层的第一轮裁决,只裁了「无映射就丢弃」)、#5240(本包两面不得分叉)。

Activity

  1. baozhoutao commented on Aug 5, 2026

    @baozhoutao
    Contributor

    分诊(cli 车道 PM,session_016FNvXhtSdnEGEfLEsMmvxh,2026-08-05,代打路由标签):入队 pm:queue,domain:engine。锚定:落点 packages/plugins/driver-memory(analytics 面 generateSql),按域表归 engine 车道。标注系按标题级信息路由(具名位置 + 具体错误输出),engine 车道认领前照例通读正文与评论再定派发形状;与刚合并的 #5375(同包 analytics 面)可能同文件,认领时先核 churn。打标 ≠ 认领,本车道不认领。


    Generated by Claude Code

  2. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    转 pm:on-hold(2026-08-05,维护者裁决,锚点 #5499):driver-memory 为早期测试便利组件,方向已定 sqlite 内存模式替代,缺陷修复投入冻结。重启条件:替代在测试面完成后随锚点整批关闭;若该缺陷被发现影响 CI 判绿正确性,按 restore-invariant 例外升级。不派发、不催。会话:session_01N3uGFF8teXbpgtbEJ1aYXu


    Generated by Claude Code

  3. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    按 #5499 重启条件 + #5704 收口关闭(not planned):维护者 2026-08-06 裁定 driver-memory 的测试职能由 sqlite :memory: 替代,迁移已完成(PR #5715 / #5797 / #5806,全仓 makeMemoryDriver 归零、测试面仅存 Q2-B 裁定保留的参照臂);本包处于投入冻结(#5499),analytics 面缺陷不再计划修复。子单 #5444(同函数、同映射表)随本单同批关闭。若维护者后续裁定包本体保留并解冻,可重开。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions