From e3879fd97e902d61403967efbe4ac1f16a22b7bb Mon Sep 17 00:00:00 2001 From: Yuanchun Shen Date: Thu, 30 Oct 2025 10:07:13 +0800 Subject: [PATCH] Support millisecond span (#4672) * Support millisecond span Signed-off-by: Yuanchun Shen * Update per funciton tests Signed-off-by: Yuanchun Shen --------- Signed-off-by: Yuanchun Shen (cherry picked from commit b224750d9bb865aa6695055c6ec4246485f597c2) --- .../sql/ast/expression/IntervalUnit.java | 2 +- .../sql/ast/expression/SpanUnit.java | 2 + .../opensearch/sql/ast/tree/Timechart.java | 10 +- .../sql/calcite/ExtendedRexBuilder.java | 21 +++++ .../sql/calcite/utils/PlanUtils.java | 9 +- .../datetime/DateTimeFunctions.java | 9 +- .../sql/ast/tree/TimechartTest.java | 20 ++-- .../sql/calcite/remote/CalciteExplainIT.java | 16 ++-- .../rest-api-spec/test/issues/4550.yml | 93 +++++++++++++++++++ ppl/src/main/antlr/OpenSearchPPLLexer.g4 | 4 +- ppl/src/main/antlr/OpenSearchPPLParser.g4 | 2 + .../ppl/calcite/CalcitePPLTimechartTest.java | 24 ++--- .../sql/ppl/parser/AstBuilderTest.java | 16 ++-- 13 files changed, 181 insertions(+), 47 deletions(-) create mode 100644 integ-test/src/yamlRestTest/resources/rest-api-spec/test/issues/4550.yml diff --git a/core/src/main/java/org/opensearch/sql/ast/expression/IntervalUnit.java b/core/src/main/java/org/opensearch/sql/ast/expression/IntervalUnit.java index 19e1b07e39b..e2da2eabd7e 100644 --- a/core/src/main/java/org/opensearch/sql/ast/expression/IntervalUnit.java +++ b/core/src/main/java/org/opensearch/sql/ast/expression/IntervalUnit.java @@ -14,8 +14,8 @@ @RequiredArgsConstructor public enum IntervalUnit { UNKNOWN, - MICROSECOND, + MILLISECOND, SECOND, MINUTE, HOUR, diff --git a/core/src/main/java/org/opensearch/sql/ast/expression/SpanUnit.java b/core/src/main/java/org/opensearch/sql/ast/expression/SpanUnit.java index 8a78dd4eddd..43f4c8ab497 100644 --- a/core/src/main/java/org/opensearch/sql/ast/expression/SpanUnit.java +++ b/core/src/main/java/org/opensearch/sql/ast/expression/SpanUnit.java @@ -15,6 +15,8 @@ public enum SpanUnit { UNKNOWN("unknown"), NONE(""), + MICROSECOND("us"), + US("us"), MILLISECOND("ms"), MS("ms"), SECONDS("s"), diff --git a/core/src/main/java/org/opensearch/sql/ast/tree/Timechart.java b/core/src/main/java/org/opensearch/sql/ast/tree/Timechart.java index 17e34ce564c..19972358721 100644 --- a/core/src/main/java/org/opensearch/sql/ast/tree/Timechart.java +++ b/core/src/main/java/org/opensearch/sql/ast/tree/Timechart.java @@ -10,7 +10,7 @@ import static org.opensearch.sql.ast.dsl.AstDSL.eval; import static org.opensearch.sql.ast.dsl.AstDSL.function; import static org.opensearch.sql.ast.dsl.AstDSL.stringLiteral; -import static org.opensearch.sql.ast.expression.IntervalUnit.SECOND; +import static org.opensearch.sql.ast.expression.IntervalUnit.MILLISECOND; import static org.opensearch.sql.ast.tree.Timechart.PerFunctionRateExprBuilder.sum; import static org.opensearch.sql.ast.tree.Timechart.PerFunctionRateExprBuilder.timestampadd; import static org.opensearch.sql.ast.tree.Timechart.PerFunctionRateExprBuilder.timestampdiff; @@ -112,11 +112,13 @@ private UnresolvedPlan transformPerFunction() { Span span = (Span) this.binExpression; Field spanStartTime = AstDSL.field(IMPLICIT_FIELD_TIMESTAMP); Function spanEndTime = timestampadd(span.getUnit(), span.getValue(), spanStartTime); - Function spanSeconds = timestampdiff(SECOND, spanStartTime, spanEndTime); - + Function spanMillis = timestampdiff(MILLISECOND, spanStartTime, spanEndTime); + final int SECOND_IN_MILLISECOND = 1000; return eval( timechart(AstDSL.alias(perFunc.aggName, sum(perFunc.aggArg))), - let(perFunc.aggName).multiply(perFunc.seconds).dividedBy(spanSeconds)); + let(perFunc.aggName) + .multiply(perFunc.seconds * SECOND_IN_MILLISECOND) + .dividedBy(spanMillis)); } private Timechart timechart(UnresolvedExpression newAggregateFunction) { diff --git a/core/src/main/java/org/opensearch/sql/calcite/ExtendedRexBuilder.java b/core/src/main/java/org/opensearch/sql/calcite/ExtendedRexBuilder.java index b1078f2d320..35db7c064fd 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/ExtendedRexBuilder.java +++ b/core/src/main/java/org/opensearch/sql/calcite/ExtendedRexBuilder.java @@ -56,38 +56,59 @@ public RelDataType commonType(RexNode... nodes) { public SqlIntervalQualifier createIntervalUntil(SpanUnit unit) { TimeUnit timeUnit; switch (unit) { + case MICROSECOND: + case US: + timeUnit = TimeUnit.MICROSECOND; + break; case MILLISECOND: case MS: timeUnit = TimeUnit.MILLISECOND; break; + case SECONDS: case SECOND: + case SECS: + case SEC: case S: timeUnit = TimeUnit.SECOND; break; + case MINUTES: case MINUTE: + case MINS: + case MIN: case m: timeUnit = TimeUnit.MINUTE; break; + case HOURS: case HOUR: + case HRS: + case HR: case H: timeUnit = TimeUnit.HOUR; break; + case DAYS: case DAY: case D: timeUnit = TimeUnit.DAY; break; + case WEEKS: case WEEK: case W: timeUnit = TimeUnit.WEEK; break; + case MONTHS: case MONTH: + case MON: case M: timeUnit = TimeUnit.MONTH; break; + case QUARTERS: case QUARTER: + case QTRS: + case QTR: case Q: timeUnit = TimeUnit.QUARTER; break; + case YEARS: case YEAR: case Y: timeUnit = TimeUnit.YEAR; diff --git a/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java b/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java index 1f755d50df1..7476df97db5 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java +++ b/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java @@ -70,8 +70,10 @@ static SpanUnit intervalUnitToSpanUnit(IntervalUnit unit) { SpanUnit result; switch (unit) { case MICROSECOND: - result = SpanUnit.MILLISECOND; + result = SpanUnit.MICROSECOND; break; + case MILLISECOND: + result = SpanUnit.MILLISECOND; case SECOND: result = SpanUnit.SECOND; break; @@ -108,9 +110,12 @@ static SpanUnit intervalUnitToSpanUnit(IntervalUnit unit) { static IntervalUnit spanUnitToIntervalUnit(SpanUnit unit) { switch (unit) { + case MICROSECOND: + case US: + return IntervalUnit.MICROSECOND; case MILLISECOND: case MS: - return IntervalUnit.MICROSECOND; + return IntervalUnit.MILLISECOND; case SECOND: case SECONDS: case SEC: diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunctions.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunctions.java index 40c306fd29b..29b330b73f2 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunctions.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunctions.java @@ -8,6 +8,7 @@ import static java.time.temporal.ChronoUnit.DAYS; import static java.time.temporal.ChronoUnit.HOURS; import static java.time.temporal.ChronoUnit.MICROS; +import static java.time.temporal.ChronoUnit.MILLIS; import static java.time.temporal.ChronoUnit.MINUTES; import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.SECONDS; @@ -2152,6 +2153,9 @@ public static ExprValue exprTimestampAdd( case "MICROSECOND": temporalUnit = MICROS; break; + case "MILLISECOND": + temporalUnit = MILLIS; + break; case "SECOND": temporalUnit = SECONDS; break; @@ -2191,10 +2195,13 @@ public static ExprValue exprTimestampAddForTimeType( private ExprValue getTimeDifference(String part, LocalDateTime startTime, LocalDateTime endTime) { long returnVal; - switch (part) { + switch (part.toUpperCase(Locale.ROOT)) { case "MICROSECOND": returnVal = MICROS.between(startTime, endTime); break; + case "MILLISECOND": + returnVal = MILLIS.between(startTime, endTime); + break; case "SECOND": returnVal = SECONDS.between(startTime, endTime); break; diff --git a/core/src/test/java/org/opensearch/sql/ast/tree/TimechartTest.java b/core/src/test/java/org/opensearch/sql/ast/tree/TimechartTest.java index 85e4de0462f..d587ff71787 100644 --- a/core/src/test/java/org/opensearch/sql/ast/tree/TimechartTest.java +++ b/core/src/test/java/org/opensearch/sql/ast/tree/TimechartTest.java @@ -54,9 +54,9 @@ void should_transform_per_second_for_different_spans( let( "per_second(bytes)", divide( - multiply("per_second(bytes)", 1.0), + multiply("per_second(bytes)", 1000.0), timestampdiff( - "SECOND", + "MILLISECOND", "@timestamp", timestampadd(expectedIntervalUnit, spanValue, "@timestamp")))), timechart(span(spanValue, spanUnit), alias("per_second(bytes)", sum("bytes"))))); @@ -73,9 +73,9 @@ void should_transform_per_minute_for_different_spans( let( "per_minute(bytes)", divide( - multiply("per_minute(bytes)", 60.0), + multiply("per_minute(bytes)", 60000.0), timestampdiff( - "SECOND", + "MILLISECOND", "@timestamp", timestampadd(expectedIntervalUnit, spanValue, "@timestamp")))), timechart(span(spanValue, spanUnit), alias("per_minute(bytes)", sum("bytes"))))); @@ -92,9 +92,9 @@ void should_transform_per_hour_for_different_spans( let( "per_hour(bytes)", divide( - multiply("per_hour(bytes)", 3600.0), + multiply("per_hour(bytes)", 3600000.0), timestampdiff( - "SECOND", + "MILLISECOND", "@timestamp", timestampadd(expectedIntervalUnit, spanValue, "@timestamp")))), timechart(span(spanValue, spanUnit), alias("per_hour(bytes)", sum("bytes"))))); @@ -111,9 +111,9 @@ void should_transform_per_day_for_different_spans( let( "per_day(bytes)", divide( - multiply("per_day(bytes)", 86400.0), + multiply("per_day(bytes)", 8.64E7), timestampdiff( - "SECOND", + "MILLISECOND", "@timestamp", timestampadd(expectedIntervalUnit, spanValue, "@timestamp")))), timechart(span(spanValue, spanUnit), alias("per_day(bytes)", sum("bytes"))))); @@ -149,9 +149,9 @@ void should_preserve_all_fields_during_per_function_transformation() { let( "per_second(bytes)", divide( - multiply("per_second(bytes)", 1.0), + multiply("per_second(bytes)", 1000.0), timestampdiff( - "SECOND", "@timestamp", timestampadd("MINUTE", 5, "@timestamp")))), + "MILLISECOND", "@timestamp", timestampadd("MINUTE", 5, "@timestamp")))), expected)); } diff --git a/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java b/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java index 45eb0b84536..3b408302bbc 100644 --- a/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java @@ -444,8 +444,8 @@ public void testExplainTimechartPerSecond() throws IOException { var result = explainQueryToString("source=events | timechart span=2m per_second(cpu_usage)"); assertTrue( result.contains( - "per_second(cpu_usage)=[DIVIDE(*($1, 1.0E0), " - + "TIMESTAMPDIFF('SECOND':VARCHAR, $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); + "per_second(cpu_usage)=[DIVIDE(*($1, 1000.0E0), TIMESTAMPDIFF('MILLISECOND':VARCHAR," + + " $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); assertTrue(result.contains("per_second(cpu_usage)=[SUM($0)]")); } @@ -454,8 +454,8 @@ public void testExplainTimechartPerMinute() throws IOException { var result = explainQueryToString("source=events | timechart span=2m per_minute(cpu_usage)"); assertTrue( result.contains( - "per_minute(cpu_usage)=[DIVIDE(*($1, 60.0E0), " - + "TIMESTAMPDIFF('SECOND':VARCHAR, $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); + "per_minute(cpu_usage)=[DIVIDE(*($1, 60000.0E0), TIMESTAMPDIFF('MILLISECOND':VARCHAR," + + " $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); assertTrue(result.contains("per_minute(cpu_usage)=[SUM($0)]")); } @@ -464,8 +464,8 @@ public void testExplainTimechartPerHour() throws IOException { var result = explainQueryToString("source=events | timechart span=2m per_hour(cpu_usage)"); assertTrue( result.contains( - "per_hour(cpu_usage)=[DIVIDE(*($1, 3600.0E0), " - + "TIMESTAMPDIFF('SECOND':VARCHAR, $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); + "per_hour(cpu_usage)=[DIVIDE(*($1, 3600000.0E0), TIMESTAMPDIFF('MILLISECOND':VARCHAR," + + " $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); assertTrue(result.contains("per_hour(cpu_usage)=[SUM($0)]")); } @@ -474,8 +474,8 @@ public void testExplainTimechartPerDay() throws IOException { var result = explainQueryToString("source=events | timechart span=2m per_day(cpu_usage)"); assertTrue( result.contains( - "per_day(cpu_usage)=[DIVIDE(*($1, 86400.0E0), " - + "TIMESTAMPDIFF('SECOND':VARCHAR, $0, TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); + "per_day(cpu_usage)=[DIVIDE(*($1, 8.64E7), TIMESTAMPDIFF('MILLISECOND':VARCHAR, $0," + + " TIMESTAMPADD('MINUTE':VARCHAR, 2, $0)))]")); assertTrue(result.contains("per_day(cpu_usage)=[SUM($0)]")); } diff --git a/integ-test/src/yamlRestTest/resources/rest-api-spec/test/issues/4550.yml b/integ-test/src/yamlRestTest/resources/rest-api-spec/test/issues/4550.yml new file mode 100644 index 00000000000..e676e8cb490 --- /dev/null +++ b/integ-test/src/yamlRestTest/resources/rest-api-spec/test/issues/4550.yml @@ -0,0 +1,93 @@ +setup: + - do: + indices.create: + index: test_data_2023 + body: + mappings: + properties: + "@timestamp": + type: date + "packets": + type: integer + - do: + bulk: + index: test_data_2023 + refresh: true + body: + - '{"index":{}}' + - '{"@timestamp":"2023-10-08T10:00:00.000Z","packets":10}' + - '{"index":{}}' + - '{"@timestamp":"2023-10-08T10:00:00.500Z","packets":15}' + - '{"index":{}}' + - '{"@timestamp":"2023-10-08T10:00:01.000Z","packets":20}' + - '{"index":{}}' + - '{"@timestamp":"2023-10-08T10:00:01.500Z","packets":25}' + - '{"index":{}}' + - '{"@timestamp":"2023-10-08T10:00:02.000Z","packets":30}' + +--- +"timechart with millisecond span": + - skip: + features: + - headers + - allowed_warnings + - do: + headers: + Content-Type: 'application/json' + ppl: + body: + query: source=test_data_2023 | timechart span=500ms count() + + - match: { total: 5 } + - match: { "schema": [ { "name": "@timestamp", "type": "timestamp" }, { "name": "count", "type": "bigint" }] } + - match: {"datarows": [["2023-10-08 10:00:00", 1], ["2023-10-08 10:00:00.5", 1], ["2023-10-08 10:00:01", 1], ["2023-10-08 10:00:01.5", 1], ["2023-10-08 10:00:02", 1]]} + +--- +"timechart with millisecond span and per_second function": + - skip: + features: + - headers + - allowed_warnings + - do: + headers: + Content-Type: 'application/json' + ppl: + body: + query: source=test_data_2023 | timechart span=1000ms per_second(packets) + + - match: { total: 3 } + - match: { "schema": [ { "name": "@timestamp", "type": "timestamp" }, { "name": "per_second(packets)", "type": "double" }] } + - match: {"datarows": [["2023-10-08 10:00:00", 25.0], ["2023-10-08 10:00:01", 45.0], ["2023-10-08 10:00:02", 30.0]]} + +--- +"timechart with milliseconds": + - skip: + features: + - headers + - allowed_warnings + - do: + headers: + Content-Type: 'application/json' + ppl: + body: + query: source=test_data_2023 | timechart span=250milliseconds count() + + - match: { total: 5 } + - match: { "schema": [ { "name": "@timestamp", "type": "timestamp" }, { "name": "count", "type": "bigint" }] } + +--- +"timechart with second span for comparison": + - skip: + features: + - headers + - allowed_warnings + - do: + headers: + Content-Type: 'application/json' + ppl: + body: + query: source=test_data_2023 | timechart span=1s count() + + - match: { total: 3 } + - match: { "schema": [ { "name": "@timestamp", "type": "timestamp" }, { "name": "count", "type": "bigint" }] } + - match: {"datarows": [["2023-10-08 10:00:00", 2], ["2023-10-08 10:00:01", 2], ["2023-10-08 10:00:02", 1]]} diff --git a/ppl/src/main/antlr/OpenSearchPPLLexer.g4 b/ppl/src/main/antlr/OpenSearchPPLLexer.g4 index 368c32f250f..0899de168fb 100644 --- a/ppl/src/main/antlr/OpenSearchPPLLexer.g4 +++ b/ppl/src/main/antlr/OpenSearchPPLLexer.g4 @@ -170,6 +170,7 @@ HOUR_MINUTE: 'HOUR_MINUTE'; HOUR_OF_DAY: 'HOUR_OF_DAY'; HOUR_SECOND: 'HOUR_SECOND'; INTERVAL: 'INTERVAL'; +MILLISECOND: 'MILLISECOND'; MICROSECOND: 'MICROSECOND'; MINUTE: 'MINUTE'; MINUTE_MICROSECOND: 'MINUTE_MICROSECOND'; @@ -505,7 +506,8 @@ ALIGNTIME: 'ALIGNTIME'; PERCENTILE_SHORTCUT: PERC(INTEGER_LITERAL | DECIMAL_LITERAL) | 'P'(INTEGER_LITERAL | DECIMAL_LITERAL); SPANLENGTH: [0-9]+ ( - 'US'|'MS'|'CS'|'DS' + 'US' |'CS'|'DS' + |'MS'|'MILLISECOND'|'MILLISECONDS' |'S'|'SEC'|'SECS'|'SECOND'|'SECONDS' |'MIN'|'MINS'|'MINUTE'|'MINUTES' |'H'|'HR'|'HRS'|'HOUR'|'HOURS' diff --git a/ppl/src/main/antlr/OpenSearchPPLParser.g4 b/ppl/src/main/antlr/OpenSearchPPLParser.g4 index 5c4aa0bf6a5..fda22fc2481 100644 --- a/ppl/src/main/antlr/OpenSearchPPLParser.g4 +++ b/ppl/src/main/antlr/OpenSearchPPLParser.g4 @@ -1157,6 +1157,7 @@ extractFunctionCall simpleDateTimePart : MICROSECOND + | MILLISECOND | SECOND | MINUTE | HOUR @@ -1335,6 +1336,7 @@ timestampLiteral intervalUnit : MICROSECOND + | MILLISECOND | SECOND | MINUTE | HOUR diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTimechartTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTimechartTest.java index 0470fc19957..ee6b82f2d85 100644 --- a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTimechartTest.java +++ b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLTimechartTest.java @@ -86,9 +86,9 @@ public void testTimechartBasic() { public void testTimechartPerSecond() { withPPLQuery("source=events | timechart per_second(cpu_usage)") .expectSparkSQL( - "SELECT `@timestamp`, `DIVIDE`(`per_second(cpu_usage)` * 1.0E0, TIMESTAMPDIFF('SECOND'," - + " `@timestamp`, TIMESTAMPADD('MINUTE', 1, `@timestamp`)))" - + " `per_second(cpu_usage)`\n" + "SELECT `@timestamp`, `DIVIDE`(`per_second(cpu_usage)` * 1.0000E3," + + " TIMESTAMPDIFF('MILLISECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1," + + " `@timestamp`))) `per_second(cpu_usage)`\n" + "FROM (SELECT `SPAN`(`@timestamp`, 1, 'm') `@timestamp`, SUM(`cpu_usage`)" + " `per_second(cpu_usage)`\n" + "FROM `scott`.`events`\n" @@ -100,9 +100,9 @@ public void testTimechartPerSecond() { public void testTimechartPerMinute() { withPPLQuery("source=events | timechart per_minute(cpu_usage)") .expectSparkSQL( - "SELECT `@timestamp`, `DIVIDE`(`per_minute(cpu_usage)` * 6.00E1," - + " TIMESTAMPDIFF('SECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1, `@timestamp`)))" - + " `per_minute(cpu_usage)`\n" + "SELECT `@timestamp`, `DIVIDE`(`per_minute(cpu_usage)` * 6.00000E4," + + " TIMESTAMPDIFF('MILLISECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1," + + " `@timestamp`))) `per_minute(cpu_usage)`\n" + "FROM (SELECT `SPAN`(`@timestamp`, 1, 'm') `@timestamp`, SUM(`cpu_usage`)" + " `per_minute(cpu_usage)`\n" + "FROM `scott`.`events`\n" @@ -114,9 +114,9 @@ public void testTimechartPerMinute() { public void testTimechartPerHour() { withPPLQuery("source=events | timechart per_hour(cpu_usage)") .expectSparkSQL( - "SELECT `@timestamp`, `DIVIDE`(`per_hour(cpu_usage)` * 3.6000E3," - + " TIMESTAMPDIFF('SECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1, `@timestamp`)))" - + " `per_hour(cpu_usage)`\n" + "SELECT `@timestamp`, `DIVIDE`(`per_hour(cpu_usage)` * 3.6000000E6," + + " TIMESTAMPDIFF('MILLISECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1," + + " `@timestamp`))) `per_hour(cpu_usage)`\n" + "FROM (SELECT `SPAN`(`@timestamp`, 1, 'm') `@timestamp`, SUM(`cpu_usage`)" + " `per_hour(cpu_usage)`\n" + "FROM `scott`.`events`\n" @@ -128,9 +128,9 @@ public void testTimechartPerHour() { public void testTimechartPerDay() { withPPLQuery("source=events | timechart per_day(cpu_usage)") .expectSparkSQL( - "SELECT `@timestamp`, `DIVIDE`(`per_day(cpu_usage)` * 8.64000E4," - + " TIMESTAMPDIFF('SECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1, `@timestamp`)))" - + " `per_day(cpu_usage)`\n" + "SELECT `@timestamp`, `DIVIDE`(`per_day(cpu_usage)` * 8.64E7," + + " TIMESTAMPDIFF('MILLISECOND', `@timestamp`, TIMESTAMPADD('MINUTE', 1," + + " `@timestamp`))) `per_day(cpu_usage)`\n" + "FROM (SELECT `SPAN`(`@timestamp`, 1, 'm') `@timestamp`, SUM(`cpu_usage`)" + " `per_day(cpu_usage)`\n" + "FROM `scott`.`events`\n" diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstBuilderTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstBuilderTest.java index 1080095b375..12609ed5c4c 100644 --- a/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstBuilderTest.java +++ b/ppl/src/test/java/org/opensearch/sql/ppl/parser/AstBuilderTest.java @@ -1195,10 +1195,10 @@ public void testTimechartWithPerSecondFunction() { field("per_second(a)"), function( "/", - function("*", field("per_second(a)"), doubleLiteral(1.0)), + function("*", field("per_second(a)"), doubleLiteral(1000.0)), function( "timestampdiff", - stringLiteral("SECOND"), + stringLiteral("MILLISECOND"), field("@timestamp"), function( "timestampadd", @@ -1220,10 +1220,10 @@ public void testTimechartWithPerMinuteFunction() { field("per_minute(a)"), function( "/", - function("*", field("per_minute(a)"), doubleLiteral(60.0)), + function("*", field("per_minute(a)"), doubleLiteral(60000.0)), function( "timestampdiff", - stringLiteral("SECOND"), + stringLiteral("MILLISECOND"), field("@timestamp"), function( "timestampadd", @@ -1245,10 +1245,10 @@ public void testTimechartWithPerHourFunction() { field("per_hour(a)"), function( "/", - function("*", field("per_hour(a)"), doubleLiteral(3600.0)), + function("*", field("per_hour(a)"), doubleLiteral(3600000.0)), function( "timestampdiff", - stringLiteral("SECOND"), + stringLiteral("MILLISECOND"), field("@timestamp"), function( "timestampadd", @@ -1270,10 +1270,10 @@ public void testTimechartWithPerDayFunction() { field("per_day(a)"), function( "/", - function("*", field("per_day(a)"), doubleLiteral(86400.0)), + function("*", field("per_day(a)"), doubleLiteral(8.64E7)), function( "timestampdiff", - stringLiteral("SECOND"), + stringLiteral("MILLISECOND"), field("@timestamp"), function( "timestampadd",