Skip to content

driver-memory analytics 面的 generateSqlin/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

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

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

未验证的部分

建议(不代裁决)

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

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

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