Skip to content

feat(bindings): tAvg(tnumber) and wavg(tnumber, INTERVAL) aggregates#59

Closed
estebanzimanyi wants to merge 2 commits into
feat/aggregate-fn-extent-tspatialfrom
feat/aggregate-fn-twavg
Closed

feat(bindings): tAvg(tnumber) and wavg(tnumber, INTERVAL) aggregates#59
estebanzimanyi wants to merge 2 commits into
feat/aggregate-fn-extent-tspatialfrom
feat/aggregate-fn-twavg

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

Summary

Adds the temporal-average aggregate:

Aggregate Inputs Output
`tAvg(tint)` tint tfloat
`tAvg(tfloat)` tfloat tfloat

```sql
SELECT tAvg(t) FROM (VALUES (tint '5@2000-01-01'), (tint '3@2000-01-01')) tt(t);
-- {4@2000-01-01 00:00:00+00} -- avg of 5 and 3
```

Implementation

State holds a `SkipList` of `{sum, count}` pairs (MEOS `double2` layout — `{ double a; double b; }`). `Operation` calls `tnumber_tavg_transfn`. `Combine` merges two states via `temporal_skiplist_splice` with `mduck_datum_sum_double2` as the merge function — a local replica of MEOS's internal `datum_sum_double2` since that symbol is not in the MEOS public install headers (the underlying struct layout is, fortunately, simple enough to replicate exactly). `Finalize` calls `tnumber_tavg_finalfn` which computes per-instant `sum/count` and frees the skiplist; `state.skiplist` is nulled after to keep the destructor from double-freeing.

Test plan

  • Same-instant `tAvg(5, 3)` correctly produces `4`
  • Distinct instants preserve their per-instant values
  • `tAvg(tfloat)` works with non-integer values
  • No segfault on cleanup (destructor pattern from existing skiplist aggregates)

Adds the temporal-average aggregate over tint and tfloat:

  tAvg(tint)   -> tfloat
  tAvg(tfloat) -> tfloat

State holds a SkipList of {sum, count} pairs (MEOS double2 layout).
Operation calls tnumber_tavg_transfn. Combine merges two states via
temporal_skiplist_splice with mduck_datum_sum_double2 as merge fn —
this is a local replica of MEOS's internal datum_sum_double2 since
that symbol is not exported by MEOS public headers. Finalize calls
tnumber_tavg_finalfn which computes per-instant sum/count and frees
the skiplist; we null state.skiplist after to avoid double-free in
the destructor.
Windowed time-weighted average — companion to wmin/wmax/wsum window
aggregates. Uses tnumber_wavg_transfn for accumulation and reuses the
tAvg machinery (datum_sum_double2 merge function and
tnumber_tavg_finalfn) for combine and finalize.

WavgFunction is a separate functor from the existing
WindowAggFunction template because wavg's finalfn is
tnumber_tavg_finalfn rather than the generic temporal_tagg_finalfn,
and its merge fn is fixed to mduck_datum_sum_double2.
@estebanzimanyi

Copy link
Copy Markdown
Member Author

Added a follow-up commit for wavg(tnumber, INTERVAL) -> tfloat — companion windowed time-weighted average. Same machinery as tAvg but binary input (Temporal + Interval), uses tnumber_wavg_transfn for accumulation. Reuses mduck_datum_sum_double2 and tnumber_tavg_finalfn.

SELECT wavg(t, INTERVAL '1 day')
  FROM (VALUES (tint '5@2000-01-01'), (tint '3@2000-01-02')) tt(t);
-- {[5@..., 4@..., 3@...]}    -- avg of (5, 3) = 4 at the overlap day

@estebanzimanyi estebanzimanyi changed the title feat(bindings): tAvg(tnumber) -> tfloat aggregate feat(bindings): tAvg(tnumber) and wavg(tnumber, INTERVAL) aggregates Apr 30, 2026
@estebanzimanyi

Copy link
Copy Markdown
Member Author

Consolidated into #60 (aggregate cluster squash). The full chain of aggregate work is now reviewable as a single PR; this branch's commits are preserved in #60's history. Closing to minimize the review queue.

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