Skip to content

Commit edcb72f

Browse files
committed
Throw exception for zero span
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent 9d47720 commit edcb72f

3 files changed

Lines changed: 64 additions & 2 deletions

File tree

core/src/main/java/org/opensearch/sql/ast/dsl/AstDSL.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,15 +492,19 @@ public static Span spanFromSpanLengthLiteral(
492492
UnresolvedExpression field, Literal spanLengthLiteral) {
493493
if (spanLengthLiteral.getType() == DataType.STRING) {
494494
String spanText = spanLengthLiteral.getValue().toString();
495-
String valueStr = spanText.replaceAll("[^0-9]", "");
496-
String unitStr = spanText.replaceAll("[0-9]", "");
495+
String valueStr = spanText.replaceAll("[^0-9-]", "");
496+
String unitStr = spanText.replaceAll("[0-9-]", "");
497497

498498
if (valueStr.isEmpty()) {
499499
// No numeric value found, use the literal as-is
500500
return new Span(field, spanLengthLiteral, SpanUnit.NONE);
501501
} else {
502502
// Parse numeric value and unit
503503
Integer value = Integer.parseInt(valueStr);
504+
if (value <= 0) {
505+
throw new IllegalArgumentException(
506+
String.format("Zero or negative time interval not supported: %s", spanText));
507+
}
504508
SpanUnit unit = unitStr.isEmpty() ? SpanUnit.NONE : SpanUnit.of(unitStr);
505509
return span(field, intLiteral(value), unit);
506510
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
setup:
2+
- do:
3+
query.settings:
4+
body:
5+
transient:
6+
plugins.calcite.enabled : true
7+
- do:
8+
indices.create:
9+
index: test_timechart_span_validation
10+
body:
11+
mappings:
12+
properties:
13+
"@timestamp":
14+
type: date_nanos
15+
packets:
16+
type: long
17+
- do:
18+
bulk:
19+
index: test_timechart_span_validation
20+
refresh: true
21+
body:
22+
- '{"index": {}}'
23+
- '{"@timestamp": "2024-01-15T10:30:04.567890123Z", "packets": 100}'
24+
- '{"index": {}}'
25+
- '{"@timestamp": "2024-01-15T10:31:04.567890123Z", "packets": 150}'
26+
- '{"index": {}}'
27+
- '{"@timestamp": "2024-01-15T10:32:04.567890123Z", "packets": 120}'
28+
29+
---
30+
teardown:
31+
- do:
32+
query.settings:
33+
body:
34+
transient:
35+
plugins.calcite.enabled : false
36+
37+
---
38+
"timechart with zero span should return validation error":
39+
- skip:
40+
features:
41+
- headers
42+
- allowed_warnings
43+
- do:
44+
catch: bad_request
45+
headers:
46+
Content-Type: 'application/json'
47+
ppl:
48+
body:
49+
query: source=test_timechart_span_validation | timechart span=0m per_second(packets)
50+
- match: {"$body": "/Zero\\s+or\\s+negative\\s+time\\s+interval\\s+not\\s+supported/"}

ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTimechartTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.opensearch.sql.ppl.calcite;
77

88
import static org.junit.Assert.assertNotNull;
9+
import static org.junit.Assert.assertThrows;
910

1011
import com.google.common.collect.ImmutableList;
1112
import java.util.List;
@@ -342,6 +343,13 @@ public void testTimechartWithUseOtherBeforeLimit() {
342343
assertNotNull(plan);
343344
}
344345

346+
@Test
347+
public void testTimechartUsingZeroSpanShouldThrow() {
348+
String ppl = "source=events | timechart span=0h limit=5 count() by host";
349+
Throwable t = assertThrows(IllegalArgumentException.class, () -> parsePPL(ppl));
350+
verifyErrorMessageContains(t, "Zero or negative time interval not supported: 0h");
351+
}
352+
345353
private UnresolvedPlan parsePPL(String query) {
346354
PPLSyntaxParser parser = new PPLSyntaxParser();
347355
AstBuilder astBuilder = new AstBuilder(query);

0 commit comments

Comments
 (0)