diff --git a/src/query/src/promql/planner.rs b/src/query/src/promql/planner.rs index bfcae8e80f..3f019c0186 100644 --- a/src/query/src/promql/planner.rs +++ b/src/query/src/promql/planner.rs @@ -1590,7 +1590,8 @@ impl PromPlanner { let logical_table = self.table_from_source(&provider)?; - let mut scan_table_ref = table_ref.clone(); + // Try to rewrite the table scan to physical table scan if possible. + let mut maybe_phy_table_ref = table_ref.clone(); let mut scan_provider = provider; let mut table_id_filter: Option = None; @@ -1639,7 +1640,7 @@ impl PromPlanner { if has_table_id && has_tsid { scan_provider = physical_provider; - scan_table_ref = physical_table_ref; + maybe_phy_table_ref = physical_table_ref; table_id_filter = Some(logical_table.table_info().ident.table_id); } } @@ -1677,7 +1678,7 @@ impl PromPlanner { .schema() .timestamp_column() .with_context(|| TimeIndexNotFoundSnafu { - table: scan_table_ref.to_quoted_string(), + table: maybe_phy_table_ref.to_quoted_string(), })? .data_type == ConcreteDataType::timestamp_millisecond_datatype(); @@ -1687,7 +1688,7 @@ impl PromPlanner { required_columns.insert(DATA_SCHEMA_TABLE_ID_COLUMN_NAME.to_string()); required_columns.insert(self.ctx.time_index_column.clone().with_context(|| { TimeIndexNotFoundSnafu { - table: scan_table_ref.to_quoted_string(), + table: maybe_phy_table_ref.to_quoted_string(), } })?); for col in &scan_tag_columns { @@ -1715,7 +1716,7 @@ impl PromPlanner { }; let mut scan_plan = - LogicalPlanBuilder::scan(scan_table_ref.clone(), scan_provider, scan_projection) + LogicalPlanBuilder::scan(maybe_phy_table_ref.clone(), scan_provider, scan_projection) .context(DataFusionPlanningSnafu)? .build() .context(DataFusionPlanningSnafu)?; @@ -1727,7 +1728,7 @@ impl PromPlanner { .eq(lit(table_id)), ) .context(DataFusionPlanningSnafu)? - .alias(table_ref) // rename the relation back to logical table's name after filtering + .alias(table_ref.clone()) // rename the relation back to logical table's name after filtering .context(DataFusionPlanningSnafu)? .build() .context(DataFusionPlanningSnafu)?; @@ -1747,7 +1748,7 @@ impl PromPlanner { self.ctx .use_tsid .then_some(DfExpr::Column(Column::new( - Some(scan_table_ref.clone()), + Some(table_ref.clone()), DATA_SCHEMA_TSID_COLUMN_NAME.to_string(), ))) .into_iter(), @@ -1757,13 +1758,13 @@ impl PromPlanner { expr: Box::new(self.create_time_index_column_expr()?), data_type: ArrowDataType::Timestamp(ArrowTimeUnit::Millisecond, None), })), - relation: Some(scan_table_ref.clone()), + relation: Some(table_ref.clone()), name: self .ctx .time_index_column .as_ref() .with_context(|| TimeIndexNotFoundSnafu { - table: scan_table_ref.to_quoted_string(), + table: table_ref.to_quoted_string(), })? .clone(), metadata: None, diff --git a/tests-integration/tests/http.rs b/tests-integration/tests/http.rs index 200123f8d6..2fdb459bd2 100644 --- a/tests-integration/tests/http.rs +++ b/tests-integration/tests/http.rs @@ -777,6 +777,17 @@ pub async fn test_prom_http_api(store_type: StorageType) { .send() .await; assert_eq!(res.status(), StatusCode::OK); + // query a metric table backed by a physical table with nanosecond precision to ensure + // time cast and __tsid path work with logical table aliasing. + let res = client + .get( + "/v1/prometheus/api/v1/query_range?query=demo_metrics_with_nanos&start=0&end=10&step=1", + ) + .send() + .await; + assert_eq!(res.status(), StatusCode::OK); + let body = serde_json::from_str::(&res.text().await).unwrap(); + assert_eq!(body.status, "success"); let res = client .get("/v1/prometheus/api/v1/query_range?query=up&start=1&end=100&step=0.5") .send()