From 509edeb90e4c6e131621103acf4581f304546ba9 Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Sun, 11 Oct 2026 11:18:41 -0400 Subject: [PATCH 1/2] test(query-engine): add SQL compliance runner Plans each SQL suite query in isolation and builds the engine's execution context against that plan, without ingesting data. Each case declares whether it is expected to be supported, so a change in SQL coverage fails the run until the suite is updated. Suites mirror the promql-compliance suites case-for-case, plus a basic suite covering single-layer shapes, time-range forms, and top-k. Co-Authored-By: Claude Opus 5.5 --- asap-query-engine/tests/sql_compliance.rs | 144 ++++++++ .../tests/sql_compliance/aggregations.yaml | 194 +++++++++++ .../tests/sql_compliance/basic.yaml | 114 +++++++ .../native-dag-aggregations.yaml | 23 ++ .../sql_compliance/nested-aggregations.yaml | 307 ++++++++++++++++++ .../tests/sql_compliance/olly-bench.yaml | 57 ++++ .../tests/sql_compliance/quantiles.yaml | 123 +++++++ .../tests/sql_compliance/temporal.yaml | 19 ++ .../tests/sql_compliance/topk-ordering.yaml | 21 ++ 9 files changed, 1002 insertions(+) create mode 100644 asap-query-engine/tests/sql_compliance.rs create mode 100644 asap-query-engine/tests/sql_compliance/aggregations.yaml create mode 100644 asap-query-engine/tests/sql_compliance/basic.yaml create mode 100644 asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml create mode 100644 asap-query-engine/tests/sql_compliance/nested-aggregations.yaml create mode 100644 asap-query-engine/tests/sql_compliance/olly-bench.yaml create mode 100644 asap-query-engine/tests/sql_compliance/quantiles.yaml create mode 100644 asap-query-engine/tests/sql_compliance/temporal.yaml create mode 100644 asap-query-engine/tests/sql_compliance/topk-ordering.yaml diff --git a/asap-query-engine/tests/sql_compliance.rs b/asap-query-engine/tests/sql_compliance.rs new file mode 100644 index 00000000..3ea4fee3 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance.rs @@ -0,0 +1,144 @@ +//! SQL compliance runner: plans each suite query in isolation and builds the +//! engine's execution context for it, without ingesting data or executing. +//! +//! A query is `supported` when both the planner accepts it and the engine +//! resolves an execution context against that plan. Each suite case declares +//! the expected outcome, so a query that starts or stops being supported +//! fails the run until its suite entry is updated. + +use asap_planner::{SQLController, SQLRuntimeOptions, StreamingEngine}; +use asap_types::enums::{CleanupPolicy, QueryLanguage}; +use query_engine_rust::{SimpleEngine, SimpleMapStore}; +use serde::Deserialize; +use serde_json::json; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +const SUITES_DIR: &str = "tests/sql_compliance"; +const SUITE_EXTENSION: &str = "yaml"; +/// Fixed evaluation time (seconds) so NOW()-relative queries plan and match +/// deterministically. +const QUERY_EVALUATION_TIME_SECS: f64 = 1_000_000.0; +const ACCURACY_SLA: f64 = 0.95; + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Suite { + /// Planner table definitions, passed through verbatim. + tables: serde_json::Value, + data_ingestion_interval_ms: u64, + repetition_delay_ms: u64, + cases: Vec, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Case { + name: String, + query: String, + expected: Outcome, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] +#[serde(rename_all = "snake_case")] +enum Outcome { + Supported, + Unsupported, +} + +/// Where a query stopped, with the reason. `None` means it is supported. +type Failure = Option; + +fn run_case(suite: &Suite, query: &str) -> Failure { + let planner_config = json!({ + "tables": suite.tables, + "query_groups": [{ + "queries": [query], + "repetition_delay_ms": suite.repetition_delay_ms, + "controller_options": { "accuracy_sla": ACCURACY_SLA }, + }], + }); + let planner_yaml = serde_yaml::to_string(&planner_config).expect("planner config serializes"); + let opts = SQLRuntimeOptions { + streaming_engine: StreamingEngine::Precompute, + query_evaluation_time: Some(QUERY_EVALUATION_TIME_SECS), + data_ingestion_interval_ms: suite.data_ingestion_interval_ms, + }; + let output = match SQLController::from_yaml(&planner_yaml, opts).and_then(|c| c.generate()) { + Ok(output) => output, + Err(error) => return Some(format!("plan: {error}")), + }; + + let inference_config = output + .to_inference_config(QueryLanguage::sql) + .expect("planner output converts to inference config"); + let streaming_config = Arc::new( + output + .to_streaming_config(QueryLanguage::sql) + .expect("planner output converts to streaming config"), + ); + let store = Arc::new(SimpleMapStore::new( + streaming_config.clone(), + CleanupPolicy::NoCleanup, + )); + let engine = SimpleEngine::new( + store, + inference_config, + streaming_config, + suite.data_ingestion_interval_ms, + QueryLanguage::sql, + ); + match engine.build_query_execution_context_sql(query.to_string(), QUERY_EVALUATION_TIME_SECS) { + Some(_) => None, + None => Some("engine: no execution context for planned query".to_string()), + } +} + +fn suite_paths() -> Vec { + let dir = Path::new(env!("CARGO_MANIFEST_DIR")).join(SUITES_DIR); + let mut paths: Vec = std::fs::read_dir(&dir) + .unwrap_or_else(|e| panic!("read {}: {e}", dir.display())) + .map(|entry| entry.expect("suite dir entry").path()) + .filter(|path| path.extension().is_some_and(|ext| ext == SUITE_EXTENSION)) + .collect(); + paths.sort(); + assert!(!paths.is_empty(), "no suites in {}", dir.display()); + paths +} + +#[test] +fn sql_queries_match_expected_support() { + let mut mismatches = Vec::new(); + for path in suite_paths() { + let suite_name = path.file_stem().unwrap().to_string_lossy().into_owned(); + let contents = std::fs::read_to_string(&path).expect("read suite"); + let suite: Suite = serde_yaml::from_str(&contents) + .unwrap_or_else(|e| panic!("parse {}: {e}", path.display())); + + for case in &suite.cases { + let failure = run_case(&suite, &case.query); + let actual = match failure { + None => Outcome::Supported, + Some(_) => Outcome::Unsupported, + }; + let status = if actual == case.expected { + "ok" + } else { + "MISMATCH" + }; + let reason = failure.as_deref().unwrap_or(""); + println!("[{status}] {suite_name}/{}: {actual:?} {reason}", case.name); + if actual != case.expected { + mismatches.push(format!( + "{suite_name}/{}: expected {:?}, got {actual:?} {reason}", + case.name, case.expected + )); + } + } + } + assert!( + mismatches.is_empty(), + "SQL compliance mismatches:\n{}", + mismatches.join("\n") + ); +} diff --git a/asap-query-engine/tests/sql_compliance/aggregations.yaml b/asap-query-engine/tests/sql_compliance/aggregations.yaml new file mode 100644 index 00000000..83c5553a --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/aggregations.yaml @@ -0,0 +1,194 @@ +# SQL equivalents of promql-compliance/suites/aggregations.yaml; case names match. +# +# Translation: `[5m]` range functions aggregate over a 300s window; instant +# vectors aggregate over one ingestion interval (1s). A per-series result +# groups by every label (job, instance). Per-group top-k uses `LIMIT k BY`. +# +# Skipped, no SQL equivalent for counter rate/increase: increase, rate, +# topk-3-rate, topk-3-rate-by-job, topk-3-rate-by-job-instance, +# sum-by-job-rate, sum-by-job-instance-rate. +tables: + - name: data + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: sum-over-time + query: SELECT job, instance, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: count-over-time + query: SELECT job, instance, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: avg-over-time + query: SELECT job, instance, AVG(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: unsupported + - name: min-over-time + query: SELECT job, instance, MIN(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: max-over-time + query: SELECT job, instance, MAX(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + + - name: topk-1-bare + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 1 + expected: supported + - name: topk-3-bare + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 + expected: supported + - name: topk-5-bare + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 5 + expected: supported + - name: topk-10-bare + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 10 + expected: supported + - name: topk-3-bare-by-job + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job + expected: unsupported + - name: topk-3-bare-by-job-instance + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job, instance + expected: unsupported + + - name: topk-1-sum-over-time + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 1 + expected: supported + - name: topk-3-sum-over-time + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 + expected: supported + - name: topk-5-sum-over-time + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 5 + expected: supported + - name: topk-10-sum-over-time + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 10 + expected: supported + - name: topk-1-sum-over-time-by-job + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 1 BY job + expected: unsupported + - name: topk-3-sum-over-time-by-job + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job + expected: unsupported + - name: topk-5-sum-over-time-by-job + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 5 BY job + expected: unsupported + - name: topk-10-sum-over-time-by-job + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 10 BY job + expected: unsupported + - name: topk-1-sum-over-time-by-job-instance + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 1 BY job, instance + expected: unsupported + - name: topk-3-sum-over-time-by-job-instance + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job, instance + expected: unsupported + - name: topk-5-sum-over-time-by-job-instance + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 5 BY job, instance + expected: unsupported + - name: topk-10-sum-over-time-by-job-instance + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 10 BY job, instance + expected: unsupported + + - name: topk-1-count-over-time + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 1 + expected: supported + - name: topk-3-count-over-time + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 3 + expected: supported + - name: topk-5-count-over-time + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 5 + expected: supported + - name: topk-10-count-over-time + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 10 + expected: supported + - name: topk-1-count-over-time-by-job + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 1 BY job + expected: unsupported + - name: topk-3-count-over-time-by-job + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 3 BY job + expected: unsupported + - name: topk-5-count-over-time-by-job + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 5 BY job + expected: unsupported + - name: topk-10-count-over-time-by-job + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 10 BY job + expected: unsupported + - name: topk-1-count-over-time-by-job-instance + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 1 BY job, instance + expected: unsupported + - name: topk-3-count-over-time-by-job-instance + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 3 BY job, instance + expected: unsupported + - name: topk-5-count-over-time-by-job-instance + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 5 BY job, instance + expected: unsupported + - name: topk-10-count-over-time-by-job-instance + query: SELECT job, instance, COUNT(value) AS c FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY c DESC LIMIT 10 BY job, instance + expected: unsupported + + - name: sum + query: SELECT SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: sum-by-job + query: SELECT job, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: sum-by-job-instance + query: SELECT job, instance, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: count + query: SELECT COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: count-by-job + query: SELECT job, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: count-by-job-instance + query: SELECT job, instance, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + + - name: sum-by-job-sum-over-time + query: SELECT job, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job + expected: supported + - name: sum-by-job-instance-sum-over-time + query: SELECT job, instance, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: sum-sum-over-time + query: SELECT SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() + expected: unsupported + - name: sum-without-job-sum-over-time + query: SELECT instance, SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY instance + expected: supported + - name: sum-count-over-time + query: SELECT COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() + expected: unsupported + - name: sum-by-job-count-over-time + query: SELECT job, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job + expected: supported + - name: sum-by-job-instance-count-over-time + query: SELECT job, instance, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: sum-without-job-count-over-time + query: SELECT instance, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY instance + expected: supported + - name: min-min-over-time + query: SELECT MIN(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() + expected: unsupported + - name: min-by-job-min-over-time + query: SELECT job, MIN(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job + expected: supported + - name: min-by-job-instance-min-over-time + query: SELECT job, instance, MIN(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: min-without-job-min-over-time + query: SELECT instance, MIN(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY instance + expected: supported + - name: max-max-over-time + query: SELECT MAX(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() + expected: unsupported + - name: max-by-job-max-over-time + query: SELECT job, MAX(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job + expected: supported + - name: max-by-job-instance-max-over-time + query: SELECT job, instance, MAX(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: max-without-job-max-over-time + query: SELECT instance, MAX(value) FROM data WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY instance + expected: supported diff --git a/asap-query-engine/tests/sql_compliance/basic.yaml b/asap-query-engine/tests/sql_compliance/basic.yaml new file mode 100644 index 00000000..8390a696 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/basic.yaml @@ -0,0 +1,114 @@ +tables: + - name: cpu_usage + time_column: time + value_columns: [value] + metadata_columns: [L1, L2, L3] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 10000 + +cases: + # Single-layer aggregations + - name: sum_by_label + query: SELECT L1, SUM(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + - name: count_by_label + query: SELECT L1, COUNT(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + # The planner plans AVG as Sum + Count, but the engine only resolves + # single-statistic SQL queries. + - name: avg_by_label + query: SELECT L1, AVG(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: unsupported + - name: min_by_label + query: SELECT L1, MIN(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + - name: max_by_label + query: SELECT L1, MAX(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + - name: quantile_by_label + query: SELECT L1, QUANTILE(0.95, value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + - name: sum_by_all_labels + query: SELECT L1, L2, L3, SUM(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2, L3 + expected: supported + - name: count_distinct_by_label + query: SELECT L1, COUNT(DISTINCT L2) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: supported + + # No GROUP BY: the pattern parser rejects an empty GROUP BY. + - name: sum_no_group_by + query: SELECT SUM(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + - name: count_no_group_by + query: SELECT COUNT(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + - name: min_no_group_by + query: SELECT MIN(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + - name: max_no_group_by + query: SELECT MAX(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + - name: quantile_no_group_by + query: SELECT QUANTILE(0.95, value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + - name: count_distinct_no_group_by + query: SELECT COUNT(DISTINCT L2) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() + expected: unsupported + + # Time-range forms, with GROUP BY + - name: absolute_between_group_by + query: SELECT L1, SUM(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, '2025-10-01 00:00:10') AND '2025-10-01 00:00:10' GROUP BY L1 + expected: supported + - name: half_open_bounds_group_by + query: SELECT L1, SUM(value) FROM cpu_usage WHERE time >= DATEADD(s, -10, NOW()) AND time < NOW() GROUP BY L1 + expected: supported + - name: mirrored_half_open_bounds_group_by + query: SELECT L1, SUM(value) FROM cpu_usage WHERE DATEADD(s, -10, NOW()) <= time AND NOW() > time GROUP BY L1 + expected: supported + - name: absolute_half_open_bounds_group_by + query: SELECT L1, SUM(value) FROM cpu_usage WHERE time >= DATEADD(s, -10, '2025-10-01 00:00:10') AND time < '2025-10-01 00:00:10' GROUP BY L1 + expected: supported + # Only half-open `>= ... <` ranges are accepted, matching ClickHouse's + # [start, end) scan; a closed `<=` upper bound would be off by one. + - name: closed_comparison_bounds_group_by + query: SELECT L1, SUM(value) FROM cpu_usage WHERE time >= DATEADD(s, -10, NOW()) AND time <= NOW() GROUP BY L1 + expected: unsupported + - name: no_time_filter_group_by + query: SELECT L1, SUM(value) FROM cpu_usage GROUP BY L1 + expected: unsupported + + # Top-k + - name: topk_sum_by_label + query: SELECT L1, SUM(value) AS total FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 ORDER BY total DESC LIMIT 5 + expected: supported + - name: topk_sum_by_two_labels + query: SELECT L1, L2, SUM(value) AS total FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2 ORDER BY total DESC LIMIT 5 + expected: supported + - name: topk_count_by_label + query: SELECT L1, COUNT(value) AS c FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 ORDER BY c DESC LIMIT 5 + expected: supported + - name: topk_count_star_by_label + query: SELECT L1, COUNT(*) AS c FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 ORDER BY c DESC LIMIT 5 + expected: unsupported + - name: topk_count_by_two_labels + query: SELECT L1, L2, COUNT(value) AS c FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2 ORDER BY c DESC LIMIT 5 + expected: supported + + # Binary operators + - name: binary_aggregate_divide_aggregate + query: SELECT L1, SUM(value) / COUNT(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: unsupported + - name: binary_aggregate_times_scalar + query: SELECT L1, SUM(value) * 2 FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: unsupported + - name: two_aggregates + query: SELECT L1, SUM(value), COUNT(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1 + expected: unsupported + + # Nested aggregations + - name: nested_avg_of_quantile + query: SELECT L1, AVG(result) FROM (SELECT L1, L2, QUANTILE(0.95, value) AS result FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2) GROUP BY L1 + expected: unsupported + - name: nested_sum_of_sum + query: SELECT L1, SUM(total) FROM (SELECT L1, L2, SUM(value) AS total FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2) GROUP BY L1 + expected: unsupported diff --git a/asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml b/asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml new file mode 100644 index 00000000..301bda6d --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml @@ -0,0 +1,23 @@ +# SQL equivalents of promql-compliance/suites/native-dag-aggregations.yaml; +# case names match. Instant vectors aggregate over one ingestion interval (1s). +tables: + - name: data + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: tumbling-sum + query: SELECT SUM(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: keyed-count + query: SELECT job, COUNT(value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: grouped-quantile-labels + query: SELECT job, QUANTILE(0.99, value) FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: self-keyed-topk + query: SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 2 + expected: supported diff --git a/asap-query-engine/tests/sql_compliance/nested-aggregations.yaml b/asap-query-engine/tests/sql_compliance/nested-aggregations.yaml new file mode 100644 index 00000000..fdab2dbf --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/nested-aggregations.yaml @@ -0,0 +1,307 @@ +# SQL equivalents of promql-compliance/suites/nested-aggregations.yaml; case +# names match. Each PromQL aggregation stage is one SELECT layer: +# anchor sum by (job, instance) (data) +# -> SELECT job, instance, SUM(value) AS v FROM data WHERE <1s> GROUP BY job, instance +# stage agg by (job) (x) -> SELECT job, AGG(v) AS m FROM (x) GROUP BY job +# stage topk by (job) (3, x) -> SELECT job, ..., v FROM (x) ORDER BY v DESC LIMIT 3 BY job +# The instant-vector anchor aggregates over one ingestion interval (1s). +tables: + - name: data + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: one-stage-sum + query: SELECT job, SUM(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-count + query: SELECT job, COUNT(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-avg + query: SELECT job, AVG(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-min + query: SELECT job, MIN(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-max + query: SELECT job, MAX(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-topk-3 + query: SELECT job, instance, v FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) ORDER BY v DESC LIMIT 3 BY job + expected: unsupported + - name: bare-topk-by-job-then-sum + query: SELECT job, SUM(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: one-stage-quantile-0-5 + query: SELECT job, QUANTILE(0.5, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-quantile-0-75 + query: SELECT job, QUANTILE(0.75, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + - name: one-stage-quantile-0-9 + query: SELECT job, QUANTILE(0.9, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job + expected: unsupported + + # Middle stage: sum by (job) + - name: two-stage-sum-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-min + query: SELECT job, MIN(m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-max + query: SELECT job, MAX(m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-topk-3 + query: SELECT job, m FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-sum-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-sum-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, SUM(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: count by (job) + - name: two-stage-count-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-min + query: SELECT job, MIN(m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-max + query: SELECT job, MAX(m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-topk-3 + query: SELECT job, m FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-count-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-count-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, COUNT(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: avg by (job) + - name: two-stage-avg-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-min + query: SELECT job, MIN(m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-max + query: SELECT job, MAX(m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-topk-3 + query: SELECT job, m FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-avg-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-avg-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, AVG(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: min by (job) + - name: two-stage-min-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-min + query: SELECT job, MIN(m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-max + query: SELECT job, MAX(m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-topk-3 + query: SELECT job, m FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-min-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-min-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, MIN(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: max by (job) + - name: two-stage-max-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-min + query: SELECT job, MIN(m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-max + query: SELECT job, MAX(m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-topk-3 + query: SELECT job, m FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-max-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-max-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, MAX(v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: topk by (job) (3, ...), which keeps per-instance rows + - name: two-stage-topk-3-then-sum + query: SELECT job, SUM(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-count + query: SELECT job, COUNT(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-avg + query: SELECT job, AVG(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-min + query: SELECT job, MIN(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-max + query: SELECT job, MAX(v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-topk-3 + query: SELECT job, instance, v FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) ORDER BY v DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-topk-3-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + - name: two-stage-topk-3-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, v) FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job) GROUP BY job + expected: unsupported + + # Middle stage: quantile by (job) (0.5, ...) + - name: two-stage-quantile-0-5-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-min + query: SELECT job, MIN(m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-max + query: SELECT job, MAX(m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-topk-3 + query: SELECT job, m FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-5-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, QUANTILE(0.5, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: quantile by (job) (0.75, ...) + - name: two-stage-quantile-0-75-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-min + query: SELECT job, MIN(m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-max + query: SELECT job, MAX(m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-topk-3 + query: SELECT job, m FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-75-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, QUANTILE(0.75, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + + # Middle stage: quantile by (job) (0.9, ...) + - name: two-stage-quantile-0-9-then-sum + query: SELECT job, SUM(m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-count + query: SELECT job, COUNT(m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-avg + query: SELECT job, AVG(m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-min + query: SELECT job, MIN(m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-max + query: SELECT job, MAX(m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-topk-3 + query: SELECT job, m FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) ORDER BY m DESC LIMIT 3 BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-quantile-0-5 + query: SELECT job, QUANTILE(0.5, m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-quantile-0-75 + query: SELECT job, QUANTILE(0.75, m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported + - name: two-stage-quantile-0-9-then-quantile-0-9 + query: SELECT job, QUANTILE(0.9, m) FROM (SELECT job, QUANTILE(0.9, v) AS m FROM (SELECT job, instance, SUM(value) AS v FROM data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance) GROUP BY job) GROUP BY job + expected: unsupported diff --git a/asap-query-engine/tests/sql_compliance/olly-bench.yaml b/asap-query-engine/tests/sql_compliance/olly-bench.yaml new file mode 100644 index 00000000..566bb518 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/olly-bench.yaml @@ -0,0 +1,57 @@ +# SQL equivalents of promql-compliance/suites/olly-bench.yaml; case names match. +# `[5m]` range functions aggregate over a 300s window; instant vectors over +# one ingestion interval (1s). +# +# Skipped, no SQL equivalent: +# - counter rate/increase: olly-01, olly-02, olly-03, olly-04, olly-08, +# olly-11, olly-13, olly-14, olly-15, olly-16, olly-18, olly-19, olly-20, +# olly-24, olly-25, olly-26 +# - PromQL subquery `[10m:]`: olly-10, olly-27 +# - bare selector (raw samples): olly-07 +# +# histogram_quantile over bucket counters maps to QUANTILE over a table of raw +# observations, grouped by the `sum by` labels minus `le`. rate() drops out +# because scaling every bucket by the same factor leaves the quantile unchanged. +tables: + - name: backend_process_resident_memory_bytes + time_column: time + value_columns: [value] + metadata_columns: [job, instance] + - name: backend_retry_backlog_depth + time_column: time + value_columns: [value] + metadata_columns: [job, instance] + - name: cache_refresh_lag_seconds + time_column: time + value_columns: [value] + metadata_columns: [job, instance] + - name: user_service_cache_refresh_lag_seconds + time_column: time + value_columns: [value] + metadata_columns: [job, instance] + - name: order_service_http_request_duration_seconds + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: olly-09-sum-memory + query: SELECT SUM(value) FROM backend_process_resident_memory_bytes WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: olly-05-max-over-time-cache-lag + query: SELECT job, instance, MAX(value) FROM cache_refresh_lag_seconds WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: olly-06-max-over-time-user-cache-lag + query: SELECT job, instance, MAX(value) FROM user_service_cache_refresh_lag_seconds WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: olly-12-topk-sum-memory-by-job + query: SELECT job, SUM(value) AS v FROM backend_process_resident_memory_bytes WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job ORDER BY v DESC LIMIT 2 + expected: supported + - name: olly-21-histogram-quantile-0.95 + query: SELECT QUANTILE(0.95, value) FROM order_service_http_request_duration_seconds WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() + expected: unsupported + - name: olly-23-topk-max-over-time-backlog + query: SELECT job, instance, MAX(value) AS v FROM backend_retry_backlog_depth WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 2 + expected: supported diff --git a/asap-query-engine/tests/sql_compliance/quantiles.yaml b/asap-query-engine/tests/sql_compliance/quantiles.yaml new file mode 100644 index 00000000..98f56112 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/quantiles.yaml @@ -0,0 +1,123 @@ +# SQL equivalents of promql-compliance/suites/quantiles.yaml; case names match. +# `[5m]` range functions aggregate over a 300s window; instant vectors over +# one ingestion interval (1s). A per-series result groups by (job, instance). +tables: + - name: quantile_dense + time_column: time + value_columns: [value] + metadata_columns: [job, instance] + - name: quantile_wide + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: quantile-over-time-0.1 + query: SELECT job, instance, QUANTILE(0.1, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.2 + query: SELECT job, instance, QUANTILE(0.2, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.3 + query: SELECT job, instance, QUANTILE(0.3, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.4 + query: SELECT job, instance, QUANTILE(0.4, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.5 + query: SELECT job, instance, QUANTILE(0.5, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.6 + query: SELECT job, instance, QUANTILE(0.6, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.7 + query: SELECT job, instance, QUANTILE(0.7, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.75 + query: SELECT job, instance, QUANTILE(0.75, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.8 + query: SELECT job, instance, QUANTILE(0.8, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.9 + query: SELECT job, instance, QUANTILE(0.9, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.95 + query: SELECT job, instance, QUANTILE(0.95, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-0.99 + query: SELECT job, instance, QUANTILE(0.99, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-over-time-ratio-0.9-0.5 + query: SELECT job, instance, QUANTILE(0.9, value) / QUANTILE(0.5, value) FROM quantile_dense WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY job, instance + expected: unsupported + + - name: quantile-0.1 + query: SELECT QUANTILE(0.1, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.2 + query: SELECT QUANTILE(0.2, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.3 + query: SELECT QUANTILE(0.3, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.4 + query: SELECT QUANTILE(0.4, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.5 + query: SELECT QUANTILE(0.5, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.6 + query: SELECT QUANTILE(0.6, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.7 + query: SELECT QUANTILE(0.7, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.75 + query: SELECT QUANTILE(0.75, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.8 + query: SELECT QUANTILE(0.8, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.9 + query: SELECT QUANTILE(0.9, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.95 + query: SELECT QUANTILE(0.95, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + - name: quantile-0.99 + query: SELECT QUANTILE(0.99, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() + expected: unsupported + + - name: quantile-0.5-by-job + query: SELECT job, QUANTILE(0.5, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: quantile-0.75-by-job + query: SELECT job, QUANTILE(0.75, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: quantile-0.9-by-job + query: SELECT job, QUANTILE(0.9, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: quantile-0.95-by-job + query: SELECT job, QUANTILE(0.95, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: quantile-0.99-by-job + query: SELECT job, QUANTILE(0.99, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job + expected: supported + - name: quantile-0.5-by-job-instance + query: SELECT job, instance, QUANTILE(0.5, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-0.75-by-job-instance + query: SELECT job, instance, QUANTILE(0.75, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-0.9-by-job-instance + query: SELECT job, instance, QUANTILE(0.9, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-0.95-by-job-instance + query: SELECT job, instance, QUANTILE(0.95, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported + - name: quantile-0.99-by-job-instance + query: SELECT job, instance, QUANTILE(0.99, value) FROM quantile_wide WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance + expected: supported diff --git a/asap-query-engine/tests/sql_compliance/temporal.yaml b/asap-query-engine/tests/sql_compliance/temporal.yaml new file mode 100644 index 00000000..ef3bb3f3 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/temporal.yaml @@ -0,0 +1,19 @@ +# SQL equivalents of promql-compliance/suites/temporal.yaml; case names match. +# The off-grid-rate suite has no SQL counterpart: its only case is a rate(). +# +# Skipped, no SQL equivalent for counter rate: request-rate. +tables: + - name: http_requests_total + time_column: time + value_columns: [value] + metadata_columns: [host] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: sum-over-time + query: SELECT host, SUM(value) FROM http_requests_total WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY host + expected: supported + - name: sum-over-time-plus-one + query: SELECT host, SUM(value) + 1 FROM http_requests_total WHERE time BETWEEN DATEADD(s, -300, NOW()) AND NOW() GROUP BY host + expected: unsupported diff --git a/asap-query-engine/tests/sql_compliance/topk-ordering.yaml b/asap-query-engine/tests/sql_compliance/topk-ordering.yaml new file mode 100644 index 00000000..d1b10912 --- /dev/null +++ b/asap-query-engine/tests/sql_compliance/topk-ordering.yaml @@ -0,0 +1,21 @@ +# SQL equivalents of promql-compliance/suites/topk-ordering.yaml; case names +# match. Instant vectors aggregate over one ingestion interval (1s); per-group +# top-k uses `LIMIT k BY`. +tables: + - name: ordered_data + time_column: time + value_columns: [value] + metadata_columns: [job, instance] +data_ingestion_interval_ms: 1000 +repetition_delay_ms: 60000 + +cases: + - name: topk-tied + query: SELECT job, instance, SUM(value) AS v FROM ordered_data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 6 + expected: supported + - name: topk-tied-by-job + query: SELECT job, instance, SUM(value) AS v FROM ordered_data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job + expected: unsupported + - name: topk-tied-without-instance + query: SELECT job, instance, SUM(value) AS v FROM ordered_data WHERE time BETWEEN DATEADD(s, -1, NOW()) AND NOW() GROUP BY job, instance ORDER BY v DESC LIMIT 3 BY job + expected: unsupported From 91fd8326b9ce6d91434095e84c063089bd635d7e Mon Sep 17 00:00:00 2001 From: Milind Srivastava Date: Sun, 11 Oct 2026 13:21:58 -0400 Subject: [PATCH 2/2] test(query-engine): rename SQL compliance runner to sql_query_support The runner checks plan-path acceptance, not result compliance. Co-Authored-By: Claude Opus 5.5 --- .../tests/{sql_compliance.rs => sql_query_support.rs} | 6 +++--- .../{sql_compliance => sql_query_support}/aggregations.yaml | 0 .../tests/{sql_compliance => sql_query_support}/basic.yaml | 0 .../native-dag-aggregations.yaml | 0 .../nested-aggregations.yaml | 0 .../{sql_compliance => sql_query_support}/olly-bench.yaml | 0 .../{sql_compliance => sql_query_support}/quantiles.yaml | 0 .../{sql_compliance => sql_query_support}/temporal.yaml | 0 .../topk-ordering.yaml | 0 9 files changed, 3 insertions(+), 3 deletions(-) rename asap-query-engine/tests/{sql_compliance.rs => sql_query_support.rs} (96%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/aggregations.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/basic.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/native-dag-aggregations.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/nested-aggregations.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/olly-bench.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/quantiles.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/temporal.yaml (100%) rename asap-query-engine/tests/{sql_compliance => sql_query_support}/topk-ordering.yaml (100%) diff --git a/asap-query-engine/tests/sql_compliance.rs b/asap-query-engine/tests/sql_query_support.rs similarity index 96% rename from asap-query-engine/tests/sql_compliance.rs rename to asap-query-engine/tests/sql_query_support.rs index 3ea4fee3..84fbac5a 100644 --- a/asap-query-engine/tests/sql_compliance.rs +++ b/asap-query-engine/tests/sql_query_support.rs @@ -1,4 +1,4 @@ -//! SQL compliance runner: plans each suite query in isolation and builds the +//! SQL query support runner: plans each suite query in isolation and builds the //! engine's execution context for it, without ingesting data or executing. //! //! A query is `supported` when both the planner accepts it and the engine @@ -14,7 +14,7 @@ use serde_json::json; use std::path::{Path, PathBuf}; use std::sync::Arc; -const SUITES_DIR: &str = "tests/sql_compliance"; +const SUITES_DIR: &str = "tests/sql_query_support"; const SUITE_EXTENSION: &str = "yaml"; /// Fixed evaluation time (seconds) so NOW()-relative queries plan and match /// deterministically. @@ -138,7 +138,7 @@ fn sql_queries_match_expected_support() { } assert!( mismatches.is_empty(), - "SQL compliance mismatches:\n{}", + "SQL query support mismatches:\n{}", mismatches.join("\n") ); } diff --git a/asap-query-engine/tests/sql_compliance/aggregations.yaml b/asap-query-engine/tests/sql_query_support/aggregations.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/aggregations.yaml rename to asap-query-engine/tests/sql_query_support/aggregations.yaml diff --git a/asap-query-engine/tests/sql_compliance/basic.yaml b/asap-query-engine/tests/sql_query_support/basic.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/basic.yaml rename to asap-query-engine/tests/sql_query_support/basic.yaml diff --git a/asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml b/asap-query-engine/tests/sql_query_support/native-dag-aggregations.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/native-dag-aggregations.yaml rename to asap-query-engine/tests/sql_query_support/native-dag-aggregations.yaml diff --git a/asap-query-engine/tests/sql_compliance/nested-aggregations.yaml b/asap-query-engine/tests/sql_query_support/nested-aggregations.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/nested-aggregations.yaml rename to asap-query-engine/tests/sql_query_support/nested-aggregations.yaml diff --git a/asap-query-engine/tests/sql_compliance/olly-bench.yaml b/asap-query-engine/tests/sql_query_support/olly-bench.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/olly-bench.yaml rename to asap-query-engine/tests/sql_query_support/olly-bench.yaml diff --git a/asap-query-engine/tests/sql_compliance/quantiles.yaml b/asap-query-engine/tests/sql_query_support/quantiles.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/quantiles.yaml rename to asap-query-engine/tests/sql_query_support/quantiles.yaml diff --git a/asap-query-engine/tests/sql_compliance/temporal.yaml b/asap-query-engine/tests/sql_query_support/temporal.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/temporal.yaml rename to asap-query-engine/tests/sql_query_support/temporal.yaml diff --git a/asap-query-engine/tests/sql_compliance/topk-ordering.yaml b/asap-query-engine/tests/sql_query_support/topk-ordering.yaml similarity index 100% rename from asap-query-engine/tests/sql_compliance/topk-ordering.yaml rename to asap-query-engine/tests/sql_query_support/topk-ordering.yaml