fix: wrong relation used in promql planner time cast (#7624)

* fix: wrong relation used in promql planner time cast

* refactor: per review

Signed-off-by: discord9 <discord9@163.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Co-authored-by: discord9 <discord9@163.com>
This commit is contained in:
fys
2026-01-28 19:09:06 +08:00
committed by GitHub
parent d99a946d33
commit ecd4efa87d
2 changed files with 21 additions and 9 deletions

View File

@@ -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<u32> = 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,

View File

@@ -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::<PrometheusJsonResponse>(&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()