做 #5374 (mingo 出口的 $notContains 编译成裸 {$not: 'x'})时,顺手把同一个 where 在 generateSql 出口的回显也测了。这一条不属于 #5374 的范围面 —— 那一条在 mingo 出口,这一条在 SQL 回显出口,#5374 修好之后完整存在。
作为 #5433 的 sub-issue 而不是独立 issue,因为修复落点完全在 #5433 的完成范围之内:同一个 operatorToSql 映射表 + 同一个 generateSql 的 WHERE 构建循环。分开修会让同一个函数被改两次。unassigned。
位置 packages/plugins/driver-memory/src/memory-analytics.ts:
operatorToSql(约 :800)—— 'contains': 'LIKE'、'notContains': 'NOT LIKE';generateSql 的 WHERE 构建循环(约 :450)—— 把比较数原样交给 toSqlLiteral,不加通配符。现象(实测) 3 行数据,name 分别为 alpha / beta / gamma(只有 beta 含 et):
wherequery() 取到generateSql() 输出的 WHERE该 SQL 若执行会取到 {name: {$contains: 'et'}}[2](正确)WHERE name LIKE 'et'0 行 {name: {$notContains: 'et'}}[1,3](#5374 修复后正确)WHERE name NOT LIKE 'et'3 行
SQL 的 LIKE 'et' 没有 %,语义是等值匹配 (等价于 = 'et'),不是子串匹配。正确的回显应当是 LIKE '%et%' / NOT LIKE '%et%',比较数里的 % 和 _ 还需要转义(否则作者写的 50% 会变成通配符)。
为什么是 bug 回显的用途就是让作者看懂自己问了什么。 generateSql 是 IAnalyticsService 的公开方法,其返回值也是 AnalyticsResult.sql 承诺的「生成的 SQL」。一个把「包含 et」显示成「等于 et」的 SQL,恰恰在作者最需要它说实话的时候说了假话 —— 与 /analytics/sql 回显的 SQL 丢掉 $startsWith / $endsWith 谓词:回显比实际执行的查询更宽,无法复现结果 #5333 同类,只是那一条是谓词整个丢掉,这一条是谓词还在但含义变了。两个出口对同一个 where 给出不同含义 ,{ field: {} }(零个操作符的字段约束)在同仓有三个答案:driver-sql 组合子内 TRUE、顶层抛 INVALID_FILTER、formula/driver-memory FALSE #5240 为本包立下的不变量所禁止的形状,与 driver-memory analytics 面的 generateSql 对 in/notIn/set/notSet 输出错误 SQL:回退成 = 且只取第一个值($in: ['100','200'] → WHERE code = '100') #5433 正文里 in/notIn/set 那三条并列。大小写这一半是巧合对上的。 mingo 出口是 /…/i(driver-memory analytics 面的 $notContains 编译成裸 mingo {$not: 'x'},该谓词不约束任何行 —— 结果被放大到全表 #5374 起借用 driver 自己的 filterSubstringPattern),而 SQLite 的 LIKE 对 ASCII 默认就不区分大小写 —— 所以这一维恰好一致,但那是两个互不相干的默认值碰巧撞上,不是任何人写下的约定。修 % 的时候值得顺便把它写成约定。未验证的部分 关联:父 issue #5433 (同函数、同一映射表)、#5374 (同一 where 的另一个出口)、#5333 (回显与执行不一致)、#5240 。
做 #5374(mingo 出口的
$notContains编译成裸{$not: 'x'})时,顺手把同一个where在generateSql出口的回显也测了。这一条不属于 #5374 的范围面 —— 那一条在 mingo 出口,这一条在 SQL 回显出口,#5374 修好之后完整存在。作为 #5433 的 sub-issue 而不是独立 issue,因为修复落点完全在 #5433 的完成范围之内:同一个
operatorToSql映射表 + 同一个generateSql的 WHERE 构建循环。分开修会让同一个函数被改两次。unassigned。位置
packages/plugins/driver-memory/src/memory-analytics.ts:operatorToSql(约 :800)——'contains': 'LIKE'、'notContains': 'NOT LIKE';generateSql的 WHERE 构建循环(约 :450)—— 把比较数原样交给toSqlLiteral,不加通配符。现象(实测)
3 行数据,
name分别为alpha/beta/gamma(只有beta含et):wherequery()取到generateSql()输出的 WHERE{name: {$contains: 'et'}}[2](正确)WHERE name LIKE 'et'{name: {$notContains: 'et'}}[1,3](#5374 修复后正确)WHERE name NOT LIKE 'et'SQL 的
LIKE 'et'没有%,语义是等值匹配(等价于= 'et'),不是子串匹配。正确的回显应当是LIKE '%et%'/NOT LIKE '%et%',比较数里的%和_还需要转义(否则作者写的50%会变成通配符)。为什么是 bug
generateSql是IAnalyticsService的公开方法,其返回值也是AnalyticsResult.sql承诺的「生成的 SQL」。一个把「包含 et」显示成「等于 et」的 SQL,恰恰在作者最需要它说实话的时候说了假话 —— 与/analytics/sql回显的 SQL 丢掉$startsWith/$endsWith谓词:回显比实际执行的查询更宽,无法复现结果 #5333 同类,只是那一条是谓词整个丢掉,这一条是谓词还在但含义变了。where给出不同含义,{ field: {} }(零个操作符的字段约束)在同仓有三个答案:driver-sql 组合子内 TRUE、顶层抛 INVALID_FILTER、formula/driver-memory FALSE #5240 为本包立下的不变量所禁止的形状,与 driver-memory analytics 面的generateSql对in/notIn/set/notSet输出错误 SQL:回退成=且只取第一个值($in: ['100','200']→WHERE code = '100') #5433 正文里in/notIn/set那三条并列。/…/i(driver-memory analytics 面的$notContains编译成裸 mingo{$not: 'x'},该谓词不约束任何行 —— 结果被放大到全表 #5374 起借用 driver 自己的filterSubstringPattern),而 SQLite 的LIKE对 ASCII 默认就不区分大小写 —— 所以这一维恰好一致,但那是两个互不相干的默认值碰巧撞上,不是任何人写下的约定。修%的时候值得顺便把它写成约定。未验证的部分
generateSql对in/notIn/set/notSet输出错误 SQL:回退成=且只取第一个值($in: ['100','200']→WHERE code = '100') #5433 正文的同一条限制:本仓库内没有任何地方执行generateSql的输出,所以目前只是「显示错误」而非「取到错误行集」。这一点显著影响严重度。%/_的转义在toSqlLiteral里该怎么表达(需要ESCAPE子句还是各方言自理),只指出当前完全没有转义。关联:父 issue #5433(同函数、同一映射表)、#5374(同一
where的另一个出口)、#5333(回显与执行不一致)、#5240。