From bd3ad6091014d22c528706334b0a630627881954 Mon Sep 17 00:00:00 2001 From: Ruihang Xia Date: Fri, 12 Dec 2025 15:51:35 +0800 Subject: [PATCH] fix: promql offset direction (#7392) * fix: promql offset direction Signed-off-by: Ruihang Xia * sort sqlness result Signed-off-by: Ruihang Xia * commit forgotten file Signed-off-by: Ruihang Xia --------- Signed-off-by: Ruihang Xia --- src/promql/src/extension_plan/normalize.rs | 12 ++--- src/query/src/promql/planner.rs | 8 ++-- .../standalone/common/promql/offset.result | 45 ++++++++++--------- .../cases/standalone/common/promql/offset.sql | 3 ++ .../common/promql/offset_direction.result | 44 ++++++++++++++++++ .../common/promql/offset_direction.sql | 20 +++++++++ .../standalone/common/tql/tql-cte.result | 15 +++---- 7 files changed, 106 insertions(+), 41 deletions(-) create mode 100644 tests/cases/standalone/common/promql/offset_direction.result create mode 100644 tests/cases/standalone/common/promql/offset_direction.sql diff --git a/src/promql/src/extension_plan/normalize.rs b/src/promql/src/extension_plan/normalize.rs index ccd21a9cd7..9466508607 100644 --- a/src/promql/src/extension_plan/normalize.rs +++ b/src/promql/src/extension_plan/normalize.rs @@ -365,7 +365,7 @@ impl SeriesNormalizeStream { Arc::new(ts_column.clone()) as _ } else { Arc::new(TimestampMillisecondArray::from_iter( - ts_column.iter().map(|ts| ts.map(|ts| ts - self.offset)), + ts_column.iter().map(|ts| ts.map(|ts| ts + self.offset)), )) }; let mut columns = input.columns().to_vec(); @@ -518,11 +518,11 @@ mod test { "+---------------------+--------+------+\ \n| timestamp | value | path |\ \n+---------------------+--------+------+\ - \n| 1970-01-01T00:00:59 | 0.0 | foo |\ - \n| 1970-01-01T00:01:59 | 1.0 | foo |\ - \n| 1969-12-31T23:59:59 | 10.0 | foo |\ - \n| 1970-01-01T00:00:29 | 100.0 | foo |\ - \n| 1970-01-01T00:01:29 | 1000.0 | foo |\ + \n| 1970-01-01T00:01:01 | 0.0 | foo |\ + \n| 1970-01-01T00:02:01 | 1.0 | foo |\ + \n| 1970-01-01T00:00:01 | 10.0 | foo |\ + \n| 1970-01-01T00:00:31 | 100.0 | foo |\ + \n| 1970-01-01T00:01:31 | 1000.0 | foo |\ \n+---------------------+--------+------+", ); diff --git a/src/query/src/promql/planner.rs b/src/query/src/promql/planner.rs index 5cc26cee05..8fc90d7f71 100644 --- a/src/query/src/promql/planner.rs +++ b/src/query/src/promql/planner.rs @@ -1414,14 +1414,14 @@ impl PromPlanner { .clone() .gt_eq(DfExpr::Literal( ScalarValue::TimestampMillisecond( - Some(self.ctx.start + offset_duration - self.ctx.lookback_delta - range), + Some(self.ctx.start - offset_duration - self.ctx.lookback_delta - range), None, ), None, )) .and(time_index_expr.lt_eq(DfExpr::Literal( ScalarValue::TimestampMillisecond( - Some(self.ctx.end + offset_duration + self.ctx.lookback_delta), + Some(self.ctx.end - offset_duration + self.ctx.lookback_delta), None, ), None, @@ -1437,14 +1437,14 @@ impl PromPlanner { .clone() .gt_eq(DfExpr::Literal( ScalarValue::TimestampMillisecond( - Some(timestamp + offset_duration - lookback_delta - range), + Some(timestamp - offset_duration - lookback_delta - range), None, ), None, )) .and(time_index_expr.clone().lt_eq(DfExpr::Literal( ScalarValue::TimestampMillisecond( - Some(timestamp + offset_duration + lookback_delta), + Some(timestamp - offset_duration + lookback_delta), None, ), None, diff --git a/tests/cases/standalone/common/promql/offset.result b/tests/cases/standalone/common/promql/offset.result index f5787928d8..760e1ac333 100644 --- a/tests/cases/standalone/common/promql/offset.result +++ b/tests/cases/standalone/common/promql/offset.result @@ -46,16 +46,6 @@ tql eval (1500, 1500, '1s') calculate_rate_offset_total; -- SQLNESS SORT_RESULT 3 1 tql eval (1500, 1500, '1s') calculate_rate_offset_total offset 10m; -+---------------------+-------+---+ -| ts | val | x | -+---------------------+-------+---+ -| 1970-01-01T00:25:00 | 140.0 | b | -| 1970-01-01T00:25:00 | 70.0 | a | -+---------------------+-------+---+ - --- SQLNESS SORT_RESULT 3 1 -tql eval (1500, 1500, '1s') calculate_rate_offset_total offset -10m; - +---------------------+------+---+ | ts | val | x | +---------------------+------+---+ @@ -63,9 +53,25 @@ tql eval (1500, 1500, '1s') calculate_rate_offset_total offset -10m; | 1970-01-01T00:25:00 | 60.0 | b | +---------------------+------+---+ +-- SQLNESS SORT_RESULT 3 1 +tql eval (1500, 1500, '1s') calculate_rate_offset_total offset -10m; + ++---------------------+-------+---+ +| ts | val | x | ++---------------------+-------+---+ +| 1970-01-01T00:25:00 | 140.0 | b | +| 1970-01-01T00:25:00 | 70.0 | a | ++---------------------+-------+---+ + -- SQLNESS SORT_RESULT 3 1 tql eval (0, 0, '1s') calculate_rate_offset_total offset 10m; +++ +++ + +-- SQLNESS SORT_RESULT 3 1 +tql eval (0, 0, '1s') calculate_rate_offset_total offset -10m; + +---------------------+------+---+ | ts | val | x | +---------------------+------+---+ @@ -73,18 +79,8 @@ tql eval (0, 0, '1s') calculate_rate_offset_total offset 10m; | 1970-01-01T00:00:00 | 40.0 | b | +---------------------+------+---+ -tql eval (0, 0, '1s') calculate_rate_offset_total offset -10m; - -++ -++ - -tql eval (3000, 3000, '1s') calculate_rate_offset_total offset 10m; - -++ -++ - -- SQLNESS SORT_RESULT 3 1 -tql eval (3000, 3000, '1s') calculate_rate_offset_total offset -10m; +tql eval (3000, 3000, '1s') calculate_rate_offset_total offset 10m; +---------------------+-------+---+ | ts | val | x | @@ -93,6 +89,13 @@ tql eval (3000, 3000, '1s') calculate_rate_offset_total offset -10m; | 1970-01-01T00:50:00 | 80.0 | a | +---------------------+-------+---+ +-- SQLNESS SORT_RESULT 3 1 +tql eval (3000, 3000, '1s') calculate_rate_offset_total offset -10m; + +++ +++ + +-- SQLNESS SORT_RESULT 3 1 tql eval (3000, 3000, '1s') rate(calculate_rate_window_total[10m]); ++ diff --git a/tests/cases/standalone/common/promql/offset.sql b/tests/cases/standalone/common/promql/offset.sql index 37981e7929..53dd2c326f 100644 --- a/tests/cases/standalone/common/promql/offset.sql +++ b/tests/cases/standalone/common/promql/offset.sql @@ -42,13 +42,16 @@ tql eval (1500, 1500, '1s') calculate_rate_offset_total offset -10m; -- SQLNESS SORT_RESULT 3 1 tql eval (0, 0, '1s') calculate_rate_offset_total offset 10m; +-- SQLNESS SORT_RESULT 3 1 tql eval (0, 0, '1s') calculate_rate_offset_total offset -10m; +-- SQLNESS SORT_RESULT 3 1 tql eval (3000, 3000, '1s') calculate_rate_offset_total offset 10m; -- SQLNESS SORT_RESULT 3 1 tql eval (3000, 3000, '1s') calculate_rate_offset_total offset -10m; +-- SQLNESS SORT_RESULT 3 1 tql eval (3000, 3000, '1s') rate(calculate_rate_window_total[10m]); -- SQLNESS SORT_RESULT 3 1 diff --git a/tests/cases/standalone/common/promql/offset_direction.result b/tests/cases/standalone/common/promql/offset_direction.result new file mode 100644 index 0000000000..50098be162 --- /dev/null +++ b/tests/cases/standalone/common/promql/offset_direction.result @@ -0,0 +1,44 @@ +-- Regression for offset direction: positive offsets should query past data. +create table offset_direction ( + ts timestamp time index, + val double, + host string primary key +); + +Affected Rows: 0 + +insert into offset_direction values + (940000, 10.0, 'a'), + (1000000, 20.0, 'a'), + (1060000, 30.0, 'a'); + +Affected Rows: 3 + +tql eval (1000, 1000, '1s') offset_direction; + ++---------------------+------+------+ +| ts | val | host | ++---------------------+------+------+ +| 1970-01-01T00:16:40 | 20.0 | a | ++---------------------+------+------+ + +tql eval (1000, 1000, '1s') offset_direction offset 60s; + ++---------------------+------+------+ +| ts | val | host | ++---------------------+------+------+ +| 1970-01-01T00:16:40 | 10.0 | a | ++---------------------+------+------+ + +tql eval (1000, 1000, '1s') offset_direction offset -60s; + ++---------------------+------+------+ +| ts | val | host | ++---------------------+------+------+ +| 1970-01-01T00:16:40 | 30.0 | a | ++---------------------+------+------+ + +drop table offset_direction; + +Affected Rows: 0 + diff --git a/tests/cases/standalone/common/promql/offset_direction.sql b/tests/cases/standalone/common/promql/offset_direction.sql new file mode 100644 index 0000000000..464062b7d1 --- /dev/null +++ b/tests/cases/standalone/common/promql/offset_direction.sql @@ -0,0 +1,20 @@ +-- Regression for offset direction: positive offsets should query past data. + +create table offset_direction ( + ts timestamp time index, + val double, + host string primary key +); + +insert into offset_direction values + (940000, 10.0, 'a'), + (1000000, 20.0, 'a'), + (1060000, 30.0, 'a'); + +tql eval (1000, 1000, '1s') offset_direction; + +tql eval (1000, 1000, '1s') offset_direction offset 60s; + +tql eval (1000, 1000, '1s') offset_direction offset -60s; + +drop table offset_direction; diff --git a/tests/cases/standalone/common/tql/tql-cte.result b/tests/cases/standalone/common/tql/tql-cte.result index 7127f79d9f..f433dda7c4 100644 --- a/tests/cases/standalone/common/tql/tql-cte.result +++ b/tests/cases/standalone/common/tql/tql-cte.result @@ -676,15 +676,10 @@ WITH time_shifted AS ( ) SELECT * FROM time_shifted; -+---------------------+-----+ -| ts | val | -+---------------------+-----+ -| 1970-01-01T00:00:00 | 3.0 | -| 1970-01-01T00:00:10 | 3.0 | -| 1970-01-01T00:00:20 | 3.0 | -| 1970-01-01T00:00:30 | 3.0 | -| 1970-01-01T00:00:40 | 3.0 | -+---------------------+-----+ ++----+-----+ +| ts | val | ++----+-----+ ++----+-----+ -- SQLNESS REPLACE (peers.*) REDACTED -- SQLNESS REPLACE (partitioning.*) REDACTED @@ -702,7 +697,7 @@ SELECT * FROM time_shifted; | | PromInstantManipulate: range=[0..40000], lookback=[300000], interval=[10000], time index=[ts] | | | PromSeriesNormalize: offset=[50000], time index=[ts], filter NaN: [false] | | | PromSeriesDivide: tags=[] | -| | Filter: metric.ts >= TimestampMillisecond(-250000, None) AND metric.ts <= TimestampMillisecond(390000, None) | +| | Filter: metric.ts >= TimestampMillisecond(-350000, None) AND metric.ts <= TimestampMillisecond(290000, None) | | | TableScan: metric | | | ]] | | physical_plan | CooperativeExec |