Skip to content

Commit 4fd3b89

Browse files
Merge remote-tracking branch 'origin/main' into 313-convert-cmd-line-inputs-to-asap-query-engine-to-a-config-file-instead
2 parents b886f9d + d7e0dde commit 4fd3b89

5 files changed

Lines changed: 122 additions & 13 deletions

File tree

‎asap-common/dependencies/rs/sql_utilities/src/ast_matching/sqlparser_test.rs‎

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,4 +639,108 @@ mod tests {
639639
).unwrap();
640640
assert!(incoming.matches_sql_pattern(&template));
641641
}
642+
643+
#[test]
644+
fn test_order_by_is_rejected() {
645+
assert!(parse_sql_query(
646+
"SELECT AVG(value) FROM cpu_usage WHERE time BETWEEN DATEADD(s, -10, NOW()) AND NOW() GROUP BY L1, L2 ORDER BY L1"
647+
).is_none());
648+
}
649+
650+
// ── scrape_interval > 1s regression tests (issue #201) ───────────────────
651+
652+
fn check_query_with_interval(
653+
sql: &str,
654+
scrape_interval: f64,
655+
expected_types: Vec<QueryType>,
656+
expected_error: Option<QueryError>,
657+
) {
658+
let schema = create_test_schema();
659+
let matcher = SQLPatternMatcher::new(schema, scrape_interval);
660+
let query_data =
661+
parse_sql_query(sql).unwrap_or_else(|| panic!("Failed to parse query: {}", sql));
662+
let result = matcher.query_info_to_pattern(&query_data);
663+
assert_eq!(result.query_type, expected_types);
664+
assert_eq!(result.error, expected_error);
665+
}
666+
667+
/// scraped_intervals = 15/15 = 1.0; bug fires 1.0 < 15.0 → false positive error
668+
#[test]
669+
fn test_bug_201_single_interval_spatial_query_not_rejected() {
670+
check_query_with_interval(
671+
"SELECT AVG(value) FROM cpu_usage \
672+
WHERE time BETWEEN DATEADD(s, -15, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
673+
GROUP BY L1, L2, L3, L4",
674+
15.0,
675+
vec![QueryType::Spatial],
676+
None,
677+
);
678+
}
679+
680+
/// scraped_intervals = 30/15 = 2.0; bug fires 2.0 < 15.0 → false positive error
681+
#[test]
682+
fn test_bug_201_two_interval_temporal_query_not_rejected() {
683+
check_query_with_interval(
684+
"SELECT SUM(value) FROM cpu_usage \
685+
WHERE time BETWEEN DATEADD(s, -30, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
686+
GROUP BY L1, L2, L3, L4",
687+
15.0,
688+
vec![QueryType::TemporalGeneric],
689+
None,
690+
);
691+
}
692+
693+
/// scraped_intervals = 30/15 = 2.0 with QUANTILE agg → TemporalQuantile
694+
#[test]
695+
fn test_bug_201_temporal_quantile_not_rejected() {
696+
check_query_with_interval(
697+
"SELECT QUANTILE(0.95, value) FROM cpu_usage \
698+
WHERE time BETWEEN DATEADD(s, -30, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
699+
GROUP BY L1, L2, L3, L4",
700+
15.0,
701+
vec![QueryType::TemporalQuantile],
702+
None,
703+
);
704+
}
705+
706+
/// scraped_intervals = 30/15 = 2.0 with subset of labels → SpatioTemporal
707+
#[test]
708+
fn test_bug_201_spatiotemporal_not_rejected() {
709+
check_query_with_interval(
710+
"SELECT SUM(value) FROM cpu_usage \
711+
WHERE time BETWEEN DATEADD(s, -30, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
712+
GROUP BY L1",
713+
15.0,
714+
vec![QueryType::SpatioTemporal],
715+
None,
716+
);
717+
}
718+
719+
/// Spatial-of-temporal: outer has UNUSED time (not checked), inner scraped_intervals = 30/15 = 2.0
720+
#[test]
721+
fn test_bug_201_spatial_of_temporal_not_rejected() {
722+
check_query_with_interval(
723+
"SELECT SUM(result) FROM \
724+
(SELECT SUM(value) AS result FROM cpu_usage \
725+
WHERE time BETWEEN DATEADD(s, -30, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
726+
GROUP BY L1, L2, L3, L4) \
727+
GROUP BY L1",
728+
15.0,
729+
vec![QueryType::Spatial, QueryType::TemporalGeneric],
730+
None,
731+
);
732+
}
733+
734+
/// scraped_intervals = 14/15 = 0.93 < 1.0 → should still be rejected (guard still works)
735+
#[test]
736+
fn test_bug_201_sub_interval_query_still_rejected() {
737+
check_query_with_interval(
738+
"SELECT AVG(value) FROM cpu_usage \
739+
WHERE time BETWEEN DATEADD(s, -14, '2025-10-01 00:00:00') AND '2025-10-01 00:00:00' \
740+
GROUP BY L1, L2, L3, L4",
741+
15.0,
742+
vec![],
743+
Some(QueryError::SpatialDurationSmall),
744+
);
745+
}
642746
}

‎asap-common/dependencies/rs/sql_utilities/src/ast_matching/sqlpattern_matcher.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ impl SQLPatternMatcher {
188188
let scrape_duration = time_info.get_duration();
189189
scraped_intervals = scrape_duration / self.scrape_interval;
190190

191-
if scraped_intervals < self.scrape_interval {
191+
if scraped_intervals < 1.0 {
192192
println!("Returned QueryError::SpatialDurationSmall");
193193

194194
return Err((
@@ -244,15 +244,15 @@ impl SQLPatternMatcher {
244244
// Last query
245245
// let time_info = TimeInfo::new("time".to_string(), *start, *scrape_duration);
246246

247-
if (scrape_duration - self.scrape_interval).abs() < f64::EPSILON {
247+
if (scrape_duration - 1.0).abs() < f64::EPSILON {
248248
sql_query.add_subquery(
249249
QueryType::Spatial,
250250
aggregation_info.clone(),
251251
metric.clone(),
252252
labels.clone(),
253253
time_info.clone(),
254254
);
255-
} else if *scrape_duration > self.scrape_interval {
255+
} else if *scrape_duration > 1.0 {
256256
// Check if labels match all metadata columns
257257
let has_all_labels = self
258258
.schema

‎asap-common/dependencies/rs/sql_utilities/src/ast_matching/sqlpattern_parser.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ impl SQLPatternParser {
3636
}
3737

3838
fn parse_query_node(&self, query: &Query) -> Option<SQLQueryData> {
39+
if query.order_by.is_some() {
40+
println!("ORDER BY is not supported");
41+
return None;
42+
}
43+
3944
// Convert CTE to subquery if present
4045
let query = self.cte_to_subquery(query);
4146

‎asap-dropin/docker-compose.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ name: asapquery-dropin
1414

1515
services:
1616
queryengine:
17-
image: ghcr.io/projectasap/asap-query-engine:v0.3.0
17+
image: ghcr.io/projectasap/asap-query-engine:v0.3.1
1818
container_name: asap-dropin-queryengine
1919
hostname: queryengine
2020
ports:

‎asap-quickstart/docker-compose.yml‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ services:
7676
#############################################################################
7777

7878
asap-planner-rs:
79-
image: ghcr.io/projectasap/asap-planner-rs:v0.3.0
79+
image: ghcr.io/projectasap/asap-planner-rs:v0.3.1
8080
container_name: asap-planner-rs
8181
hostname: asap-planner-rs
8282
networks:
@@ -99,7 +99,7 @@ services:
9999
#############################################################################
100100

101101
queryengine:
102-
image: ghcr.io/projectasap/asap-query-engine:v0.3.0
102+
image: ghcr.io/projectasap/asap-query-engine:v0.3.1
103103
container_name: asap-queryengine
104104
hostname: queryengine
105105
networks:
@@ -141,7 +141,7 @@ services:
141141

142142
# Constant values - baseline for comparison
143143
fake-exporter-constant:
144-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
144+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
145145
container_name: asap-fake-exporter-constant
146146
hostname: fake-exporter-constant
147147
networks:
@@ -163,7 +163,7 @@ services:
163163

164164
# Linear increasing - tests trend preservation
165165
fake-exporter-linear-up:
166-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
166+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
167167
container_name: asap-fake-exporter-linear-up
168168
hostname: fake-exporter-linear-up
169169
networks:
@@ -185,7 +185,7 @@ services:
185185

186186
# Linear decreasing - tests trend preservation
187187
fake-exporter-linear-down:
188-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
188+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
189189
container_name: asap-fake-exporter-linear-down
190190
hostname: fake-exporter-linear-down
191191
networks:
@@ -207,7 +207,7 @@ services:
207207

208208
# Sine wave - tests periodicity preservation
209209
fake-exporter-sine:
210-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
210+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
211211
container_name: asap-fake-exporter-sine
212212
hostname: fake-exporter-sine
213213
networks:
@@ -229,7 +229,7 @@ services:
229229

230230
# Sine with noise - tests signal extraction / smoothing
231231
fake-exporter-sine-noise:
232-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
232+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
233233
container_name: asap-fake-exporter-sine-noise
234234
hostname: fake-exporter-sine-noise
235235
networks:
@@ -251,7 +251,7 @@ services:
251251

252252
# Step function - tests edge preservation
253253
fake-exporter-step:
254-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
254+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
255255
container_name: asap-fake-exporter-step
256256
hostname: fake-exporter-step
257257
networks:
@@ -273,7 +273,7 @@ services:
273273

274274
# Exponential growth - tests non-linear patterns
275275
fake-exporter-exp-up:
276-
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.0
276+
image: ghcr.io/projectasap/asap-fake-exporter:v0.3.1
277277
container_name: asap-fake-exporter-exp-up
278278
hostname: fake-exporter-exp-up
279279
networks:

0 commit comments

Comments
 (0)