feat: adapt prometheus 3.x matrix selector behavior change (#7671)

feat: adapt prometheus 3.x matrix selector behavior

Signed-off-by: Ruihang Xia <waynestxia@gmail.com>
This commit is contained in:
Ruihang Xia
2026-02-06 11:06:33 +08:00
committed by GitHub
parent 581c777dce
commit a10d40e552
13 changed files with 176 additions and 145 deletions

View File

@@ -746,7 +746,7 @@ impl RangeManipulateStream {
while cursor < ts_column.len() {
let ts = ts_column.value(cursor);
if range_start > cursor && ts >= start_ts {
if range_start > cursor && ts > start_ts {
range_start = cursor;
range_start_index = range_start;
}
@@ -1009,14 +1009,14 @@ mod test {
1970-01-01T00:05:00,\n\
]\nRangeArray { \
base array: PrimitiveArray<Float64>\n[\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n], \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(0..4), Some(1..5), Some(2..5), Some(3..6), Some(4..6), Some(5..7), Some(5..8), Some(6..10)] \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(1..4), Some(2..5), Some(3..5), Some(4..6), Some(5..6), Some(5..7), Some(6..8), Some(6..10)] \
}\nRangeArray { \
base array: PrimitiveArray<Float64>\n[\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n 1.0,\n], \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(0..4), Some(1..5), Some(2..5), Some(3..6), Some(4..6), Some(5..7), Some(5..8), Some(6..10)] \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(1..4), Some(2..5), Some(3..5), Some(4..6), Some(5..6), Some(5..7), Some(6..8), Some(6..10)] \
}\nStringArray\n[\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n \"foo\",\n]\n\
RangeArray { \
base array: PrimitiveArray<Timestamp(ms)>\n[\n 1970-01-01T00:00:00,\n 1970-01-01T00:00:30,\n 1970-01-01T00:01:00,\n 1970-01-01T00:01:30,\n 1970-01-01T00:02:00,\n 1970-01-01T00:03:00,\n 1970-01-01T00:04:00,\n 1970-01-01T00:04:01,\n 1970-01-01T00:04:31,\n 1970-01-01T00:04:51,\n], \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(0..4), Some(1..5), Some(2..5), Some(3..6), Some(4..6), Some(5..7), Some(5..8), Some(6..10)] \
ranges: [Some(0..1), Some(0..2), Some(0..3), Some(1..4), Some(2..5), Some(3..5), Some(4..6), Some(5..6), Some(5..7), Some(6..8), Some(6..10)] \
}",
);
do_normalize_test(0, 310_000, 30_000, 90_000, expected.clone()).await;

View File

@@ -31,7 +31,7 @@ tql eval (3, 3, '1s') predict_linear(prom_series[3s], 0);
+---------------------+----------------------------------------------+------+
| ts | prom_predict_linear(ts_range,val,Float64(0)) | host |
+---------------------+----------------------------------------------+------+
| 1970-01-01T00:00:03 | 38.63636363636364 | p |
| 1970-01-01T00:00:03 | 37.27272727272727 | p |
+---------------------+----------------------------------------------+------+
-- SQLNESS SORT_RESULT 3 1
@@ -40,7 +40,7 @@ tql eval (3, 3, '1s') predict_linear(prom_series[3s], 3);
+---------------------+----------------------------------------------+------+
| ts | prom_predict_linear(ts_range,val,Float64(3)) | host |
+---------------------+----------------------------------------------+------+
| 1970-01-01T00:00:03 | 70.45454545454547 | p |
| 1970-01-01T00:00:03 | 64.54545454545455 | p |
+---------------------+----------------------------------------------+------+
-- SQLNESS SORT_RESULT 3 1
@@ -49,7 +49,7 @@ tql eval (3, 3, '1s') predict_linear(prom_series[3s], 40 + 2);
+---------------------+------------------------------------------------------------+------+
| ts | prom_predict_linear(ts_range,val,Float64(40) + Float64(2)) | host |
+---------------------+------------------------------------------------------------+------+
| 1970-01-01T00:00:03 | 484.0909090909091 | p |
| 1970-01-01T00:00:03 | 419.090909090909 | p |
+---------------------+------------------------------------------------------------+------+
-- holt_winters

View File

@@ -58,9 +58,9 @@ TQL EVAL (0, 15, '5s') avg_over_time(host_sec{host="host1"}[5s]);
| ts | prom_avg_over_time(ts_range,val) | host |
+---------------------+----------------------------------+-------+
| 1970-01-01T00:00:00 | 1.0 | host1 |
| 1970-01-01T00:00:05 | 2.0 | host1 |
| 1970-01-01T00:00:10 | 4.0 | host1 |
| 1970-01-01T00:00:15 | 6.0 | host1 |
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
+---------------------+----------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
@@ -82,9 +82,9 @@ TQL EVAL (0, 15, '5s') avg_over_time(host_micro{host="host1"}[5s]);
| ts | prom_avg_over_time(ts_range,val) | host |
+---------------------+----------------------------------+-------+
| 1970-01-01T00:00:00 | 1.0 | host1 |
| 1970-01-01T00:00:05 | 2.0 | host1 |
| 1970-01-01T00:00:10 | 4.0 | host1 |
| 1970-01-01T00:00:15 | 6.0 | host1 |
| 1970-01-01T00:00:05 | 3.0 | host1 |
| 1970-01-01T00:00:10 | 5.0 | host1 |
| 1970-01-01T00:00:15 | 7.0 | host1 |
+---------------------+----------------------------------+-------+
-- SQLNESS SORT_RESULT 3 1
@@ -106,9 +106,9 @@ TQL EVAL (0, 15, '5s') avg_over_time(host_sec{host="host1"}[5s]) + avg_over_time
| host | ts | host_sec.prom_avg_over_time(ts_range,val) + host_micro.prom_avg_over_time(ts_range,val) |
+-------+---------------------+-----------------------------------------------------------------------------------------+
| host1 | 1970-01-01T00:00:00 | 2.0 |
| host1 | 1970-01-01T00:00:05 | 4.0 |
| host1 | 1970-01-01T00:00:10 | 8.0 |
| host1 | 1970-01-01T00:00:15 | 12.0 |
| host1 | 1970-01-01T00:00:05 | 6.0 |
| host1 | 1970-01-01T00:00:10 | 10.0 |
| host1 | 1970-01-01T00:00:15 | 14.0 |
+-------+---------------------+-----------------------------------------------------------------------------------------+
DROP TABLE host_sec;

View File

@@ -827,9 +827,6 @@ tql eval(1000, 2000, '300s') sum by (src, src_pod, src_namespace, src_node, dest
| 1970-01-01T00:26:40 | us-west-6 | cloud-1 | 10.0.0.2 | us-west | 10.0.0.1 | namespace-1 | node-1 | pod-1 | 2500.0 |
| 1970-01-01T00:26:40 | us-west-6 | cloud-1 | 10.0.0.3 | us-west | 10.0.0.1 | namespace-1 | node-2 | pod-2 | 2000.0 |
| 1970-01-01T00:26:40 | us-west-6 | cloud-2 | 10.0.0.5 | us-west | 10.0.0.4 | namespace-2 | node-3 | pod-3 | 2300.0 |
| 1970-01-01T00:31:40 | us-west-6 | cloud-1 | 10.0.0.2 | us-west | 10.0.0.1 | namespace-1 | node-1 | pod-1 | 1500.0 |
| 1970-01-01T00:31:40 | us-west-6 | cloud-1 | 10.0.0.3 | us-west | 10.0.0.1 | namespace-1 | node-2 | pod-2 | 1500.0 |
| 1970-01-01T00:31:40 | us-west-6 | cloud-2 | 10.0.0.5 | us-west | 10.0.0.4 | namespace-2 | node-3 | pod-3 | 1500.0 |
+---------------------+-----------+---------+----------+---------+----------+---------------+----------+---------+----------------------------------------------------------------------------------------------+
DROP TABLE node_network_transmit_bytes_total;

View File

@@ -32,33 +32,33 @@ WITH(
Affected Rows: 0
-- Counter samples at t=0 and t=5m (300000ms). `rate(...[5m])` uses the delta in this window.
-- Counter samples at t=1ms and t=5m (300000ms). `rate(...[5m])` uses the delta in this window.
INSERT INTO promql_stats_mismatch_hist_bucket (`cluster`, le, instance, operation, `type`, ts, val) VALUES
-- t = 0
('cluster', '0.5', 'inst1', 'op', 't', 0, 0),
('cluster', '1', 'inst1', 'op', 't', 0, 0),
('cluster', '2', 'inst1', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst1', 'op', 't', 0, 0),
('cluster', '0.5', 'inst2', 'op', 't', 0, 0),
('cluster', '1', 'inst2', 'op', 't', 0, 0),
('cluster', '2', 'inst2', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst2', 'op', 't', 0, 0),
('cluster', '0.5', 'inst3', 'op', 't', 0, 0),
('cluster', '1', 'inst3', 'op', 't', 0, 0),
('cluster', '2', 'inst3', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst3', 'op', 't', 0, 0),
('cluster', '0.5', 'inst4', 'op', 't', 0, 0),
('cluster', '1', 'inst4', 'op', 't', 0, 0),
('cluster', '2', 'inst4', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst4', 'op', 't', 0, 0),
('cluster', '0.5', 'inst5', 'op', 't', 0, 0),
('cluster', '1', 'inst5', 'op', 't', 0, 0),
('cluster', '2', 'inst5', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst5', 'op', 't', 0, 0),
('cluster', '0.5', 'inst6', 'op', 't', 0, 0),
('cluster', '1', 'inst6', 'op', 't', 0, 0),
('cluster', '2', 'inst6', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst6', 'op', 't', 0, 0),
-- t = 1ms (avoid range-start boundary exclusion)
('cluster', '0.5', 'inst1', 'op', 't', 1, 0),
('cluster', '1', 'inst1', 'op', 't', 1, 0),
('cluster', '2', 'inst1', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst1', 'op', 't', 1, 0),
('cluster', '0.5', 'inst2', 'op', 't', 1, 0),
('cluster', '1', 'inst2', 'op', 't', 1, 0),
('cluster', '2', 'inst2', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst2', 'op', 't', 1, 0),
('cluster', '0.5', 'inst3', 'op', 't', 1, 0),
('cluster', '1', 'inst3', 'op', 't', 1, 0),
('cluster', '2', 'inst3', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst3', 'op', 't', 1, 0),
('cluster', '0.5', 'inst4', 'op', 't', 1, 0),
('cluster', '1', 'inst4', 'op', 't', 1, 0),
('cluster', '2', 'inst4', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst4', 'op', 't', 1, 0),
('cluster', '0.5', 'inst5', 'op', 't', 1, 0),
('cluster', '1', 'inst5', 'op', 't', 1, 0),
('cluster', '2', 'inst5', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst5', 'op', 't', 1, 0),
('cluster', '0.5', 'inst6', 'op', 't', 1, 0),
('cluster', '1', 'inst6', 'op', 't', 1, 0),
('cluster', '2', 'inst6', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst6', 'op', 't', 1, 0),
-- t = 300000ms (5m)
('cluster', '0.5', 'inst1', 'op', 't', 300000, 95),
('cluster', '1', 'inst1', 'op', 't', 300000, 98),

View File

@@ -30,33 +30,33 @@ WITH(
on_physical_table = 'promql_stats_mismatch_physical'
);
-- Counter samples at t=0 and t=5m (300000ms). `rate(...[5m])` uses the delta in this window.
-- Counter samples at t=1ms and t=5m (300000ms). `rate(...[5m])` uses the delta in this window.
INSERT INTO promql_stats_mismatch_hist_bucket (`cluster`, le, instance, operation, `type`, ts, val) VALUES
-- t = 0
('cluster', '0.5', 'inst1', 'op', 't', 0, 0),
('cluster', '1', 'inst1', 'op', 't', 0, 0),
('cluster', '2', 'inst1', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst1', 'op', 't', 0, 0),
('cluster', '0.5', 'inst2', 'op', 't', 0, 0),
('cluster', '1', 'inst2', 'op', 't', 0, 0),
('cluster', '2', 'inst2', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst2', 'op', 't', 0, 0),
('cluster', '0.5', 'inst3', 'op', 't', 0, 0),
('cluster', '1', 'inst3', 'op', 't', 0, 0),
('cluster', '2', 'inst3', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst3', 'op', 't', 0, 0),
('cluster', '0.5', 'inst4', 'op', 't', 0, 0),
('cluster', '1', 'inst4', 'op', 't', 0, 0),
('cluster', '2', 'inst4', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst4', 'op', 't', 0, 0),
('cluster', '0.5', 'inst5', 'op', 't', 0, 0),
('cluster', '1', 'inst5', 'op', 't', 0, 0),
('cluster', '2', 'inst5', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst5', 'op', 't', 0, 0),
('cluster', '0.5', 'inst6', 'op', 't', 0, 0),
('cluster', '1', 'inst6', 'op', 't', 0, 0),
('cluster', '2', 'inst6', 'op', 't', 0, 0),
('cluster', '+Inf', 'inst6', 'op', 't', 0, 0),
-- t = 1ms (avoid range-start boundary exclusion)
('cluster', '0.5', 'inst1', 'op', 't', 1, 0),
('cluster', '1', 'inst1', 'op', 't', 1, 0),
('cluster', '2', 'inst1', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst1', 'op', 't', 1, 0),
('cluster', '0.5', 'inst2', 'op', 't', 1, 0),
('cluster', '1', 'inst2', 'op', 't', 1, 0),
('cluster', '2', 'inst2', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst2', 'op', 't', 1, 0),
('cluster', '0.5', 'inst3', 'op', 't', 1, 0),
('cluster', '1', 'inst3', 'op', 't', 1, 0),
('cluster', '2', 'inst3', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst3', 'op', 't', 1, 0),
('cluster', '0.5', 'inst4', 'op', 't', 1, 0),
('cluster', '1', 'inst4', 'op', 't', 1, 0),
('cluster', '2', 'inst4', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst4', 'op', 't', 1, 0),
('cluster', '0.5', 'inst5', 'op', 't', 1, 0),
('cluster', '1', 'inst5', 'op', 't', 1, 0),
('cluster', '2', 'inst5', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst5', 'op', 't', 1, 0),
('cluster', '0.5', 'inst6', 'op', 't', 1, 0),
('cluster', '1', 'inst6', 'op', 't', 1, 0),
('cluster', '2', 'inst6', 'op', 't', 1, 0),
('cluster', '+Inf', 'inst6', 'op', 't', 1, 0),
-- t = 300000ms (5m)
('cluster', '0.5', 'inst1', 'op', 't', 300000, 95),
('cluster', '1', 'inst1', 'op', 't', 300000, 98),

View File

@@ -90,8 +90,8 @@ TQL EVAL (0, 10, '5s') avg_over_time(tsid_no_aggr_metric[5s]);
| ts | prom_avg_over_time(ts_range,val) | instance | job |
+---------------------+----------------------------------+----------+-----------+
| 1970-01-01T00:00:00 | 1.0 | job1 | instance1 |
| 1970-01-01T00:00:05 | 2.0 | job1 | instance1 |
| 1970-01-01T00:00:10 | 4.0 | job1 | instance1 |
| 1970-01-01T00:00:05 | 3.0 | job1 | instance1 |
| 1970-01-01T00:00:10 | 5.0 | job1 | instance1 |
+---------------------+----------------------------------+----------+-----------+
-- Histogram quantile must fold buckets across `le` even when `__tsid` exists.

View File

@@ -1,4 +1,4 @@
-- Port from functions.test L607 - L630, commit 001ee2620e094970e5657ce39275b2fccdbd1359
-- Port from Prometheus `promql/promqltest/testdata/functions.test`.
-- Include stddev/stdvar over time
-- load 10s
-- metric 0 8 8 2 3
@@ -27,9 +27,9 @@ select * from metric;
| 1970-01-01T00:00:40 | 3.0 |
+---------------------+-----+
-- eval instant at 1m stdvar_over_time(metric[1m])
-- eval instant at 1m stdvar_over_time(metric[2m])
-- {} 10.56
tql eval (60, 61, '10s') stdvar_over_time(metric[1m]);
tql eval (60, 60, '1s') stdvar_over_time(metric[2m]);
+---------------------+-------------------------------------+
| ts | prom_stdvar_over_time(ts_range,val) |
@@ -37,9 +37,9 @@ tql eval (60, 61, '10s') stdvar_over_time(metric[1m]);
| 1970-01-01T00:01:00 | 10.559999999999999 |
+---------------------+-------------------------------------+
-- eval instant at 1m stddev_over_time(metric[1m])
-- eval instant at 1m stddev_over_time(metric[2m])
-- {} 3.249615
tql eval (60, 60, '1s') stddev_over_time(metric[1m]);
tql eval (60, 60, '1s') stddev_over_time(metric[2m]);
+---------------------+-------------------------------------+
| ts | prom_stddev_over_time(ts_range,val) |
@@ -47,9 +47,9 @@ tql eval (60, 60, '1s') stddev_over_time(metric[1m]);
| 1970-01-01T00:01:00 | 3.249615361854384 |
+---------------------+-------------------------------------+
-- eval instant at 1m stddev_over_time((metric[1m]))
-- eval instant at 1m stddev_over_time((metric[2m]))
-- {} 3.249615
tql eval (60, 60, '1s') stddev_over_time((metric[1m]));
tql eval (60, 60, '1s') stddev_over_time((metric[2m]));
+---------------------+-------------------------------------+
| ts | prom_stddev_over_time(ts_range,val) |
@@ -68,31 +68,30 @@ create table metric (ts timestamp(3) time index, val double);
Affected Rows: 0
insert into metric values
(0,0),
(0,1.5990505637277868),
(10000,1.5990505637277868),
(20000,1.5990505637277868),
(30000,1.5990505637277868);
(20000,1.5990505637277868);
Affected Rows: 4
Affected Rows: 3
-- eval instant at 1m stdvar_over_time(metric[1m])
-- eval instant at 55s stdvar_over_time(metric[1m])
-- {} 0
tql eval (60, 60, '1s') stdvar_over_time(metric[1m]);
tql eval (55, 55, '1s') stdvar_over_time(metric[1m]);
+---------------------+-------------------------------------+
| ts | prom_stdvar_over_time(ts_range,val) |
+---------------------+-------------------------------------+
| 1970-01-01T00:01:00 | 0.47943050725465364 |
| 1970-01-01T00:00:55 | 0.0 |
+---------------------+-------------------------------------+
-- eval instant at 1m stddev_over_time(metric[1m])
-- eval instant at 55s stddev_over_time(metric[1m])
-- {} 0
tql eval (60, 60, '1s') stddev_over_time(metric[1m]);
tql eval (55, 55, '1s') stddev_over_time(metric[1m]);
+---------------------+-------------------------------------+
| ts | prom_stddev_over_time(ts_range,val) |
+---------------------+-------------------------------------+
| 1970-01-01T00:01:00 | 0.6924092050620454 |
| 1970-01-01T00:00:55 | 0.0 |
+---------------------+-------------------------------------+
drop table metric;

View File

@@ -1,4 +1,4 @@
-- Port from functions.test L607 - L630, commit 001ee2620e094970e5657ce39275b2fccdbd1359
-- Port from Prometheus `promql/promqltest/testdata/functions.test`.
-- Include stddev/stdvar over time
-- load 10s
@@ -14,17 +14,17 @@ insert into metric values
select * from metric;
-- eval instant at 1m stdvar_over_time(metric[1m])
-- eval instant at 1m stdvar_over_time(metric[2m])
-- {} 10.56
tql eval (60, 61, '10s') stdvar_over_time(metric[1m]);
tql eval (60, 60, '1s') stdvar_over_time(metric[2m]);
-- eval instant at 1m stddev_over_time(metric[1m])
-- eval instant at 1m stddev_over_time(metric[2m])
-- {} 3.249615
tql eval (60, 60, '1s') stddev_over_time(metric[1m]);
tql eval (60, 60, '1s') stddev_over_time(metric[2m]);
-- eval instant at 1m stddev_over_time((metric[1m]))
-- eval instant at 1m stddev_over_time((metric[2m]))
-- {} 3.249615
tql eval (60, 60, '1s') stddev_over_time((metric[1m]));
tql eval (60, 60, '1s') stddev_over_time((metric[2m]));
drop table metric;
@@ -33,18 +33,17 @@ drop table metric;
create table metric (ts timestamp(3) time index, val double);
insert into metric values
(0,0),
(0,1.5990505637277868),
(10000,1.5990505637277868),
(20000,1.5990505637277868),
(30000,1.5990505637277868);
(20000,1.5990505637277868);
-- eval instant at 1m stdvar_over_time(metric[1m])
-- eval instant at 55s stdvar_over_time(metric[1m])
-- {} 0
tql eval (60, 60, '1s') stdvar_over_time(metric[1m]);
tql eval (55, 55, '1s') stdvar_over_time(metric[1m]);
-- eval instant at 1m stddev_over_time(metric[1m])
-- eval instant at 55s stddev_over_time(metric[1m])
-- {} 0
tql eval (60, 60, '1s') stddev_over_time(metric[1m]);
tql eval (55, 55, '1s') stddev_over_time(metric[1m]);
drop table metric;

View File

@@ -13,25 +13,40 @@ Affected Rows: 0
INSERT INTO metrics VALUES
-- host1, service1
(0, 10, 'host1', 'service1'),
(30000, 15, 'host1', 'service1'),
(60000, 20, 'host1', 'service1'),
(90000, 25, 'host1', 'service1'),
(120000, 30, 'host1', 'service1'),
(150000, 35, 'host1', 'service1'),
(180000, 40, 'host1', 'service1'),
(210000, 45, 'host1', 'service1'),
(240000, 50, 'host1', 'service1'),
-- host1, service2
(0, 5, 'host1', 'service2'),
(30000, 10, 'host1', 'service2'),
(60000, 15, 'host1', 'service2'),
(90000, 20, 'host1', 'service2'),
(120000, 25, 'host1', 'service2'),
(150000, 30, 'host1', 'service2'),
(180000, 35, 'host1', 'service2'),
(210000, 40, 'host1', 'service2'),
(240000, 45, 'host1', 'service2'),
-- host2, service1
(0, 8, 'host2', 'service1'),
(30000, 13, 'host2', 'service1'),
(60000, 18, 'host2', 'service1'),
(90000, 23, 'host2', 'service1'),
(120000, 28, 'host2', 'service1'),
(180000, 38, 'host2', 'service1');
(150000, 33, 'host2', 'service1'),
(180000, 38, 'host2', 'service1'),
(210000, 43, 'host2', 'service1'),
(240000, 48, 'host2', 'service1');
Affected Rows: 12
Affected Rows: 27
-- Test basic sum(rate()) - sum rate across all series
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics[1m]));
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -43,7 +58,7 @@ TQL EVAL (0, 180, '60s') sum(rate(metrics[1m]));
-- Test sum(rate()) with grouping by host
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum by(host) (rate(metrics[1m]));
+-------+---------------------+----------------------------------------------+
| host | ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -58,7 +73,7 @@ TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m]));
-- Test sum(rate()) with grouping by service
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(service) (rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum by(service) (rate(metrics[1m]));
+----------+---------------------+----------------------------------------------+
| service | ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -73,7 +88,7 @@ TQL EVAL (0, 180, '60s') sum by(service) (rate(metrics[1m]));
-- Test sum(rate()) with label filtering
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1"}[1m]));
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -85,7 +100,7 @@ TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1"}[1m]));
-- Test sum(rate()) with multiple label filters
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1", service="service1"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1", service="service1"}[1m]));
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -97,7 +112,7 @@ TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1", service="service1"}[1m])
-- Test sum(rate()) with regex label matching
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host=~"host.*"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host=~"host.*"}[1m]));
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -109,14 +124,19 @@ TQL EVAL (0, 180, '60s') sum(rate(metrics{host=~"host.*"}[1m]));
-- Test sum(rate()) with different time ranges
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[30s]));
TQL EVAL (60, 180, '60s') sum(rate(metrics[31s]));
++
++
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(31000))) |
+---------------------+----------------------------------------------+
| 1970-01-01T00:01:00 | 0.5 |
| 1970-01-01T00:02:00 | 0.5 |
| 1970-01-01T00:03:00 | 0.5 |
+---------------------+----------------------------------------------+
-- Test sum(rate()) with longer evaluation window
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 240, '60s') sum(rate(metrics[1m]));
TQL EVAL (60, 240, '60s') sum(rate(metrics[1m]));
+---------------------+----------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) |
@@ -124,11 +144,12 @@ TQL EVAL (0, 240, '60s') sum(rate(metrics[1m]));
| 1970-01-01T00:01:00 | 0.5 |
| 1970-01-01T00:02:00 | 0.5 |
| 1970-01-01T00:03:00 | 0.5 |
| 1970-01-01T00:04:00 | 0.5 |
+---------------------+----------------------------------------------+
-- Test sum(rate()) combined with arithmetic operations
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[1m])) * 100;
TQL EVAL (60, 180, '60s') sum(rate(metrics[1m])) * 100;
+---------------------+-------------------------------------------------------------+
| ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) * Float64(100) |
@@ -140,7 +161,7 @@ TQL EVAL (0, 180, '60s') sum(rate(metrics[1m])) * 100;
-- Test sum(rate()) with grouping and arithmetic
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m])) * 60;
TQL EVAL (60, 180, '60s') sum by(host) (rate(metrics[1m])) * 60;
+-------+---------------------+------------------------------------------------------------+
| host | ts | sum(prom_rate(ts_range,val,ts,Int64(60000))) * Float64(60) |
@@ -154,43 +175,43 @@ TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m])) * 60;
+-------+---------------------+------------------------------------------------------------+
-- Test querying non-existent table
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table[1m]));
++
++
-- Test querying non-existent label
TQL EVAL (0, 180, '60s') sum(rate(metrics{non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{non_existent_label="value"}[1m]));
++
++
-- Test querying non-existent label value
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="non_existent_host"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="non_existent_host"}[1m]));
++
++
-- Test querying multiple non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(metrics{non_existent_label1="value1", non_existent_label2="value2"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{non_existent_label1="value1", non_existent_label2="value2"}[1m]));
++
++
-- Test querying mix of existing and non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1", non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1", non_existent_label="value"}[1m]));
++
++
-- Test querying non-existent table with non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table{non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table{non_existent_label="value"}[1m]));
++
++
-- Test querying non-existent table with multiple non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table{label1="value1", label2="value2"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table{label1="value1", label2="value2"}[1m]));
++
++

View File

@@ -11,79 +11,94 @@ CREATE TABLE metrics (
INSERT INTO metrics VALUES
-- host1, service1
(0, 10, 'host1', 'service1'),
(30000, 15, 'host1', 'service1'),
(60000, 20, 'host1', 'service1'),
(90000, 25, 'host1', 'service1'),
(120000, 30, 'host1', 'service1'),
(150000, 35, 'host1', 'service1'),
(180000, 40, 'host1', 'service1'),
(210000, 45, 'host1', 'service1'),
(240000, 50, 'host1', 'service1'),
-- host1, service2
(0, 5, 'host1', 'service2'),
(30000, 10, 'host1', 'service2'),
(60000, 15, 'host1', 'service2'),
(90000, 20, 'host1', 'service2'),
(120000, 25, 'host1', 'service2'),
(150000, 30, 'host1', 'service2'),
(180000, 35, 'host1', 'service2'),
(210000, 40, 'host1', 'service2'),
(240000, 45, 'host1', 'service2'),
-- host2, service1
(0, 8, 'host2', 'service1'),
(30000, 13, 'host2', 'service1'),
(60000, 18, 'host2', 'service1'),
(90000, 23, 'host2', 'service1'),
(120000, 28, 'host2', 'service1'),
(180000, 38, 'host2', 'service1');
(150000, 33, 'host2', 'service1'),
(180000, 38, 'host2', 'service1'),
(210000, 43, 'host2', 'service1'),
(240000, 48, 'host2', 'service1');
-- Test basic sum(rate()) - sum rate across all series
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics[1m]));
-- Test sum(rate()) with grouping by host
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum by(host) (rate(metrics[1m]));
-- Test sum(rate()) with grouping by service
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(service) (rate(metrics[1m]));
TQL EVAL (60, 180, '60s') sum by(service) (rate(metrics[1m]));
-- Test sum(rate()) with label filtering
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1"}[1m]));
-- Test sum(rate()) with multiple label filters
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1", service="service1"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1", service="service1"}[1m]));
-- Test sum(rate()) with regex label matching
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics{host=~"host.*"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host=~"host.*"}[1m]));
-- Test sum(rate()) with different time ranges
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[30s]));
TQL EVAL (60, 180, '60s') sum(rate(metrics[31s]));
-- Test sum(rate()) with longer evaluation window
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 240, '60s') sum(rate(metrics[1m]));
TQL EVAL (60, 240, '60s') sum(rate(metrics[1m]));
-- Test sum(rate()) combined with arithmetic operations
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum(rate(metrics[1m])) * 100;
TQL EVAL (60, 180, '60s') sum(rate(metrics[1m])) * 100;
-- Test sum(rate()) with grouping and arithmetic
-- SQLNESS SORT_RESULT 2 1
TQL EVAL (0, 180, '60s') sum by(host) (rate(metrics[1m])) * 60;
TQL EVAL (60, 180, '60s') sum by(host) (rate(metrics[1m])) * 60;
-- Test querying non-existent table
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table[1m]));
-- Test querying non-existent label
TQL EVAL (0, 180, '60s') sum(rate(metrics{non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{non_existent_label="value"}[1m]));
-- Test querying non-existent label value
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="non_existent_host"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="non_existent_host"}[1m]));
-- Test querying multiple non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(metrics{non_existent_label1="value1", non_existent_label2="value2"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{non_existent_label1="value1", non_existent_label2="value2"}[1m]));
-- Test querying mix of existing and non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(metrics{host="host1", non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(metrics{host="host1", non_existent_label="value"}[1m]));
-- Test querying non-existent table with non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table{non_existent_label="value"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table{non_existent_label="value"}[1m]));
-- Test querying non-existent table with multiple non-existent labels
TQL EVAL (0, 180, '60s') sum(rate(non_existent_table{label1="value1", label2="value2"}[1m]));
TQL EVAL (60, 180, '60s') sum(rate(non_existent_table{label1="value1", label2="value2"}[1m]));
DROP TABLE metrics;

View File

@@ -180,7 +180,7 @@ SELECT sum(val) FROM filtered;
+-------------------+
| sum(filtered.val) |
+-------------------+
| 1.05 |
| 0.7 |
+-------------------+
-- SQLNESS REPLACE (peers.*) REDACTED

View File

@@ -82,7 +82,7 @@ TQL ANALYZE (0, 10, '5s') sum(rate(promql_column_pruning[5s]));
|_|_|_CooperativeExec REDACTED
|_|_|_SeriesScan: region=REDACTED, "partition_count":{"count":1, "mem_ranges":1, "files":0, "file_ranges":0}, "distribution":"PerSeries" REDACTED
|_|_|_|
|_|_| Total rows: 2_|
|_|_| Total rows: 0_|
+-+-+-+
DROP TABLE promql_column_pruning;