Skip to content

Commit f8e25aa

Browse files
Restore top-k detection for OnlySpatial queries and warn on SUM negatives
1 parent 7376ef3 commit f8e25aa

2 files changed

Lines changed: 21 additions & 10 deletions

File tree

asap-query-engine/src/engines/simple_engine/sql.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -606,16 +606,27 @@ impl SimpleEngine {
606606
}
607607
};
608608

609-
// Top-k (CountMinSketchWithHeap) is defined only for flat temporal queries:
610-
// one window, one GROUP BY key, COUNT/SUM ... ORDER BY <agg alias> DESC LIMIT k.
611-
// Nested patterns attach ORDER BY / LIMIT to the outer SELECT; `query_data` from
612-
// parse is the outer layer, while the temporal aggregate lives in `inner_data`
613-
// for OneTemporalOneSpatial. Running detect_sql_topk on the outer layer would
614-
// mis-classify spatial rollups as top-k.
609+
// Top-k (CountMinSketchWithHeap) applies to flat single-layer queries:
610+
// COUNT/SUM ... GROUP BY <key> ORDER BY <agg alias> DESC LIMIT k.
611+
// Nested patterns attach ORDER BY / LIMIT to the outer SELECT; `query_data`
612+
// from parse is the outer layer, while the temporal aggregate lives in
613+
// `inner_data` for OneTemporalOneSpatial. Running detect_sql_topk on the
614+
// outer layer would mis-classify spatial rollups as top-k.
615+
//
616+
// Single-interval windows (duration == scrape interval) classify as
617+
// `OnlySpatial` in the pattern matcher even though they are flat temporal
618+
// reads, so both `OnlyTemporal` and `OnlySpatial` must run detection.
615619
let topk = match query_pattern_type {
616-
QueryPatternType::OnlyTemporal => detect_sql_topk(&query_data),
617-
QueryPatternType::OnlySpatial | QueryPatternType::OneTemporalOneSpatial => None,
620+
QueryPatternType::OnlyTemporal | QueryPatternType::OnlySpatial => {
621+
detect_sql_topk(&query_data)
622+
}
623+
QueryPatternType::OneTemporalOneSpatial => None,
618624
};
625+
if topk.is_some_and(|t| t.weighting == TopkWeighting::Sum) {
626+
warn!(
627+
"SUM top-k assumes non-negative values; results are undefined for columns with negative entries"
628+
);
629+
}
619630
let statistic_to_compute = if topk.is_some() {
620631
Statistic::Topk
621632
} else {
@@ -980,7 +991,7 @@ mod detect_topk_tests {
980991
let qd = parse(&sql).expect("nested query should parse");
981992
assert!(
982993
detect_sql_topk(&qd).is_some(),
983-
"outer SELECT alone matches the top-k shape (this is why OnlyTemporal is gated)",
994+
"outer SELECT alone matches the top-k shape (this is why OneTemporalOneSpatial is gated)",
984995
);
985996
}
986997
}

asap-query-engine/src/tests/sql_pattern_matching_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ mod tests {
193193
assert_ne!(
194194
context.metadata.statistic_to_compute,
195195
Statistic::Topk,
196-
"top-k detection is OnlyTemporal-only; nested outer ORDER BY LIMIT must stay on the plain SUM path",
196+
"top-k detection skips nested OneTemporalOneSpatial; outer ORDER BY LIMIT must stay on the plain SUM path",
197197
);
198198
}
199199

0 commit comments

Comments
 (0)