#3839 收敛了空分组桶的键(两边现在都是真 null)。同一个函数里紧挨着的非空分支还有第二条分歧,爆炸半径更大,#3839 刻意没碰。
packages/objectql/src/in-memory-aggregation.ts 的 projectGroupValue:
return v == null ? null : String(v);
String(v) 把每一个分组键都强转成字符串。下推 SQL 不转 —— 驱动原样交出列值。
实测(better-sqlite3,两行)
groupBy ['qty'] SQL: 3(number) in-memory: "3"(string) ❌ DIVERGES
groupBy ['won'] SQL: 0(number) 1(number) in-memory: "false"(string) "true"(string) ❌ DIVERGES
- 数字列:类型分歧。
3 vs "3"。
- 布尔列:语义分歧,不只是类型 —— SQLite 存 0/1,SQL 侧交出
0/1,内存侧交出 "false"/"true"。这两组字面量没有任何重叠,任何按键查表/配色/取标签的消费方,换一条路就全部落空,不是"格式不一样"而是"认不出来"。
选路条件与 #3839 完全相同(engine.aggregate:驱动是否声明该 granularity、是否非 UTC 时区、驱动有没有原生 aggregate),所以同一份数据换个时区、换个粒度、换个驱动就换一种键形状。
#3839 的爆炸半径是可枚举的:三个仓里没有任何生产代码依赖 '(null)',而且所有消费方本来就写的是 == null。这一条不是 —— 它动的是每一个非空桶的键,包括 select 选项值、lookup 外键 id、布尔、数字。要先确认:
- 有没有消费方依赖"键一定是 string"(例如直接
key.startsWith(...) / 拿去做对象属性名 / localeCompare 排序)?
- 反过来,
dimension-labels.ts 把桶键翻译成显示标签、bucketKeyToCalendarRange 反解日期桶键,这些拿到 number/boolean 还对不对?
- 收敛方向:让内存侧不转(与 SQL 对齐,类型更诚实),还是让 SQL 侧转成字符串(每个驱动都要实现,且会把数字键变成字符串键)?
日期分桶那一支不受影响 —— bucketDateValue 本来就产出规范字符串标签,两边一致。
门
checkDateBucketParity(packages/verify/src/date-bucket-parity.ts)只覆盖日期分桶,天然够不着。#3839 新加的 packages/qa/dogfood/test/empty-group-bucket-parity.test.ts 覆盖了普通 groupBy 的空桶,把它扩到非空桶是最省的落点。
注意:那个门里的 labelCounts / shape 目前用 String(...) 折叠标签,会把这条分歧抹平。要守这一条必须连键的类型一起比 —— 不能只比字面量。
不阻塞任何东西:度量值两边一直都对,坏的只有键的形状。
#3839 收敛了空分组桶的键(两边现在都是真
null)。同一个函数里紧挨着的非空分支还有第二条分歧,爆炸半径更大,#3839 刻意没碰。packages/objectql/src/in-memory-aggregation.ts的projectGroupValue:String(v)把每一个分组键都强转成字符串。下推 SQL 不转 —— 驱动原样交出列值。实测(better-sqlite3,两行)
3vs"3"。0/1,内存侧交出"false"/"true"。这两组字面量没有任何重叠,任何按键查表/配色/取标签的消费方,换一条路就全部落空,不是"格式不一样"而是"认不出来"。选路条件与 #3839 完全相同(
engine.aggregate:驱动是否声明该 granularity、是否非 UTC 时区、驱动有没有原生 aggregate),所以同一份数据换个时区、换个粒度、换个驱动就换一种键形状。为什么 #3839 没有一起修
#3839 的爆炸半径是可枚举的:三个仓里没有任何生产代码依赖
'(null)',而且所有消费方本来就写的是== null。这一条不是 —— 它动的是每一个非空桶的键,包括 select 选项值、lookup 外键 id、布尔、数字。要先确认:key.startsWith(...)/ 拿去做对象属性名 /localeCompare排序)?dimension-labels.ts把桶键翻译成显示标签、bucketKeyToCalendarRange反解日期桶键,这些拿到 number/boolean 还对不对?日期分桶那一支不受影响 ——
bucketDateValue本来就产出规范字符串标签,两边一致。门
checkDateBucketParity(packages/verify/src/date-bucket-parity.ts)只覆盖日期分桶,天然够不着。#3839 新加的packages/qa/dogfood/test/empty-group-bucket-parity.test.ts覆盖了普通groupBy的空桶,把它扩到非空桶是最省的落点。注意:那个门里的
labelCounts/shape目前用String(...)折叠标签,会把这条分歧抹平。要守这一条必须连键的类型一起比 —— 不能只比字面量。不阻塞任何东西:度量值两边一直都对,坏的只有键的形状。