fix(service-analytics): 只当窗口用的 timeDimensions 条目不再被补默认粒度、不再静默拆网格 (#5688) - #6003
Merged
Merged
Conversation
…buckets the grid (#5688) A `timeDimensions` entry carrying only a `dateRange` — a dashboard date-range filter, with the dimension absent from `selection.dimensions` — had the dataset dimension's declared `dateGranularity` filled in, which made it a GROUP BY item: the response grew a time column nobody selected and rows split per bucket, so "count by Owner" plus a date filter came back as "by Owner x month". Narrow the backfill: an entry that states no `granularity` gets one only when the request says that date is being bucketed — the dimension is a grid dimension of this query, or `selection.dateGranularity` is set. An entry carrying its own granularity is unaffected and stays projected (#4033). compareTo alignment (#3588/#4870) holds by construction: the comparison pass re-enters `buildQuery` with the same grid dimensions, so both passes bucket an entry alike or not at all. For a window-only anchor this repairs the comparison — the merge keys on `dimensions` alone, so the backfilled bucket column sat outside the key and the comparison value landed on whichever split row the index held last. Pinned as a pair, both verdicts, both passes. Also closes the same-root-cause label blind spot: a time column projected via `timeDimensions` now carries its dataset `label` in `fields`. The enrichment lookup widens; the projection does not, so a window-only entry still mints no descriptor. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015a5qkLzpGXhLL2F5gvJ7dD
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 8 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5688
前提重验(对 origin/main
628b028,含 fb3d99b/#5808 与 #5963/#5716)前提成立,三个必要条件逐字复现。 以正文的 dataset 与三条数据实测,输出与立单描述逐字节一致:
附带症状同样成立:被投影的
close_date在fields里只有type没有label;同一 dataset 里把close_date写进selection.dimensions时则有label: "Close Date"—— 富化循环只读selection.dimensions的盲区。改动
按裁决「回填判据收窄」,落在
buildQuery的resolvedTimeDims一处:未写granularity的条目仅当该 dimension 是本次查询的网格维度、或selection.dateGranularity已设时才回填默认粒度(条目自带granularity的走不到这里,照旧分桶并投影,#4033 不变)。resolveDimensionGranularity未改:它回答「桶多大」,不回答「要不要分桶」。两个问题拆开写在注释里,因为它们在同一处打架正是本单的成因 —— dataset 维度的dateGranularity说的是「这个日期被分组时怎么渲染」,不是「请按它分组」。compareTo 的对齐语义(同场必答项)
定义:compareTo 不隐含分桶需求;它锚定的条目按与其它条目完全相同的判据决定是否分桶,主趟与比较趟因此按构造得到同一结论 ——
runCompare经runMeasurePass回到同一个buildQuery,网格维度与selection.dateGranularity都相同,只有dateRange被平移。{field:'close_date', dateGranularity:'month'})。mergeByDimensions一直只按selection.dimensions建键,回填出来的桶列从来不在合并键里:实测同一 owner 被裂成多行时,比较值落在索引最后写入的那一行上,其余行读到一个自信的0。实测(比较窗口内有数据,且 u1 的比较值跨两个月 = 1 + 2,单月凑不出来):
KPI 单值卡(
dimensions: [])同理:改前是两行月桶、卡片读第一行,改后一行{opp_count:3, opp_count__compare:4}。PM 机制假设 1 未被证伪 —— 未发现「窗口-only 不分桶」与「compareTo 对齐」不可同时满足的形状,不报 fork。
label 富化盲区(#5691 现状 + 顺手收掉)
先读了 #5691:它是 #5537 的 PR,已 closed/merged(2026-08-06T00:49:29Z),不是待认领的单,无撞车。它把盲区作为成对控制用例钉在
dataset-dimension-field-descriptors.test.ts里并指向本单。修法:
fields的维度 label 富化,查找集合从selection.dimensions扩到「本次 selection 通过timeDimensions引用到的 dataset 维度」。扩的是查找,不是投影 —— 循环仍然只富化result.fields里已经存在的条目,所以停留为纯窗口的条目不产生列、也拿不到描述符(#5691 在该处写下的「只富化、不造列」边界原样保留,并另加注释说明为什么没有并进selectedDims:钻取元数据与行值 label 解析回答的是另一个问题,动它们会改钻取载荷与行值,而不是表头)。翻 pin:承重,不是删断言
dataset-dimension-field-descriptors.test.ts的成对控制用例是明写的翻转靶,两条都翻了,并且都加重了:新增
dataset-window-timedimension-bucketing.test.ts(11 例)钉住收窄判据的三条正向臂与反向臂、compareTo 成对双向行为、以及一条「dataset 未声明dateGranularity」的对照(证明声明本身就是触发条件,而不是假定)。反向验证(先预测方向,再跑;拆成两半各自隔离)
方向普通(红),无反转、无计数移动。
两半各自承重,互不代偿。
范围与门禁
dataset-refusal-envelope/filter-refusal-envelope/unlisted-refusal-envelope/read-scope-refusal-envelope与dataset-compare-dimension-resolution全绿,拒收到达条件无变化(判据只影响 granularity 回填,不影响dateRange是否存在)。packages/spec、dataset-compiler、strategies 的拒收面。packages/rest(62 文件 / 854 例绿)、packages/qa/dogfood的 analytics/temporal 四个文件(18 例绿,其中 Analytics: a timeDimensions-bucketed query drops the bucket label from rows and fields — trend charts get counts with no x-axis #4033 那条走的正是「条目自带 granularity」这条保留分桶的路径)。examples/app-crm、app-showcase确有声明dateGranularity的 dataset(可达性属实),但仓库内无一处 fixture 把窗口-only 条目与声明了dateGranularity的维度组合起来,故无其它 fixture 需要改判。必答项:对 #5717(
isMissingSourceError嗅探器)的影响完全无影响,三条独立理由:
DatasetExecutor.execute()的catch上(analytics-service.ts:796),判的是驱动抛出的 relation-missing 错误;本改动只动buildQuery里成功路径的 granularity 判据,不新增、不消除、不改写任何异常。isMissingSourceError关心的是表/关系是否存在,与是否分桶正交。dataset-cross-datasource-registration.test.ts等相关用例全绿,未出现新的空结果吞没路径。既没让它变简单,也没让它变难,更没让它变得不必要。
验证
.github/workflows/lint.yml逐个枚举全跑(lint / slot-lookup / query-options-erasure / nul-bytes / doc-authoring / docs-audit-scope / role-word / adr-anchors / org-identifier / authz-resolver / service-providers / route-envelope / error-code-casing / wildcard-fallthrough / init-service-contract / durability-log-level / startup-registry-verdict / objectui-changeset / release-notes / release-body / node-version / workflow-status-functions / published-files / engine-double-contract / resume-authority-declared),全绿;typecheck 侧check:type-check-coverage(本包 3 error 的实测台账未移动)/check:driver-conformance/check:stall-guard全绿。@objectstack/service-analytics:59 文件 / 1092 例(改前基线)→ 60 文件 / 1103 例全绿。changeset 已加(用户可见行为变更:窗口-only selection 的行数与列集同时变化 —— 此前多出的月列与裂行消失)。
Generated by Claude Code