Skip to content

feat(promql): lower extra *_over_time reducers + sort family (#51) - #90

Merged
zzylol merged 1 commit into
mainfrom
feat/51-range-reducers-sort
Jul 4, 2026
Merged

zzylol merged 1 commit into
mainfrom
feat/51-range-reducers-sort

Conversation

@zzylol

@zzylol zzylol commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Closes #51. Splits min_of/max_of to #89.

What

The #51 long tail was three groups. This lands the two clean ones:

  • Extra *_over_time reducers (21 corpus rejections): last_over_time, first_over_time, mad_over_time, ts_of_min_over_time, ts_of_max_over_time, ts_of_first_over_time, ts_of_last_over_time.
  • Sort family (16): sort, sort_desc, sort_by_label, sort_by_label_desc.

How

Range reducers — new per-series intents Last/First/Mad/TsOfMin/TsOfMax/TsOfFirst/TsOfLast-OverTime, wired through requires (TimeSeries), is_per_series, output_column, the L2 AggFunc, agg_func_to_intent, the RangelessRangeReduction guard, and both dispatch paths — the matrix-selector lower_inner_call and the sub-query range_fn_over_subquery (so last_over_time(rate(m[5m])[1h:1m]) works too). They slot into the exact windowed per-series shape as avg_over_time/max_over_time: a TimeRange-wrapped Aggregate whose intent is label-preserving.

Sort family — front-end only (the Sort node already exists). is_sort_fn / walk_sort: sort/sort_desc(v) → a bare Sort by sample value (asc/desc, no Limit — row-preserving reorder); sort_by_label[_desc](v, "l"…) → one sort key per label in argument order. The label args are seeded into the usage-derived schema by the existing Sort.keys binder path.

Scope: min_of / max_of deferred to #89

Per the parser these are n-ary scalar reducers (Scalar…→Scalar), not vector element-wise as the issue guessed. In the corpus they're almost always nested with step()/range() inside range/offset positions that are themselves unsupported (count_over_time(m[min_of(step()+1, 1h)])), and a non-constant min_of has no home in the current Scalar(f64) leaf. Left rejected, pinned by min_of_max_of_are_rejected__GAP, design in #89.

Tests

Conformance §U:

  • each reducer → its per-series intent over a TimeRange.
  • sum by (job) (last_over_time(m[5m])) — per-series-then-cross-series nesting.
  • sort/sort_desc reorder by value with no Limit, correct direction.
  • sort_by_label(v, "group", "instance", "job") — three keys in order, labels seeded.
  • sort_by_label_desc descending; min_of/max_of GAP.

unsupported_functions_are_rejected repointed to step() / range() / histogram_quantiles.

Full workspace suite green; clippy clean.

The #51 long tail was three groups: extra range reducers, the sort family,
and min_of/max_of. This lands the first two; min_of/max_of (n-ary scalar
reducers, entangled with the unsupported step()/range() helpers) split to #89.

Range reducers (asap-ir / asap-l2 / front end):
- New per-series intents Last/First/Mad/TsOfMin/TsOfMax/TsOfFirst/TsOfLast-
  OverTime, wired through requires (TimeSeries), is_per_series, output_column,
  AggFunc, agg_func_to_intent, the RangelessRangeReduction guard, and both the
  matrix-selector (`lower_inner_call`) and sub-query (`range_fn_over_subquery`)
  dispatch paths. They slot into the same windowed per-series reduction shape
  as avg_over_time/max_over_time — a `TimeRange`-wrapped `Aggregate`.

Sort family (front end only):
- `is_sort_fn` / `walk_sort`: `sort`/`sort_desc(v)` → a bare `Sort` by sample
  value (asc/desc, no `Limit` — row-preserving); `sort_by_label[_desc](v,
  "l"…)` → one sort key per label, in argument order. The label args are
  seeded into the usage-derived schema by the existing `Sort.keys` binder path.

Tests: conformance §U — each reducer → its per-series intent over a TimeRange;
last_over_time under an outer sum; sort/sort_desc reorder by value with no
Limit; sort_by_label's per-label keys + label seeding; min_of/max_of GAP.
`unsupported_functions_are_rejected` repointed to step()/range()/
histogram_quantiles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@zzylol
zzylol merged commit 66094d9 into main Jul 4, 2026
1 check passed
@zzylol
zzylol deleted the feat/51-range-reducers-sort branch July 4, 2026 14:47
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.

PromQL: long-tail functions (extra *_over_time reducers, sort family, min_of/max_of) unsupported

1 participant