mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-05-30 20:00:36 +00:00
fix: qualify HistogramFold schema (#8157)
* test: add regression test for binary op on histogram_quantile (#8144) Signed-off-by: evenyag <realevenyag@gmail.com> * fix: preserve column qualifiers in HistogramFold output schema (#8144) Signed-off-by: evenyag <realevenyag@gmail.com> --------- Signed-off-by: evenyag <realevenyag@gmail.com>
This commit is contained in:
@@ -322,16 +322,18 @@ impl HistogramFold {
|
||||
/// Transform the schema
|
||||
///
|
||||
/// - `le` will be removed
|
||||
///
|
||||
/// Column qualifiers are preserved so downstream plan nodes can keep
|
||||
/// referencing the columns by their original qualified names.
|
||||
fn convert_schema(
|
||||
input_schema: &DFSchemaRef,
|
||||
le_column: &str,
|
||||
) -> DataFusionResult<DFSchemaRef> {
|
||||
let fields = input_schema.fields();
|
||||
// safety: those fields are checked in `check_schema()`
|
||||
let mut new_fields = Vec::with_capacity(fields.len() - 1);
|
||||
for f in fields {
|
||||
if f.name() != le_column {
|
||||
new_fields.push((None, f.clone()));
|
||||
let mut new_fields = Vec::with_capacity(input_schema.fields().len() - 1);
|
||||
for (qualifier, field) in input_schema.iter() {
|
||||
if field.name() != le_column {
|
||||
new_fields.push((qualifier.cloned(), field.clone()));
|
||||
}
|
||||
}
|
||||
Ok(Arc::new(DFSchema::new_with_metadata(
|
||||
|
||||
@@ -4023,12 +4023,15 @@ impl PromPlanner {
|
||||
return Ok(plan);
|
||||
}
|
||||
|
||||
// Preserve column qualifiers so downstream plan nodes can keep referencing
|
||||
// the columns by their original qualified names.
|
||||
let project_exprs = schema
|
||||
.fields()
|
||||
.iter()
|
||||
.filter(|field| field.name() != DATA_SCHEMA_TSID_COLUMN_NAME)
|
||||
.map(|field| Ok(DfExpr::Column(Column::from_name(field.name().clone()))))
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
.filter(|(_, field)| field.name() != DATA_SCHEMA_TSID_COLUMN_NAME)
|
||||
.map(|(qualifier, field)| {
|
||||
DfExpr::Column(Column::new(qualifier.cloned(), field.name().clone()))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
LogicalPlanBuilder::from(plan)
|
||||
.project(project_exprs)
|
||||
@@ -6005,6 +6008,39 @@ mod test {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_histogram_quantile_binary_op() {
|
||||
let mut eval_stmt = EvalStmt {
|
||||
expr: PromExpr::NumberLiteral(NumberLiteral { val: 1.0 }),
|
||||
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),
|
||||
};
|
||||
|
||||
// Arithmetic applied to a histogram_quantile() result. Regression for #8144:
|
||||
// HistogramFold used to drop the input column qualifiers, so the binary-op
|
||||
// projection failed to resolve the qualified tag column.
|
||||
let case = r#"histogram_quantile(0.5, sum by (le, pod) (rate(http_request_duration_seconds_bucket[5m]))) + 0"#;
|
||||
|
||||
let prom_expr = parser::parse(case).unwrap();
|
||||
eval_stmt.expr = prom_expr;
|
||||
let table_provider = build_test_table_provider_with_fields(
|
||||
&[(
|
||||
DEFAULT_SCHEMA_NAME.to_string(),
|
||||
"http_request_duration_seconds_bucket".to_string(),
|
||||
)],
|
||||
&["pod", "le"],
|
||||
)
|
||||
.await;
|
||||
// Should plan without a "No field named ..." error.
|
||||
let _ = PromPlanner::stmt_to_plan(table_provider, &eval_stmt, &build_query_engine_state())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_and_operator() {
|
||||
let mut eval_stmt = EvalStmt {
|
||||
|
||||
Reference in New Issue
Block a user