diff --git a/docs/changelog/136448.yaml b/docs/changelog/136448.yaml new file mode 100644 index 0000000000000..649b9da2d45d8 --- /dev/null +++ b/docs/changelog/136448.yaml @@ -0,0 +1,6 @@ +pr: 136448 +summary: Add `m` alias for `minute` duration literal +area: ES|QL +type: enhancement +issues: + - 135552 diff --git a/docs/reference/query-languages/esql/esql-time-spans.md b/docs/reference/query-languages/esql/esql-time-spans.md index e9da009e7deff..fb0b73421575b 100644 --- a/docs/reference/query-languages/esql/esql-time-spans.md +++ b/docs/reference/query-languages/esql/esql-time-spans.md @@ -120,7 +120,7 @@ POST /_query | week | w, weeks | | day | d, days | | hour | h, hours | -| minute | min, minutes | +| minute | m, min, minutes | | second | s, sec, seconds | | millisecond | ms, milliseconds | diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java index b098c4be0cdf3..37da17b2b4a7b 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/RestEsqlTestCase.java @@ -666,7 +666,7 @@ public void testErrorMessageForInvalidIntervalParams() throws IOException { error, containsString( "Invalid interval value in [?n2::time_duration], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3 days]" + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3 days]" ) ); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/tbucket.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/tbucket.csv-spec index cb0c699ae451e..ee8cfc86a3b1a 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/tbucket.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/tbucket.csv-spec @@ -255,11 +255,12 @@ errors:long | day:datetime | message:keyword keepWildcardBeforeStats required_capability: implicit_casting_string_literal_to_temporal_amount required_capability: tbucket +required_capability: temporal_amount_m FROM sample_data | WHERE client_ip IS NOT NULL | KEEP *stamp*, client_ip, event_duration -| STATS p95 = PERCENTILE(event_duration, 95) BY ten_min = TBUCKET(10min), client_ip +| STATS p95 = PERCENTILE(event_duration, 95) BY ten_min = TBUCKET(10m), client_ip ; ignoreOrder:true diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index 36b61e127888e..cffbd17244d8c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -1499,7 +1499,12 @@ public enum Cap { /** * Support for dots in FUSE attributes */ - DOTS_IN_FUSE; + DOTS_IN_FUSE, + + /** + * Support for the literal {@code m} suffix as an alias for {@code minute} in temporal amounts. + */ + TEMPORAL_AMOUNT_M; private final boolean enabled; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java index 059cb20b8a08c..98b89d1983958 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/type/EsqlDataTypeConverter.java @@ -175,6 +175,7 @@ public enum INTERVALS { MINUTE, MINUTES, MIN, + M, HOUR, HOURS, H, @@ -208,6 +209,7 @@ public enum INTERVALS { INTERVALS.MINUTE, INTERVALS.MINUTES, INTERVALS.MIN, + INTERVALS.M, INTERVALS.HOUR, INTERVALS.HOURS, INTERVALS.H @@ -488,7 +490,7 @@ public static TemporalAmount parseTemporalAmount(Number value, String temporalUn return switch (INTERVALS.valueOf(temporalUnit.toUpperCase(Locale.ROOT))) { case MILLISECOND, MILLISECONDS, MS -> Duration.ofMillis(safeToLong(value)); case SECOND, SECONDS, SEC, S -> Duration.ofSeconds(safeToLong(value)); - case MINUTE, MINUTES, MIN -> Duration.ofMinutes(safeToLong(value)); + case MINUTE, MINUTES, MIN, M -> Duration.ofMinutes(safeToLong(value)); case HOUR, HOURS, H -> Duration.ofHours(safeToLong(value)); case DAY, DAYS, D -> Period.ofDays(safeToInt(safeToLong(value))); diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java index 4c5004fd3c9ff..ab21c700b41be 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LogicalPlanOptimizerTests.java @@ -7973,7 +7973,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { from types | EVAL interval = "3 ours", x = date + interval::time_duration""")); assertEquals( "Invalid interval value in [interval::time_duration], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3 ours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3 ours]", e.getMessage() ); @@ -7981,7 +7981,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { from types | EVAL interval = "- 3 hours", x = date + interval::time_duration""")); assertEquals( "Invalid interval value in [interval::time_duration], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [- 3 hours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [- 3 hours]", e.getMessage() ); @@ -7989,7 +7989,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { from types | EVAL interval = "3 ours", x = date - to_timeduration(interval)""")); assertEquals( "Invalid interval value in [to_timeduration(interval)], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3 ours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3 ours]", e.getMessage() ); @@ -7997,7 +7997,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { from types | EVAL interval = "- 3 hours", x = date - to_timeduration(interval)""")); assertEquals( "Invalid interval value in [to_timeduration(interval)], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [- 3 hours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [- 3 hours]", e.getMessage() ); @@ -8005,7 +8005,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { from types | EVAL interval = "3.5 hours", x = date - to_timeduration(interval)""")); assertEquals( "Invalid interval value in [to_timeduration(interval)], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3.5 hours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3.5 hours]", e.getMessage() ); @@ -8029,7 +8029,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { row x = "2024-01-01"::datetime | eval y = x + "3 ours"::time_duration""")); assertEquals( "Invalid interval value in [\"3 ours\"::time_duration], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3 ours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3 ours]", e.getMessage() ); @@ -8037,7 +8037,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { row x = "2024-01-01"::datetime | eval y = x - to_timeduration("3 ours")""")); assertEquals( "Invalid interval value in [to_timeduration(\"3 ours\")], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3 ours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3 ours]", e.getMessage() ); @@ -8045,7 +8045,7 @@ public void testToDatePeriodTimeDurationInvalidIntervals() { row x = "2024-01-01"::datetime | eval y = x - to_timeduration("3.5 hours")""")); assertEquals( "Invalid interval value in [to_timeduration(\"3.5 hours\")], expected integer followed by one of " - + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, HOUR, HOURS, H] but got [3.5 hours]", + + "[MILLISECOND, MILLISECONDS, MS, SECOND, SECONDS, SEC, S, MINUTE, MINUTES, MIN, M, HOUR, HOURS, H] but got [3.5 hours]", e.getMessage() ); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/ExpressionTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/ExpressionTests.java index c39dc70f3ad39..20ca82fc845db 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/ExpressionTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/parser/ExpressionTests.java @@ -392,6 +392,7 @@ public void testDurationLiterals() { assertEquals(l(Duration.ofMinutes(value), TIME_DURATION), whereExpression(value + "minute")); assertEquals(l(Duration.ofMinutes(value), TIME_DURATION), whereExpression(value + " minutes")); assertEquals(l(Duration.ofMinutes(value), TIME_DURATION), whereExpression(value + " min")); + assertEquals(l(Duration.ofMinutes(value), TIME_DURATION), whereExpression(value + " m")); assertEquals(l(Duration.ZERO, TIME_DURATION), whereExpression("0 hour")); assertEquals(l(Duration.ofHours(value), TIME_DURATION), whereExpression(value + "hour"));