Skip to content

fix(analytics): timeDimensions 分桶维度回到结果的 rows 与 fields (#4033) - #4069

Merged
os-zhuang merged 1 commit into
mainfrom
claude/sqlite-datetime-filter-empty-hradlv
Jul 30, 2026
Merged

fix(analytics): timeDimensions 分桶维度回到结果的 rows 与 fields (#4033)#4069
os-zhuang merged 1 commit into
mainfrom
claude/sqlite-datetime-filter-empty-hradlv

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes #4033

问题

只用 timeDimensions 分桶的 analytics 查询,分组是对的 —— 回显的 SQL 就是 date_trunc('month', due_date) AS "due_date" —— 但结果里没有这个维度:

rows:   [{ "count": 2 }, { "count": 8 }]
fields: [{ "name": "count", "type": "number" }]

趋势图因此拿到 N 个数值却没有 x 轴标签。数值全对,所以下游没有任何报错,只是标签没了;把同一个查询写成 dimensions: ['due_date'] 又完全正常 —— 这就是它一直没被发现的原因。是 dogfood 真实跑 showcase app 时发现的,不是静态审出来的。

根因

ObjectQLStrategy 里三处对「哪些维度被投影」各有一套判断:

  • groupBy(3 处,主路径 / generateSql / cross-object):dimensions + 带 granularitytimeDimensions
  • 主路径行映射:只枚举 query.dimensions
  • buildFieldMeta:只枚举 query.dimensions
  • cross-object 行映射:自己另写了一份正确的循环 ✅(但与上面两处平行维护)

引擎按时间桶分了组、行里也带着它,映射这一步把它丢了。

修法

三方(分组、行映射、字段元数据)统一由一个 projectedDimensions() 推导:dimensions 加上所有带 granularity 且不重复的 timeDimensions

granularity 为闸门是因为那正是三处 groupBy 的判据 —— 不带 granularity 的条目只贡献 dateRange 谓词,把它投影出去会声明一个引擎从没分组过的列。cross-object 那份「正确但平行」的循环也并入同一定义,不再是第二个需要同步的地方。

验证

新增 objectql-timedimension-projection.test.ts(5 例)。先验证它能抓到 bug:在未修复的代码上跑 → 3 失败 2 通过(通过的那 2 个是负向断言,本就该过);修复后 5/5。

覆盖:桶进 rows、桶进 fields、timeDimensions 写法与 dimensions 写法结果一致、同时出现时不重复、不带 granularity 的条目不得被投影

  • service-analytics 329/329
  • driver-sql 508 passed / 38 skipped
  • objectql 1179/1179

过程说明:首轮跑出 10 个失败(涉及 #3777/#3912/#3650),我先在未改动的 main 上复跑确认同样失败,再定位到是本工作树 dist 过期(#4041 新增的 nextUtcCalendarDay 尚未构建进 @objectstack/core)。全量重建后归零,与本 PR 无关。

🤖 Generated with Claude Code

https://claude.ai/code/session_01TPxNwPnjcn599ujXpU3ibJ


Generated by Claude Code

…and fields

A query bucketing by `timeDimensions` alone grouped correctly — the echoed SQL
read `date_trunc('month', due_date) AS "due_date"` — but the row mapper and
buildFieldMeta both enumerated `query.dimensions` only, so the bucket was
dropped on the way out:

  rows:   [{ count: 2 }, { count: 8 }]
  fields: [{ name: 'count', type: 'number' }]

A trend chart therefore got N values and no x-axis. Found by driving a live
showcase app, not by static review: the numbers were right, so nothing
downstream errored — only the labels were gone. Writing the same query as
`dimensions: ['due_date']` was always fine, which is why it survived.

Grouping, row mapping (both the direct and cross-object paths) and field
metadata now derive their projected set from one `projectedDimensions()`
helper: `dimensions` plus every GRANULAR `timeDimensions` entry not already
among them. Granularity is the right gate because it is exactly what the three
groupBy sites key on — an entry without one contributes only a `dateRange`
predicate, and projecting it would declare a column the engine never grouped
by. The cross-object path already had its own correct-but-parallel loop; it now
shares the single definition rather than being a second place to keep in sync.

Closes #4033

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

vercel Bot commented Jul 30, 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 Jul 30, 2026 7:58am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jul 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): packages/services.

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

  • content/docs/automation/webhooks.mdx (via packages/services)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/index.mdx (via packages/services)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/plugins/packages.mdx (via packages/services)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/services)

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.

@os-zhuang
os-zhuang marked this pull request as ready for review July 30, 2026 08:16
@os-zhuang
os-zhuang merged commit 3abd233 into main Jul 30, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/sqlite-datetime-filter-empty-hradlv branch July 30, 2026 08:16
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/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Analytics: a timeDimensions-bucketed query drops the bucket label from rows and fields — trend charts get counts with no x-axis

2 participants