Skip to content

feat: ad-hoc aggregation suite + multi-value filter fix (#1606-1610, #2027)#2057

Merged
rubenvdlinde merged 1 commit into
developmentfrom
wip/build-adhoc-aggregation
Jul 23, 2026
Merged

feat: ad-hoc aggregation suite + multi-value filter fix (#1606-1610, #2027)#2057
rubenvdlinde merged 1 commit into
developmentfrom
wip/build-adhoc-aggregation

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Summary

Implements the adhoc-aggregation-suite OpenSpec change — 5 of 6 requirements shipped, 1 deferred (see below). Ground-truthed each sub-part against HEAD before writing code: several were already fully implemented and only needed HTTP wiring or a missing response header.

Requirement Status
REQ-AGG-101 multi-field groupBy Already implemented (service layer) — added controller wiring (comma-list / repeated groupBy[] param)
REQ-AGG-102 multi-metric Implementedmetrics list on value()/grouped(), native path merges N single-metric queries into one values map, PHP fallback computes all metrics over the same row set
REQ-AGG-103 cumulative time-bucket Deferred — not implemented this wave, left open in spec/tasks.md
REQ-AGG-104 cross-dialect native time-bucket Already fully implemented + tested at HEAD (Postgres/MySQL/MariaDB/SQLite) — no change needed
REQ-AGG-105 timeseries caching Cache engine already implemented at HEAD — added the missing X-OR-Cache: hit|miss header on value()/grouped()/timeseries()
REQ-AGG-106 bug #2027 (multi-value filter) Implemented — bare array filter → implicit in (any-of); in/notIn/eq/ne now any-overlap-match multi-value (JSON-array) properties; native path defers array-typed-property filters to the PHP fallback instead of emitting a silently-wrong predicate

Single-field/single-metric response shapes are regression-pinned byte-identical.

Not archived — REQ-AGG-103 is deferred; tasks.md marks it explicitly as an open follow-up.

Test plan

  • docker run --rm -v <worktree>:/app -w /app nextcloud:34.0.0-apache php vendor/bin/phpunit — 217 aggregation-scoped tests pass (130 pre-existing regression + 87 new/updated across AggregationQueryTest, AggregationRunnerMultiValueFilterTest (new), AggregationRunnerMultiMetricTest (new), AggregationControllerValueGroupedTest (new))
  • vendor/bin/phpcs clean on all changed lib/ files (1 pre-existing warning, unrelated to this change, verified present at HEAD too)
  • Full Unit Tests suite (15k tests) run for regression sanity — the handful of pre-existing failures/errors (RelationHandler ctor arity, missing CSV fixture, SchemaLinkedTypes, MapLink/PhotoLink/PollLink deep-link format, a full-suite-only test-isolation issue affecting JSONResponse::addHeader) are unrelated to this change and reproduce identically in an untouched sibling worktree at a similar commit — confirmed pre-existing, not introduced here

Known pre-existing CI infra failures (npm/eslint/stylelint/license/Newman) are unrelated to this backend change.

…2027)

Ground-truthed the six adhoc-aggregation-suite requirements against HEAD
before implementing:

- REQ-AGG-101 (multi-field groupBy) and REQ-AGG-104 (cross-dialect native
  time-bucket) were already fully implemented and tested in
  AggregationQuery/AggregationRunner. Wired the missing HTTP surface:
  AggregationController::grouped() now parses a comma-list or repeated
  groupBy[] param into the multi-field shape.
- REQ-AGG-105 (timeseries caching): the cache engine already read-through
  cached every ad-hoc query via AggregationCache; only the X-OR-Cache
  hit/miss response header was missing on value()/grouped()/timeseries()
  (aggregate() already had it). Added.
- REQ-AGG-102 (multi-metric): implemented. AggregationQuery gains a
  metrics list (getMetrics()/isMultiMetric()/metricResponseKey()); the
  native path merges N single-metric native calls into one values map
  (reuses the proven per-dialect SQL builder rather than a new
  multi-column statement); the PHP fallback computes all metrics over the
  same row set. Wired into value()/grouped(), not timeseries() (rejected
  combination with dateBucket).
- REQ-AGG-106 (bug #2027): fixed on both paths. A bare array filter value
  is now treated as an implicit `in` (any-of) instead of being silently
  ignored by the PHP fallback (previously counted every row) or bailing
  the native path with no translation. The `in`/`notIn`/`eq`/`ne`
  operators now correctly any-overlap match multi-value (JSON-array)
  object properties in the PHP fallback; the native path defers
  array-typed-property filters to the PHP fallback rather than emit a
  silently-wrong equality/IN predicate.
- REQ-AGG-103 (cumulative time-bucket) is deferred — not implemented this
  wave; left as an open requirement, tasks.md marks it explicitly.

Single-field/single-metric response shapes are regression-pinned
byte-identical. 217 aggregation unit tests pass (130 pre-existing + 87
new/updated across 4 test files).

Not archived: 5 of 6 requirements are done; REQ-AGG-103 remains open.
@rubenvdlinde
rubenvdlinde merged commit c6ac632 into development Jul 23, 2026
10 of 19 checks passed
@rubenvdlinde
rubenvdlinde deleted the wip/build-adhoc-aggregation branch July 23, 2026 22:13
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/openregister @ c4e7c7d

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 172/172
npm
PHPUnit ⏭️
Newman ⏭️
Playwright ⏭️

Quality workflow — 2026-07-23 22:15 UTC

Download the full PDF report from the workflow artifacts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant