diff --git a/src/query/src/promql/planner.rs b/src/query/src/promql/planner.rs index f361d4d51e..c2cd6316ad 100644 --- a/src/query/src/promql/planner.rs +++ b/src/query/src/promql/planner.rs @@ -2465,8 +2465,10 @@ impl PromPlanner { plan: &LogicalPlan, out: &mut BTreeSet, ) -> Result<()> { - if let LogicalPlan::TableScan(scan) = plan { - let table = planner.table_from_source(&scan.source)?; + // Derived PromQL plans may contain non-Greptime scans without row-key metadata. + if let LogicalPlan::TableScan(scan) = plan + && let Ok(table) = planner.table_from_source(&scan.source) + { for col in table.table_info().meta.row_key_column_names() { if col != DATA_SCHEMA_TABLE_ID_COLUMN_NAME && col != DATA_SCHEMA_TSID_COLUMN_NAME @@ -6576,6 +6578,51 @@ mod test { assert!(!aggr_line.contains(DATA_SCHEMA_TSID_COLUMN_NAME)); } + #[tokio::test] + async fn aggregate_over_binary_time_function_expr() { + for op in ["sum", "min", "max", "avg"] { + let prom_expr = parser::parse(&format!( + "{op} by (tag_0, tag_1, tag_2) (time() - some_metric)" + )) + .unwrap(); + let eval_stmt = EvalStmt { + expr: prom_expr, + start: UNIX_EPOCH, + end: UNIX_EPOCH + .checked_add(Duration::from_secs(100_000)) + .unwrap(), + interval: Duration::from_secs(5), + lookback_delta: Duration::from_secs(1), + }; + + let table_provider = build_test_table_provider_with_tsid( + &[(DEFAULT_SCHEMA_NAME.to_string(), "some_metric".to_string())], + 3, + 1, + ) + .await; + let plan = + PromPlanner::stmt_to_plan(table_provider, &eval_stmt, &build_query_engine_state()) + .await + .unwrap(); + + let plan_str = plan.display_indent_schema().to_string(); + let aggr_line = plan_str + .lines() + .find(|line| line.contains("Aggregate: groupBy=")) + .unwrap(); + assert!(aggr_line.contains(op), "{plan_str}"); + assert!(aggr_line.contains("first_value"), "{plan_str}"); + assert!( + !plan + .schema() + .fields() + .iter() + .any(|field| { field.name() == DATA_SCHEMA_TSID_COLUMN_NAME }) + ); + } + } + #[tokio::test] async fn topk_by_does_not_partition_by_tsid() { let prom_expr = parser::parse("topk by (__tsid) (1, some_metric)").unwrap(); diff --git a/tests/cases/standalone/common/promql/tsid_binary_join_regression.result b/tests/cases/standalone/common/promql/tsid_binary_join_regression.result index 8dbbd4131b..d5313ba41c 100644 --- a/tests/cases/standalone/common/promql/tsid_binary_join_regression.result +++ b/tests/cases/standalone/common/promql/tsid_binary_join_regression.result @@ -691,6 +691,19 @@ TQL EVAL (0, 5, '5s') rate(tsid_binary_join_left[5s]) / tsid_binary_join_left; +------+-----+----+----------------------------------------------------------------------------+ +------+-----+----+----------------------------------------------------------------------------+ +-- Regression for aggregating a binary expression over `time()` and a TSID-backed metric. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (0, 5, '5s') sum by (host, job) (time() - tsid_binary_join_left); + ++-------+------+---------------------+-------------------------------------------------------------------+ +| host | job | ts | sum(.time / Float64(1000) - tsid_binary_join_left.greptime_value) | ++-------+------+---------------------+-------------------------------------------------------------------+ +| host1 | job1 | 1970-01-01T00:00:00 | -12.0 | +| host1 | job1 | 1970-01-01T00:00:05 | -10.0 | +| host2 | job2 | 1970-01-01T00:00:00 | -18.0 | +| host2 | job2 | 1970-01-01T00:00:05 | -16.0 | ++-------+------+---------------------+-------------------------------------------------------------------+ + DROP TABLE tsid_binary_join_third; Affected Rows: 0 diff --git a/tests/cases/standalone/common/promql/tsid_binary_join_regression.sql b/tests/cases/standalone/common/promql/tsid_binary_join_regression.sql index 726651f8e4..7a3bc897c7 100644 --- a/tests/cases/standalone/common/promql/tsid_binary_join_regression.sql +++ b/tests/cases/standalone/common/promql/tsid_binary_join_regression.sql @@ -252,6 +252,10 @@ TQL EVAL (0, 5, '5s') (tsid_binary_join_left or tsid_binary_join_right) / tsid_b -- SQLNESS SORT_RESULT 3 1 TQL EVAL (0, 5, '5s') rate(tsid_binary_join_left[5s]) / tsid_binary_join_left; +-- Regression for aggregating a binary expression over `time()` and a TSID-backed metric. +-- SQLNESS SORT_RESULT 3 1 +TQL EVAL (0, 5, '5s') sum by (host, job) (time() - tsid_binary_join_left); + DROP TABLE tsid_binary_join_third; DROP TABLE tsid_binary_join_right_by_job; DROP TABLE tsid_binary_join_right;