Skip to content

Commit 88a6bed

Browse files
os-zhuangclaude
andauthored
fix(service-analytics): lower the where before seeding an ad-hoc cube's dimensions (#5353) (#5764)
`inferCubeFromQuery` guarded its `where` arm with `!Array.isArray(query.where)`, written when an array `where` was not a filter. #5334 made it one, so one filter minted two different cubes depending on its spelling: where: {stage: 'won'} -> dimensions: {stage} where: [['stage','=','won']] -> dimensions: {} The `where` is now lowered to its canonical FilterCondition first, so the spelling stops mattering. The lowering is #5334's own, extracted from `normalizeAnalyticsFilterTree` as `lowerAnalyticsWhere` so exactly one of it survives; keys are read via `conjunctFieldKeys`, which descends `$and` because the lowering introduces `$and` where the object spelling has none. `$or` / `$not` contribute no key on either spelling, as before. No compiled statement, bound value or gate verdict changes: both spellings already compiled a byte-identical predicate, and an inferred cube declares no `joins`, so `qualifyAndRegisterJoin` leaves the newly-declared members' columns bare. The rejection suggestion lists and `getMeta` now read alike for both. A DOTTED `where` key stays spelling-dependent, deliberately: unifying it means either propagating #5739's base-column mis-cast to the array spelling (measured: a working traversal becomes a different-rows base-column filter, or a 400) or splitting a verdict #5740 shares with the `dimensions` request key. Left to #5739 and pinned by tests. Claude-Session: https://claude.ai/code/session_01BWS4heBoAitLmzCLhcYdbK Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9f747ee commit 88a6bed

4 files changed

Lines changed: 667 additions & 57 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
"@objectstack/service-analytics": patch
3+
---
4+
5+
fix(service-analytics): an ad-hoc cube's dimensions no longer depend on how the `where` was spelled (#5353)
6+
7+
`inferCubeFromQuery` mints a Cube for a free-form analytics query that names no
8+
registered cube, seeding `dimensions` from the fields the query mentions — its
9+
`measures`, `dimensions`, `timeDimensions`, and its `where`. The `where` arm was
10+
guarded by `!Array.isArray(query.where)`, written when an array `where` was not a
11+
filter. #5334 made it one, so from then on one filter minted two different cubes
12+
depending on its spelling:
13+
14+
```
15+
where: {stage: 'won'} → dimensions: {stage} ← seeded
16+
where: [['stage','=','won']] → dimensions: {} ← skipped
17+
```
18+
19+
The `where` is now LOWERED to its canonical `FilterCondition` before its keys are
20+
read, so the spelling stops mattering. The lowering is the same one the
21+
strategies already use (#5334's `parseFilterAST` call, extracted from
22+
`normalizeAnalyticsFilterTree` as `lowerAnalyticsWhere` so there is still exactly
23+
one of it), and the keys are read through `conjunctFieldKeys`, which descends
24+
`$and` — necessarily, because the lowering itself introduces `$and` where the
25+
object spelling has none: `[[a,…],[b,…]]` lowers to `{$and: [{a…},{b…}]}`. As a
26+
result an explicit `{$and: […]}` object `where` now also seeds its conjuncts'
27+
keys, which it never did.
28+
29+
`$or` / `$not` are not descended, and contribute no key on either spelling, as
30+
before.
31+
32+
**No compiled statement, bound value or gate verdict changes.** Both spellings
33+
already compiled a byte-identical predicate (which is why this shipped as an
34+
observation rather than a defect): `resolveFieldSql` falls back to the bare
35+
column name for an undeclared member, and `qualifyAndRegisterJoin` leaves bare
36+
columns bare on a cube with no `joins` — which an inferred cube never has. So the
37+
newly-declared dimensions move those members from the undeclared branch to the
38+
declared one and both yield the same column. What does change is the suggestion
39+
list in a rejection: `Valid filter members:` / `Valid dimensions:` now read the
40+
same for both spellings of one filter, and `getMeta` reports the same dimension
41+
vocabulary for both.
42+
43+
**Still spelling-dependent: a DOTTED `where` key.** `{'owner.region': 'NA'}`
44+
seeds the stripped tail `region` as a base-table dimension; the array spelling
45+
`[['owner.region','=','NA']]` seeds nothing and compiles the relation traversal.
46+
Unifying them is #5739's call, not this change's — propagating the mint to the
47+
array spelling turns a working traversal into a base-column filter over different
48+
rows (and a `400 INVALID_FIELD` where the base table has no such column), while
49+
withdrawing it from the object spelling would split a verdict #5740 deliberately
50+
shares with the `dimensions` request key. Dotted keys therefore keep today's
51+
per-spelling answer, pinned by tests, until #5739 rules.

0 commit comments

Comments
 (0)