Skip to content

fix(service-analytics): lower the where before seeding an ad-hoc cube's dimensions (#5353) - #5764

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-5353-infercube-array-where
Aug 6, 2026
Merged

fix(service-analytics): lower the where before seeding an ad-hoc cube's dimensions (#5353)#5764
os-zhuang merged 1 commit into
mainfrom
claude/issue-5353-infercube-array-where

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5353

前提重验(对 origin/main,fce4c7385)

立单前提仍然成立,逐条核过:

改了什么

inferCubeFromQuerywhere先下沉再取键。下沉复用 #5334 那一次,不是新接一份:normalizeAnalyticsFilterTree 里的数组分支抽成 lowerAnalyticsWhere(返回下沉后的 canonical FilterCondition),normalizeAnalyticsFilterTree 变成「这次下沉 + buildNode」。全仓只有一处 isFilterAST/parseFilterAST 调用,两处读者(闸门读树的叶子,铸造读条件的键)看同一次下沉的两种视图。

取键走新的 conjunctFieldKeys,它下钻 $and、不下钻 $or / $not。下钻 $and 不是顺手加的:下沉本身会引入 $and —— 平铺数组 [[a,…],[b,…]] 是对象 {a…, b…} 的数组写法,parseFilterAST 把它降成 {$and: [{a…},{b…}]}。只读下沉后对象自己的顶层键的话,答案是「只有 $and」即什么都没有,两种写法照旧铸出两个 cube。连带效果:对象写法的显式 {$and: […]} 现在也会铸出其 conjunct 的键(以前不会),这与 {a…, b…} 拉平,属同一个缺陷类。

$or / $not 两种写法今天都不贡献键,保持不变。

刻意不用 collectFilterLeaves:叶子回答「编出的谓词绑了哪些 member」,这个 bag 回答「调用方可以命名什么」,两者真的不同 —— {stage: {$in: []}} 降成布尔常量 FALSE,不绑任何 member,却仍然命名了 stage

判定不变性(实测,不是推断)

两种写法修前就编出逐字相同的谓词,这也是本单属 observation 而非缺陷的原因:resolveFieldSql 对未声明 member 回落裸列名,而 qualifyAndRegisterJoin 只在 cube 声明了 joins 时才加限定 —— 即席 cube 从不声明。所以新铸的 dimension 只是把这些 member 从「未声明裸列」分支挪到「已声明 dimension」分支,两分支得出同一列。

一处没有统一的:点号 where

{'owner.region': 'NA'} 铸出剥尾后的基表列 region;数组写法 [['owner.region','=','NA']] 什么都不铸,编出关系穿越。两个方向都不是本单能选的,实测:

① where: {'owner.region': 'NA'}       dims ["deal.region"]  → 400 INVALID_FIELD 'region'
② where: [['owner.region','=','NA']]  dims []               → LEFT JOIN "owner" ON …
                                                               WHERE "owner"."region" = $1

所以点号键原样保留各自写法今天的答案(残留循环逐字复刻 origin/main 的对象顶层键 + stripPrefix),归 #5739 裁定 —— 该单已带 needs-user-decision,实测与两个子选项的代价已评论上去。#5353 自己的范围(过时的 !Array.isArray 守卫)是完整交付的:守卫已删,数组走下沉。

测试

新增 infer-cube-where-spelling-parity.test.ts(23 例)。平价表直接取 #5334 自己的 EQUIVALENT_SPELLINGS,让两个文件不会对「同一份筛选的两种写法」各说各话 —— #5334 断言两者选出同样的,这里断言两者铸出同样的cube。每例都断言「精确期望集合」而不只是「两边相等」:只比两边的表会在两边都空时同样通过,而那正是缺陷本身。

反向验证(先预测方向,再跑)

恢复 !Array.isArray(query.where) 守卫。预测 13 红 / 10 绿,并预先点名红的集合:平价表 13 例中降成合取且至少命名一个字段的 11 例、seeds the where keys ALONGSIDE …、以及 bare keys reach parity even when a dotted key rides along实测恰好这 13 例

两处绿是刻意的,写在用例头里而不留给下一位读者去踩:


Generated by Claude Code

…be's dimensions (#5353)

`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.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWS4heBoAitLmzCLhcYdbK
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 6, 2026 4:15am

Request Review

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/service-analytics.

8 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/api/data-api.mdx (via @objectstack/service-analytics)
  • content/docs/api/index.mdx (via @objectstack/service-analytics)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/service-analytics)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/service-analytics)
  • content/docs/plugins/packages.mdx (via @objectstack/service-analytics)
  • content/docs/releases/implementation-status.mdx (via @objectstack/service-analytics)
  • content/docs/releases/v17.mdx (via @objectstack/service-analytics)
  • content/docs/releases/v9.mdx (via @objectstack/service-analytics)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Aug 6, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 6, 2026 04:52
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 88a6bed Aug 6, 2026
24 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-5353-infercube-array-where branch August 6, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

observation: inferCube 仍把数组 where 当「不是筛选」跳过 —— #5334 之后这个 !Array.isArray 守卫已经过时

2 participants