mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-10-27 06:06:19 +00:00
* fix(promql): honor @ modifier on subqueries `prom_subquery_expr_to_plan` never read the `at` field of a subquery, so `sum_over_time(m[20s:10s] @ 60)` was evaluated like `m[20s:10s]` and followed the outer evaluation grid. Handle `@` the way Prometheus does: fold the anchor into the subquery offset (`offset + (eval_start - anchor)`, as `setOffsetForAtModifier` does), evaluate the subquery once at the start of the evaluation, and replay the folded window over the outer grid, reusing the anchored range selector machinery. A call whose range argument is an anchored subquery is promoted as step-invariant, like one over an anchored range selector. `@ start()`/`@ end()` and `offset` combine as for selectors, and an unrepresentable anchor is rejected with the existing error. Closes #9411 Signed-off-by: Aarav <aaravsjadav@gmail.com> * test(promql): add sqlness cases for @ on subqueries Cover the #9411 reproducer end to end: `@ <ts>`, `@ start()`/`@ end()`, `@` combined with `offset` in either order, an instant query away from the anchor, `*_over_time` functions and `rate` over an anchored subquery, a computed inner expression, and an aggregation above the anchored call. Two series per table so a dropped or merged series shows up as a wrong row. Refs #9411 Signed-off-by: Aarav <aaravsjadav@gmail.com> --------- Signed-off-by: Aarav <aaravsjadav@gmail.com>
93 lines
3.6 KiB
SQL
93 lines
3.6 KiB
SQL
-- Tests for the PromQL `@` modifier on subqueries.
|
|
--
|
|
-- Prometheus folds the `@` of a subquery into its offset (`setOffsetForAtModifier`) and treats
|
|
-- the subquery as step-invariant: every evaluation step reports the window
|
|
-- `(anchor - offset - range, anchor - offset]`, sampled on the absolute multiples of the subquery
|
|
-- step, exactly like `@` on a range selector. `@ start()` / `@ end()` anchor at the start/end of
|
|
-- the statement's evaluation range. The output timestamps still follow the evaluation grid.
|
|
--
|
|
-- Two series with different values, so that a dropped or merged series shows up as a wrong row.
|
|
-- Sample timestamps are in milliseconds, while `@` and `TQL EVAL` timestamps are in seconds.
|
|
-- The samples lie on the 10s subquery step grid.
|
|
|
|
CREATE TABLE subquery_at_total (
|
|
ts TIMESTAMP TIME INDEX,
|
|
host STRING PRIMARY KEY,
|
|
val DOUBLE,
|
|
);
|
|
|
|
INSERT INTO subquery_at_total VALUES
|
|
(0, 'a', 1),
|
|
(10000, 'a', 2),
|
|
(20000, 'a', 3),
|
|
(30000, 'a', 4),
|
|
(40000, 'a', 5),
|
|
(50000, 'a', 6),
|
|
(60000, 'a', 7),
|
|
(0, 'b', 10),
|
|
(10000, 'b', 20),
|
|
(20000, 'b', 30),
|
|
(30000, 'b', 40),
|
|
(40000, 'b', 50),
|
|
(50000, 'b', 60),
|
|
(60000, 'b', 70);
|
|
|
|
-- The range selector form folds (40s, 60s] at every step: 6 + 7 = 13 (and 130 for 'b').
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s] @ 60);
|
|
|
|
-- The subquery with `@ 60` must report the same window at every step.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s] @ 60);
|
|
|
|
-- Baseline without `@`: the window follows the grid, 3 + 4 at 30s and 6 + 7 at 60s.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s]);
|
|
|
|
-- `@ end()` anchors at 60s: 13 at both steps.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s] @ end());
|
|
|
|
-- `@ start()` anchors at 30s: (10s, 30s] holds 3 + 4 = 7 at both steps.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s] @ start());
|
|
|
|
-- `offset` applies relative to the anchor, in either modifier order: `@ 60 offset 30s` folds
|
|
-- (10s, 30s] = 7 at both steps.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s] @ 60 offset 30s);
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time(subquery_at_total[20s:10s] offset 30s @ 60);
|
|
|
|
-- An instant query away from the anchor still folds the anchored window: 13.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (0, 0, '1s') sum_over_time(subquery_at_total[20s:10s] @ 60);
|
|
|
|
-- Other `*_over_time` functions over the anchored window (40s, 60s]: points 50s and 60s.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') max_over_time(subquery_at_total[20s:10s] @ 60);
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') count_over_time(subquery_at_total[20s:10s] @ 60);
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') avg_over_time(subquery_at_total[20s:10s] @ 60);
|
|
|
|
-- `rate` over (30s, 60s] -- points 40s, 50s, 60s -- extrapolates from the anchored window, not
|
|
-- from the evaluation step, so the subquery form matches the range selector form at every step.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') rate(subquery_at_total[30s] @ 60);
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') rate(subquery_at_total[30s:10s] @ 60);
|
|
|
|
-- A computed inner expression and an aggregation above the anchored call.
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum_over_time((subquery_at_total * 2)[20s:10s] @ 60);
|
|
|
|
-- SQLNESS SORT_RESULT 3 1
|
|
TQL EVAL (30, 60, '30s') sum(sum_over_time(subquery_at_total[20s:10s] @ 60));
|
|
|
|
DROP TABLE subquery_at_total;
|