test(promql): cover the multi-value timestamp refusal

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
This commit is contained in:
discord9
2026-10-26 11:25:44 +08:00
parent 24e214b7d4
commit 9a70220974
@@ -73,6 +73,19 @@ fn raw_schema() -> Arc<SeriesSchema> {
})
}
/// The same layout with `count` fields, for the shapes whose answer depends on how many a scan holds.
fn raw_schema_with_fields(count: usize) -> Arc<SeriesSchema> {
Arc::new(SeriesSchema {
fields: (0..count)
.map(|index| FieldSpec {
name: format!("value_{index}").into(),
})
.collect::<Vec<_>>()
.into(),
eval_grid: None,
})
}
/// A statement over 100 seconds in 5-second steps, which is 21 grid points.
fn eval_stmt(query: &str) -> EvalStmt {
eval_stmt_over(query, Duration::from_secs(100))
@@ -4537,6 +4550,36 @@ fn an_invalid_label_replace_expression_fails_the_statement() {
assert!(matches!(error, DataFusionError::Plan(_)), "{error}");
}
/// `timestamp` reports one value per input field, and the native node reports the time of the sample
/// each field was selected from. A table with several data fields would need that node to say which
/// field's sample it means, so the compiler declines the shape instead of answering with one
/// field's timestamps under every field's name.
#[test]
fn timestamp_multi_field_input_is_not_supported_natively() {
for query in ["timestamp(x)", "timestamp(abs(x))"] {
let error = compile(
&eval_stmt(query),
raw_schema_with_fields(2),
SeriesOrdering::KeyThenTime,
)
.unwrap_err();
assert!(
matches!(&error, DataFusionError::NotImplemented(_)),
"`{query}` is a shape this compiler declines: {error}"
);
assert!(
error
.to_string()
.contains("timestamp() over a multi-value input"),
"`{query}` did not name the field count as the reason: {error}"
);
}
// One field is the shape the node does answer, so the refusal is about the field count.
for query in ["timestamp(x)", "timestamp(abs(x))"] {
compile(&eval_stmt(query), raw_schema(), SeriesOrdering::KeyThenTime)
.unwrap_or_else(|error| panic!("`{query}` over one field was refused: {error}"));
}
}
#[test]
fn selector_requirements_capture_bounds_and_source_occurrence() {
let compiled = compile_selectors(