Commit 5d4de37
Three code paths produce a `groupBy` key and no two agreed:
qty (number) won (boolean)
find() 3 number true boolean
aggregate() pushed down 3 number 0/1 number
in-memory fallback '3' string 'false'/'true' string
Two independent causes. `applyInMemoryAggregation` ran every key through
`String()`, which the pushed-down path never did. And the pushed-down path
returns raw builder output: #3797 taught it to present temporal columns the way
`formatOutput` does on a `find()` row, but not the boolean and numeric repairs,
so a SQLite boolean — no native type, stored 0/1 — surfaced as an integer from
`aggregate()` and a real boolean from `find()`.
`engine.aggregate` picks between the two aggregate paths per query, so the same
column changed shape with no change to the data or the query.
The measures were always right, which is why nobody noticed. What broke was
downstream code probing a raw `Map` keyed by the value's own type — `Map` lookup
is SameValueZero, so '1' never finds 1: select-option labels fell back to raw
values, lookup labels missed whenever the referenced object had a numeric id
(routine for external objects), and cross-object rebucketing filed every row
under RESTRICTED_BUCKET — one bar, correct grand total, no error. A boolean
dimension drilled from the in-memory path also sent { won: 'true' } to SQLite,
which an INTEGER column can never match.
- `applyInMemoryAggregation` emits the value verbatim; its rows are find()
output, so passing through is what makes the key equal the column's read shape.
- The internal bucket id is type-preserving, so 1 and '1', true and 'true' stay
distinct groups. BigInt is encoded explicitly — JSON.stringify throws on it,
and a value that bucketed fine under String() must not start crashing.
- `SqlDriver.aggregate`/`.distinct` present group keys and min/max with the same
rules `formatOutput` applies, generalizing #3797 to boolean and numeric
columns. The protected helpers are renamed to match (temporalFieldKind →
readPresentationKind, presentTemporalValue → presentReadValue,
presentTemporalColumns → presentReadColumns) and the kind union is exported.
Date-bucketed groupBy is unaffected: both sides already produce canonical string
labels, and #3839 pinned their empty bucket.
Gate: group-key-read-shape-parity.test.ts measures both aggregate paths against
find() for number, boolean and text columns on driver-sql and
driver-sqlite-wasm, asserting the runtime TYPE — folding through String() is the
reflex that hid this and would pass against the bug. Each half was confirmed to
redden the gate on its own.
Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e47b342 commit 5d4de37
5 files changed
Lines changed: 435 additions & 49 deletions
File tree
- .changeset
- packages
- objectql/src
- plugins/driver-sql/src
- qa/dogfood/test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
115 | 115 | | |
116 | 116 | | |
117 | 117 | | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
118 | 181 | | |
119 | 182 | | |
120 | 183 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
43 | 57 | | |
44 | 58 | | |
45 | 59 | | |
| |||
75 | 89 | | |
76 | 90 | | |
77 | 91 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | | - | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
83 | 97 | | |
84 | 98 | | |
85 | 99 | | |
| |||
98 | 112 | | |
99 | 113 | | |
100 | 114 | | |
101 | | - | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
102 | 128 | | |
103 | 129 | | |
104 | 130 | | |
105 | 131 | | |
106 | 132 | | |
107 | | - | |
108 | | - | |
109 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
110 | 138 | | |
111 | 139 | | |
112 | 140 | | |
| |||
0 commit comments