Repository navigation
PromQL: non-literal scalar parameters (topk(scalar(foo), v), quantile(scalar(f), v), limit_ratio(time()%17/17, v)) #120
Description
Summary
topk / bottomk / quantile / limitk / limit_ratio accept a scalar-valued expression as their k / φ / ratio parameter. We require a literal (after constant folding), and reject everything else:
topk(scalar(foo), http_requests)
→ invalid parameter: expected a numeric scalar, got Discriminant(9)
Split out of #109, whose histogram_quantiles half landed separately. The two share the issue title but nothing else.
Corpus impact
11 rejections. Every one needs a scalar subtree, not a number:
topk(scalar(foo), http_requests)
count(bottomk(scalar(foo), http_requests))
quantile without(point)(scalar(foo), data)
quantile_over_time(scalar(up) + 1, {__name__="up"}[1h:1m] @ 1111111)
count(limitk(scalar(foo), http_requests))
count(limit_ratio(scalar(bar), http_requests))
count(limit_ratio(time() % 17/17, http_requests) or …)
num_expr already constant-folds pure arithmetic (10*1024*1024), so what is missing is specifically a parameter that depends on the data or the evaluation time.
Why this is not a small change
The parameter is baked into the intent as a plain value:
AggIntent::TopK { k: usize, accuracy }
AggIntent::Quantile { col, q: f64, accuracy }
QueryExpr::Sample { kind: SampleKind, … } // limitk / limit_ratioand read back out at L4:
SketchQuery::TopK { k: usize } // crates/sketch
SketchQuery::Quantile { q: f64 }Making these expressions means:
- The IR has to carry a scalar subtree (
Box<QueryExpr>/ anL3Scalarexpression) in each parameter slot. plan::boundarydecides sketch-vs-exact per intent. It keys onAccuracyTarget, not onk, so the decision survives — but the sketch readout (SketchQuery::TopK { k }) needskat estimate time, which is now a runtime value.plan::csededupes onAggIntentequality; a parameter subtree has to participate in that equality.- Schema derivation names the quantile output column after φ (
quantile_0_99). With a non-literal φ there is no name to derive — the same union-compatibility problemhistogram_quantileshit (see thevaluealiasing inwalk_histogram_quantiles).
Point 4 is the interesting one: it suggests the output-column naming convention, not just the parameter type, needs revisiting.
Suggested scope
Probably two steps:
- Step 1 — allow a scalar parameter that is constant per evaluation (
scalar(foo)still varies per step, so this does not cover the corpus; buttime()-free folding already works). Low value on its own. - Step 2 — a real
ScalarExprparameter slot threaded to the L4 readout. This is the one the corpus needs.
Worth confirming whether an approximate TopK with a runtime k is even wanted: a CMS+heap is sized by ε, not k, so the sketch is buildable — only the readout needs k. That is a point in favour of step 2 being tractable.
Notes
quantile_param/topk-kvalidation would move to evaluation time for the non-literal case, which also changes where the out-of-range diagnostics in PromQL: histogram_quantiles() and non-literal scalar k/φ parameters unsupported #109 surface.- Rejection site:
crates/frontend-promql/src/promql.rs,num_expr/num_param.
Activity
feat(promql): lower histogram_quantiles as a per-φ Merge fan-out (#109)…
zzylol commentedon Aug 26, 2026
Related open work