Repository navigation
Commit 95fed33
fix(driver-memory): the cube face lowers the FilterArray spelling of
Fixes #20859
Clause-②: no (narrowing)
## What changed
`MemoryAnalyticsService.normalizeFilters`
(`packages/drivers/driver-memory/src/memory-analytics.ts`) read only a
non-array object `where`. A `FilterArray` `where` therefore skipped the
shared comparand doors, the shared lowering, the vocabulary gate and the
flatten, so its predicate vanished.
The array is now lowered at the method's entry by a module-private
`lowerWhereFilterArray`, which calls the spec's own pair: `isFilterAST`
gates the shape and `parseFilterAST` lowers it. That is the pair the
analytics `where` door (`lowerAnalyticsWhere`, see #5334) and the
engine's `lowerWhereFilterArray` call. The face adds no parser of its
own. The lowered condition then enters the step-3 door (#20857) exactly
as an authored object does. So both spellings meet the same comparand
doors, the same `lowerFilterCondition` and the same gate, and both exits
(`query()` and `generateSql()`) read the same normalized list.
The three arrival answers are the analytics `where` door's:
| arrival | answer |
|---|---|
| `[]` | no filter (unchanged: every row, no WHERE) |
| an array `isFilterAST` accepts | lowered by `parseFilterAST`, then the
door, the lowering and the gate, like the object spelling |
| any other array (infix join, unknown operator, list of scalars, a
cube-style entry list) | refused `INVALID_FILTER` / 400 on both exits |
## Measured
On the fixture from the card (`d` is `'v1'`, `'v2'`, `null`, absent):
| `where` | before (base `d78a0bda07`) | after (`ca8448c005`) |
|---|---|---|
| `{ d: 'v1' }` | rows 1; echo `d = 'v1'` | rows 1; echo `d = 'v1'`
(control, unchanged) |
| `[['d', '=', 'v1']]` | rows 1, 2, 3, 4; echo has no WHERE | rows 1;
echo `d = 'v1'` |
| `[]` | rows 1–4; no WHERE | rows 1–4; no WHERE (unchanged) |
| `[['d', '=', 'v1'], 'or', ['d', '=', 'v2']]` (infix) | rows 1–4 |
`INVALID_FILTER` / 400 |
| `[['d', 'in', 'v1']]` (scalar `in`) | rows 1–4 | `INVALID_FILTER` /
400, as `{ d: { $in: 'v1' } }` is |
## Tests
New pin file
`packages/drivers/driver-memory/src/memory-analytics-filter-array-where.test.ts`,
16 cases:
- the card's row, rows and echo;
- seven spellings, each answering the rows and the echo of the
`FilterCondition` it lowers to (a comparison, a flat list, an `and`
group, an `or` group, a negative-polarity leaf, `is_null`,
`is_not_null`);
- the `[]` control;
- four non-lowerable arrays refused on both exits;
- three lowerable arrays that are refused exactly as their object
spelling is refused.
Refusals assert the envelope (`code` + `status`), not the prose.
- Red first: at `62eff2a8f9` (pins only, source at the base), the file
gave 15 failed, 1 passed. The one pass is the `[]` control. The card's
row read rows `['1','2','3','4']` and echo `undefined`.
- Green: 16 of 16 passed at `f2be8432cd`.
- Ablation on the parse: `scripts/ablation-replace.mjs` replaced `const
where = lowerWhereFilterArray((query as { where?: unknown }).where);`
with the pre-fix read. The anchor went from 1 to 0, and the blob moved
`cc0aaa764022` to `3445aece6953`. Result: 15 failed, 1 passed (the `[]`
control). The restore was proven: the blob equals HEAD `cc0aaa764022`,
and `git diff HEAD` is empty. The pins import `./memory-analytics.js` by
relative path, and the package's vitest config aliases `@objectstack/*`
to source, so no build sat between the mutation and the reading.
- At `ca8448c005`, after `pnpm --filter '@objectstack/driver-memory...'
build`, the `driver-memory` suite gave 66 files and 1429 tests passed.
`typecheck` exited 0, and `tsc --noEmit --listFiles` includes the new
test file.
- Gates at `ca8448c005`: `dispatch-gates --commands` derived 60
families, and all 60 were run.
- Three first answered PREREQUISITE NOT MET (exit 3):
`check:dual-build-cjs-loads`, `check:lean-entry-closure` and
`check:type-check-debt`. After a full `turbo run build` (72 tasks) they
were re-run, and all three passed.
- `dispatch-gates --ran` reported 60 derived, 60 run, 0 NOT-MEASURED, 0
UNRUN.
- The six roster families under touched directories were also run, and
all passed: `check-changeset-fixed`, `authz-resolver`,
`error-code-casing`, `filter-alias-parity`, `object-def-param-keys`,
`tenant-chokepoint`.
- Lint, narrowed and measured:
- Population: `eslint.config.mjs`'s
`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` block.
- `eslint --no-inline-config --format json` over the two changed
TypeScript files: 2 files, 0 errors, 0 warnings, at `ca8448c005`.
- The config enables no type-aware linting, so no untouched file's
verdict can move.
- NOT MEASURED, left to CI: the path-scheduled CI jobs (Test Core
shards, Dogfood, Temporal Conformance, Build Core) and the workspace
type-check lanes.
## Acceptance notes
- **Accept-set reading.** A well-formed array that answered every row
now answers its predicate's rows. An array whose lowered condition the
doors refuse is refused as that object spelling already is. One row goes
beyond "a dropped predicate now filters": an array `isFilterAST` refuses
(the infix join, an unknown operator, a list of scalars, a cube-style
entry list) used to answer every row and now answers `INVALID_FILTER` /
400. None of those shapes is admitted by `AnalyticsQuerySchema.where`
(`FilterConditionSchema`) or by `FilterArraySchema`, and the triage
direction rules out dropping. Answered by the seat (5920030329, B, open
to veto): the face's accept set narrows, as it did on PR #20857 (#5930
step 3) on this same face, so this PR takes `Clause-②: no (narrowing)`.
The changeset is `minor` with a **BREAKING** paragraph and one ADR-0087
marker; the claim's "nothing is newly refused" was the seat's error.
- On an array, the shared comparand-shape and comparand-type faces run
twice: inside `parseFilterAST`, then at the door. Both are idempotent
(an assertion, and a copy-on-write narrowing), so the verdict is the
same one the first pass gives.
- `normalizeFilters`' object branch still carries its
`!Array.isArray(where)` test. After the lowering it is always true for
anything that reaches it, and it is kept as the object branch's own
statement of what it reads.
- Unmeasured reading, not filed (carrier: none): the analytics `where`
door's and the engine's non-lowerable-array refusals render the value
with a bare `JSON.stringify`. A `bigint` inside such an array would make
that call throw a raw `TypeError` instead of the envelope. This face's
message renders through a non-throwing preview. No JSON wire can carry a
`bigint`.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DEvba2nBuD4tWzfq8r8NFY)_
---------
Co-authored-by: Claude <noreply@anthropic.com>where instead of answering every row (#20944)1 parent 75519e1 commit 95fed33
3 files changed
Lines changed: 289 additions & 4 deletions
File tree
- .changeset
- packages/drivers/driver-memory/src
| 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 | + | |
| 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 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
18 | 23 | | |
19 | 24 | | |
20 | 25 | | |
| |||
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
| 59 | + | |
54 | 60 | | |
55 | 61 | | |
56 | 62 | | |
| |||
938 | 944 | | |
939 | 945 | | |
940 | 946 | | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
941 | 1024 | | |
942 | 1025 | | |
943 | | - | |
| 1026 | + | |
944 | 1027 | | |
945 | 1028 | | |
946 | 1029 | | |
| |||
1646 | 1729 | | |
1647 | 1730 | | |
1648 | 1731 | | |
1649 | | - | |
1650 | | - | |
| 1732 | + | |
| 1733 | + | |
| 1734 | + | |
| 1735 | + | |
| 1736 | + | |
| 1737 | + | |
| 1738 | + | |
| 1739 | + | |
1651 | 1740 | | |
1652 | 1741 | | |
1653 | 1742 | | |
1654 | 1743 | | |
1655 | 1744 | | |
1656 | | - | |
| 1745 | + | |
1657 | 1746 | | |
1658 | 1747 | | |
1659 | 1748 | | |
| |||
0 commit comments