Skip to content

driver-mongodb: native dateGranularity lowering ($dateTrunc → engine bucket labels) + publish supports.queryDateGranularity #7580

Description

@huangyiirene

Provenance (maintainer direct-route, 2026-08-11)

Filed and queued on the maintainer's instruction in the drivers PM session chat (session session_013ZU38vNzLXCscgdFZjKd53), verbatim:

mongodb dateGranularity 立卡排进队列

Routing label applied under the 2026-08-10 direct-route standing authorization (maintainer-commanded cards route directly; natural-inflow triage remains the triage seat's). driver-mongodb is unfrozen per #5499 comment 5249019855.

Background — what PR #7550 measured and deliberately did not do

PR #7550 (Fixes #6850 / Part of #6814) gave driver-mongodb a real structured-GroupByNode lowering, and chose to refuse a dateGranularity-bearing node (NOT_IMPLEMENTED / 501, ADR-0112 envelope) rather than implement or silently drop it. Its PR body records the measurement that sized the native lowering as a card of its own — this card.

The standard already exists — this card joins it, it does not invent it

  • Capability record: supports.queryDateGranularity is a per-granularity record ({ day, week, month, quarter, year }). packages/objectql/src/engine.ts (~:9295-9301, drifts — locate by content) pushes a bucketed groupBy down only for granularities the driver advertises; otherwise the engine buckets in memory (in-memory-aggregation.ts). So today mongodb aggregations still bucket correctly — one layer up, without index/server-side benefit.
  • Precedent + parity suites: driver-sql publishes the capability and is held to sql-driver-date-bucket.test.ts (parity), sql-driver-date-bucket-storage.test.ts (storage forms), sql-driver-aggregate-datetime-window.test.ts / -temporal-output.test.ts. The engine's timezone semantics are pinned in engine-aggregate-timezone.test.ts.
  • Labels are the contract: buckets must come back as the ENGINE's label spellings (e.g. 2026-01, quarter and ISO-week forms) — byte-parity with what the in-memory fallback emits, or the two paths answer the same query differently depending on a capability bit.

Scope

  1. Lower a dateGranularity-bearing groupBy node natively ($dateTrunc or equivalent expression), emitting the engine's bucket labels.
  2. Storage forms per ADR-0053: mongodb stores datetime as BSON Date but date/time as text — measure which granularity × field-kind cells a native lowering can honestly serve, and only advertise those.
  3. Publish supports.queryDateGranularity for exactly the cells implemented — declared = enforced; an advertised granularity the lowering mishandles is worse than the current honest refusal.
  4. Keep the fix(driver-mongodb): take a structured GroupByNode, and answer count/count_distinct like every other backend #7550 refusal as local defense for direct callers with unadvertised granularities (the engine will not push those down once the capability record is honest).
  5. Parity coverage in the shape of the driver-sql suites, server-free per driver-mongodb 测试:两个套件并发下载 MongoDB 二进制,mongodb-memory-server 的 rename 竞态让全绿测试 exit 1(队列 flaky) #5517 (the in-process evaluator from mongodb-aggregation-translation.test.ts — note its stated bound: it holds the LOWERING to the table; live-mongod agreement stays out of reach in this fleet, and any modelled $dateTrunc semantics must carry the same written bound).

Acceptance

  • For every advertised granularity × field-kind cell: pushdown result labels are byte-identical to the engine's in-memory fallback on the same rows (parity cases, both spellings of the node).
  • Unadvertised cells keep refusing loudly at the builder (existing tests stay green or are consciously updated).
  • Timezone semantics match engine-aggregate-timezone.test.ts's pinned behavior — measure before implementing; if a faithful timezone treatment is not achievable server-free, narrow the advertised set and record why rather than approximating.

Refs: PR #7550 (measurement + refusal), #6850 / #6814 (the cell this grew from), #5499 (unfreeze), aggregation-conformance.ts:51 (capability note), ADR-0053 (storage forms), ADR-0112 (refusal envelope).

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions