From 16522a978dc85572280ba4be5d780b7fde909eb3 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 23 Feb 2023 11:57:46 -0800 Subject: [PATCH 01/11] Added Tests Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 115 ++++++++++++++++++ .../sql/sql/DateTimeFunctionIT.java | 6 + .../sql/sql/antlr/SQLSyntaxParserTest.java | 6 + 3 files changed, 127 insertions(+) diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java index fdb029ca90..c580ad1ec8 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java @@ -1498,6 +1498,121 @@ private void weekQuery(String date, int mode, int expectedResult) { assertEquals(integerValue(expectedResult), eval(expression)); } + private void weekdayQuery( + FunctionExpression dateExpression, + int dayOfWeek, + String testExpr) { + + assertAll( + () -> assertEquals(INTEGER, dateExpression.type()), + () -> assertEquals(integerValue(dayOfWeek), eval(dateExpression)), + () -> assertEquals(testExpr, dateExpression.toString()) + ); + } + + private static Stream getTestDataForWeekday() { + return Stream.of( + Arguments.of( + DSL.literal(new ExprDateValue("2020-08-07")), + 5, + "weekday(DATE '2020-08-07')"), + Arguments.of( + DSL.literal(new ExprDateValue("2020-08-09")), + 0, + "weekday(DATE '2020-08-09')"), + Arguments.of( + DSL.literal("2020-08-09"), + 0, + "weekday(\"2020-08-09\")"), + Arguments.of( + DSL.literal("2020-08-09 01:02:03"), + 0, + "weekday(\"2020-08-09 01:02:03\")") + ); + } + + @MethodSource("getTestDataForWeekday") + @ParameterizedTest + public void weekday(LiteralExpression arg, int expectedInt, String expectedString) { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + + FunctionExpression expression = DSL.weekday( + functionProperties, + arg); + + weekdayQuery(expression, expectedInt, expectedString); + } + + @Test + public void testDayOfWeekWithTimeType() { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + FunctionExpression expression = DSL.weekday( + functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); + + assertAll( + () -> assertEquals(INTEGER, eval(expression).type()), + () -> assertEquals(( + LocalDate.now( + functionProperties.getQueryStartClock()).getDayOfWeek().getValue() % 7) + 1, + eval(expression).integerValue()), + () -> assertEquals("weekday(TIME '12:23:34')", expression.toString()) + ); + } + + private void testInvalidWeekday(String date) { + FunctionExpression expression = DSL.weekday( + functionProperties, DSL.literal(new ExprDateValue(date))); + eval(expression); + } + + @Test + public void weekdayLeapYear() { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + + assertAll( + //Feb. 29 of a leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2020-02-29")), 6, "weekday(\"2020-02-29\")"), + //day after Feb. 29 of a leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2020-03-01")), 0, "weekday(\"2020-03-01\")"), + //Feb. 28 of a non-leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2021-02-28")), 0, "weekday(\"2021-02-28\")"), + //Feb. 29 of a non-leap year + () -> assertThrows( + SemanticCheckException.class, () -> testInvalidWeekday("2021-02-29")) + ); + } + + @Test + public void weekdayInvalidArgument() { + when(nullRef.type()).thenReturn(DATE); + when(missingRef.type()).thenReturn(DATE); + assertEquals(nullValue(), eval(DSL.weekday(functionProperties, nullRef))); + assertEquals(missingValue(), eval(DSL.weekday(functionProperties, missingRef))); + + assertAll( + //40th day of the month + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("2021-02-40")), + + //13th month of the year + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("2021-13-29")), + + //incorrect format + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("asdfasdf")) + ); + } + private void weekOfYearUnderscoresQuery(String date, int mode, int expectedResult) { FunctionExpression expression = DSL .week_of_year( diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java index 4254641524..661f1db296 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java @@ -932,6 +932,12 @@ public void testWeek() throws IOException { week("2000-01-01", 2, 52, "week"); } + @Test + public void testWeekday() throws IOException { + JSONObject result = executeQuery(String.format("SELECT weekday(datetime0) FROM %s LIMIT 3")); + verifyDataRows(result, rows(3), rows(1), rows(2)); + } + @Test public void testWeekOfYearUnderscores() throws IOException { JSONObject result = executeQuery("select week_of_year(date('2008-02-20'))"); diff --git a/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java b/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java index 0b8e64d0bb..a00231425f 100644 --- a/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java +++ b/sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java @@ -175,6 +175,12 @@ private static Stream nowLikeFunctionsData() { ); } + @Test + public void can_parse_weekday_function() { + assertNotNull(parser.parse("SELECT weekday('2022-11-18')")); + assertNotNull(parser.parse("SELECT day_of_week('2022-11-18')")); + } + @ParameterizedTest(name = "{0}") @MethodSource("nowLikeFunctionsData") public void can_parse_now_like_functions(String name, Boolean hasFsp, Boolean hasShortcut) { From 719bb6ef4e981696d6dc82d2aad7c3b00f666922 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 23 Feb 2023 15:35:57 -0800 Subject: [PATCH 02/11] Added Implementation Signed-off-by: GabeFernandez310 --- .../org/opensearch/sql/expression/DSL.java | 5 ++++ .../expression/datetime/DateTimeFunction.java | 23 +++++++++++++++++++ .../function/BuiltinFunctionName.java | 1 + .../datetime/DateTimeFunctionTest.java | 12 +++++----- sql/src/main/antlr/OpenSearchSQLLexer.g4 | 1 + sql/src/main/antlr/OpenSearchSQLParser.g4 | 1 + 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/opensearch/sql/expression/DSL.java b/core/src/main/java/org/opensearch/sql/expression/DSL.java index 616f431283..7f369bc342 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -439,6 +439,11 @@ public static FunctionExpression week( return compile(functionProperties, BuiltinFunctionName.WEEK, expressions); } + public static FunctionExpression weekday(FunctionProperties functionProperties, + Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.WEEKDAY, expressions); + } + public static FunctionExpression weekofyear( FunctionProperties functionProperties, Expression... expressions) { return compile(functionProperties, BuiltinFunctionName.WEEKOFYEAR, expressions); diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index fc8cdc93ef..1eb1887c4c 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java @@ -195,6 +195,7 @@ public void register(BuiltinFunctionRepository repository) { repository.register(week(BuiltinFunctionName.WEEK)); repository.register(week(BuiltinFunctionName.WEEKOFYEAR)); repository.register(week(BuiltinFunctionName.WEEK_OF_YEAR)); + repository.register(weekday()); repository.register(year()); } @@ -888,6 +889,18 @@ private DefaultFunctionResolver week(BuiltinFunctionName week) { ); } + private DefaultFunctionResolver weekday() { + return define(BuiltinFunctionName.WEEKDAY.getName(), + implWithProperties(nullMissingHandlingWithProperties( + (functionProperties, arg) -> DateTimeFunction.dayOfWeekToday( + functionProperties.getQueryStartClock())), INTEGER, TIME), + impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATE), + impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATETIME), + impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, TIMESTAMP), + impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, STRING) + ); + } + /** * YEAR(STRING/DATE/DATETIME/TIMESTAMP). return the year for date (1000-9999). */ @@ -1637,6 +1650,16 @@ private ExprValue exprWeek(ExprValue date, ExprValue mode) { CalendarLookup.getWeekNumber(mode.integerValue(), date.dateValue())); } + /** + * Weekday implementation for ExprValue. + * + * @param date ExprValue of Date/Datetime/String/Timstamp type. + * @return ExprValue. + */ + private ExprValue exprWeekday(ExprValue date) { + return new ExprIntegerValue(date.dateValue().getDayOfWeek().getValue() - 1); + } + private ExprValue unixTimeStamp(Clock clock) { return new ExprLongValue(Instant.now(clock).getEpochSecond()); } diff --git a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java index ec4a7bc140..968950c09a 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java @@ -109,6 +109,7 @@ public enum BuiltinFunctionName { UTC_TIMESTAMP(FunctionName.of("utc_timestamp")), UNIX_TIMESTAMP(FunctionName.of("unix_timestamp")), WEEK(FunctionName.of("week")), + WEEKDAY(FunctionName.of("weekday")), WEEKOFYEAR(FunctionName.of("weekofyear")), WEEK_OF_YEAR(FunctionName.of("week_of_year")), YEAR(FunctionName.of("year")), diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java index c580ad1ec8..64397d695f 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java @@ -1514,19 +1514,19 @@ private static Stream getTestDataForWeekday() { return Stream.of( Arguments.of( DSL.literal(new ExprDateValue("2020-08-07")), - 5, + 4, "weekday(DATE '2020-08-07')"), Arguments.of( DSL.literal(new ExprDateValue("2020-08-09")), - 0, + 6, "weekday(DATE '2020-08-09')"), Arguments.of( DSL.literal("2020-08-09"), - 0, + 6, "weekday(\"2020-08-09\")"), Arguments.of( DSL.literal("2020-08-09 01:02:03"), - 0, + 6, "weekday(\"2020-08-09 01:02:03\")") ); } @@ -1545,7 +1545,7 @@ public void weekday(LiteralExpression arg, int expectedInt, String expectedStrin } @Test - public void testDayOfWeekWithTimeType() { + public void testWeekdayWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expression = DSL.weekday( @@ -1555,7 +1555,7 @@ public void testDayOfWeekWithTimeType() { () -> assertEquals(INTEGER, eval(expression).type()), () -> assertEquals(( LocalDate.now( - functionProperties.getQueryStartClock()).getDayOfWeek().getValue() % 7) + 1, + functionProperties.getQueryStartClock()).getDayOfWeek().getValue() % 7), eval(expression).integerValue()), () -> assertEquals("weekday(TIME '12:23:34')", expression.toString()) ); diff --git a/sql/src/main/antlr/OpenSearchSQLLexer.g4 b/sql/src/main/antlr/OpenSearchSQLLexer.g4 index 25f23a7bd6..a09bb88778 100644 --- a/sql/src/main/antlr/OpenSearchSQLLexer.g4 +++ b/sql/src/main/antlr/OpenSearchSQLLexer.g4 @@ -331,6 +331,7 @@ TOPHITS: 'TOPHITS'; TYPEOF: 'TYPEOF'; WEEK_OF_YEAR: 'WEEK_OF_YEAR'; WEEKOFYEAR: 'WEEKOFYEAR'; +WEEKDAY: 'WEEKDAY'; WILDCARDQUERY: 'WILDCARDQUERY'; WILDCARD_QUERY: 'WILDCARD_QUERY'; diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index e5efeabba0..e801363724 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -479,6 +479,7 @@ dateTimeFunctionName | TO_DAYS | UNIX_TIMESTAMP | WEEK + | WEEKDAY | WEEK_OF_YEAR | WEEKOFYEAR | YEAR From 32e0d61dfad7756e032fc859768f958e0fdb1d84 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 24 Feb 2023 07:55:16 -0800 Subject: [PATCH 03/11] Added Documentation Signed-off-by: GabeFernandez310 --- docs/user/dql/functions.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 5d5a3e1f96..ed62af85a0 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -2627,6 +2627,30 @@ Example:: | 7 | 8 | +----------------------------+-------------------------------+ +WEEKDAY +_______ + +Description +>>>>>>>>>>> + +Usage: weekday(date) returns the weekday index for date (0 = Monday, 1 = Tuesday, …, 6 = Sunday). + +It is similar to the `dayofweek`_ function, but returns different indexes for each day. + +Argument type: STRING/DATE/DATETIME/TIMESTAMP + +Return type: INTEGER + +Example:: + + os> SELECT weekday('2020-08-26'), weekday('2020-08-26') + fetched rows / total rows = 1/1 + +---------------------------------------------------+ + | weekday('2020-08-26') | weekday('2020-08-27') | + |-------------------------+-------------------------| + | 2 | 3 | + +-------------------------+-------------------------+ + WEEK_OF_YEAR ------------ From 2c266ec93bc710f98f0d76e7b1edc88df76e1303 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 24 Feb 2023 08:27:08 -0800 Subject: [PATCH 04/11] Fixed IT Test Signed-off-by: GabeFernandez310 --- .../test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java index 661f1db296..1c3b5b2a2d 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java @@ -934,7 +934,7 @@ public void testWeek() throws IOException { @Test public void testWeekday() throws IOException { - JSONObject result = executeQuery(String.format("SELECT weekday(datetime0) FROM %s LIMIT 3")); + JSONObject result = executeQuery(String.format("SELECT weekday(datetime0) FROM %s LIMIT 3", TEST_INDEX_CALCS)); verifyDataRows(result, rows(3), rows(1), rows(2)); } From 7b2e8f75b43563b4f49c6e615d97a0c421ed5ef5 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 24 Feb 2023 10:53:54 -0800 Subject: [PATCH 05/11] Adjusted IT test Signed-off-by: GabeFernandez310 --- .../test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java index 1c3b5b2a2d..950678a2ca 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java @@ -934,7 +934,7 @@ public void testWeek() throws IOException { @Test public void testWeekday() throws IOException { - JSONObject result = executeQuery(String.format("SELECT weekday(datetime0) FROM %s LIMIT 3", TEST_INDEX_CALCS)); + JSONObject result = executeQuery(String.format("SELECT weekday(date0) FROM %s LIMIT 3", TEST_INDEX_CALCS)); verifyDataRows(result, rows(3), rows(1), rows(2)); } From 9c28bb8b6ca927871aec10e53c0b6378e6b0c276 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 24 Feb 2023 11:36:02 -0800 Subject: [PATCH 06/11] Fixed Implementation for Time And Unit Tests Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunction.java | 12 +++++++++++- .../expression/datetime/DateTimeFunctionTest.java | 8 ++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index 1eb1887c4c..3f1d27d3f9 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java @@ -892,7 +892,7 @@ private DefaultFunctionResolver week(BuiltinFunctionName week) { private DefaultFunctionResolver weekday() { return define(BuiltinFunctionName.WEEKDAY.getName(), implWithProperties(nullMissingHandlingWithProperties( - (functionProperties, arg) -> DateTimeFunction.dayOfWeekToday( + (functionProperties, arg) -> DateTimeFunction.weekdayToday( functionProperties.getQueryStartClock())), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATETIME), @@ -1660,6 +1660,16 @@ private ExprValue exprWeekday(ExprValue date) { return new ExprIntegerValue(date.dateValue().getDayOfWeek().getValue() - 1); } + /** + * weekday implementation for ExprValue when passing in an arguemt of type TIME. + * + * @param clock Current clock taken from function properties + * @return ExprValue. + */ + private ExprValue weekdayToday(Clock clock) { + return new ExprIntegerValue(formatNow(clock).getDayOfWeek().getValue() - 1); + } + private ExprValue unixTimeStamp(Clock clock) { return new ExprLongValue(Instant.now(clock).getEpochSecond()); } diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java index 64397d695f..ad9f90d399 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java @@ -1555,7 +1555,7 @@ public void testWeekdayWithTimeType() { () -> assertEquals(INTEGER, eval(expression).type()), () -> assertEquals(( LocalDate.now( - functionProperties.getQueryStartClock()).getDayOfWeek().getValue() % 7), + functionProperties.getQueryStartClock()).getDayOfWeek().getValue() - 1), eval(expression).integerValue()), () -> assertEquals("weekday(TIME '12:23:34')", expression.toString()) ); @@ -1576,15 +1576,15 @@ public void weekdayLeapYear() { //Feb. 29 of a leap year () -> weekdayQuery(DSL.weekday( functionProperties, - DSL.literal("2020-02-29")), 6, "weekday(\"2020-02-29\")"), + DSL.literal("2020-02-29")), 5, "weekday(\"2020-02-29\")"), //day after Feb. 29 of a leap year () -> weekdayQuery(DSL.weekday( functionProperties, - DSL.literal("2020-03-01")), 0, "weekday(\"2020-03-01\")"), + DSL.literal("2020-03-01")), 6, "weekday(\"2020-03-01\")"), //Feb. 28 of a non-leap year () -> weekdayQuery(DSL.weekday( functionProperties, - DSL.literal("2021-02-28")), 0, "weekday(\"2021-02-28\")"), + DSL.literal("2021-02-28")), 6, "weekday(\"2021-02-28\")"), //Feb. 29 of a non-leap year () -> assertThrows( SemanticCheckException.class, () -> testInvalidWeekday("2021-02-29")) From a47d630183cf2ee53f08f0d0ad304d096854b10a Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Tue, 28 Feb 2023 08:51:29 -0800 Subject: [PATCH 07/11] Addressed PR Comments Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 115 -------------- .../sql/expression/datetime/WeekdayTest.java | 146 ++++++++++++++++++ docs/user/dql/functions.rst | 4 +- 3 files changed, 148 insertions(+), 117 deletions(-) create mode 100644 core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java index ad9f90d399..fdb029ca90 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java @@ -1498,121 +1498,6 @@ private void weekQuery(String date, int mode, int expectedResult) { assertEquals(integerValue(expectedResult), eval(expression)); } - private void weekdayQuery( - FunctionExpression dateExpression, - int dayOfWeek, - String testExpr) { - - assertAll( - () -> assertEquals(INTEGER, dateExpression.type()), - () -> assertEquals(integerValue(dayOfWeek), eval(dateExpression)), - () -> assertEquals(testExpr, dateExpression.toString()) - ); - } - - private static Stream getTestDataForWeekday() { - return Stream.of( - Arguments.of( - DSL.literal(new ExprDateValue("2020-08-07")), - 4, - "weekday(DATE '2020-08-07')"), - Arguments.of( - DSL.literal(new ExprDateValue("2020-08-09")), - 6, - "weekday(DATE '2020-08-09')"), - Arguments.of( - DSL.literal("2020-08-09"), - 6, - "weekday(\"2020-08-09\")"), - Arguments.of( - DSL.literal("2020-08-09 01:02:03"), - 6, - "weekday(\"2020-08-09 01:02:03\")") - ); - } - - @MethodSource("getTestDataForWeekday") - @ParameterizedTest - public void weekday(LiteralExpression arg, int expectedInt, String expectedString) { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - - FunctionExpression expression = DSL.weekday( - functionProperties, - arg); - - weekdayQuery(expression, expectedInt, expectedString); - } - - @Test - public void testWeekdayWithTimeType() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.weekday( - functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); - - assertAll( - () -> assertEquals(INTEGER, eval(expression).type()), - () -> assertEquals(( - LocalDate.now( - functionProperties.getQueryStartClock()).getDayOfWeek().getValue() - 1), - eval(expression).integerValue()), - () -> assertEquals("weekday(TIME '12:23:34')", expression.toString()) - ); - } - - private void testInvalidWeekday(String date) { - FunctionExpression expression = DSL.weekday( - functionProperties, DSL.literal(new ExprDateValue(date))); - eval(expression); - } - - @Test - public void weekdayLeapYear() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - - assertAll( - //Feb. 29 of a leap year - () -> weekdayQuery(DSL.weekday( - functionProperties, - DSL.literal("2020-02-29")), 5, "weekday(\"2020-02-29\")"), - //day after Feb. 29 of a leap year - () -> weekdayQuery(DSL.weekday( - functionProperties, - DSL.literal("2020-03-01")), 6, "weekday(\"2020-03-01\")"), - //Feb. 28 of a non-leap year - () -> weekdayQuery(DSL.weekday( - functionProperties, - DSL.literal("2021-02-28")), 6, "weekday(\"2021-02-28\")"), - //Feb. 29 of a non-leap year - () -> assertThrows( - SemanticCheckException.class, () -> testInvalidWeekday("2021-02-29")) - ); - } - - @Test - public void weekdayInvalidArgument() { - when(nullRef.type()).thenReturn(DATE); - when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.weekday(functionProperties, nullRef))); - assertEquals(missingValue(), eval(DSL.weekday(functionProperties, missingRef))); - - assertAll( - //40th day of the month - () -> assertThrows(SemanticCheckException.class, - () -> testInvalidWeekday("2021-02-40")), - - //13th month of the year - () -> assertThrows(SemanticCheckException.class, - () -> testInvalidWeekday("2021-13-29")), - - //incorrect format - () -> assertThrows(SemanticCheckException.class, - () -> testInvalidWeekday("asdfasdf")) - ); - } - private void weekOfYearUnderscoresQuery(String date, int mode, int expectedResult) { FunctionExpression expression = DSL .week_of_year( diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java new file mode 100644 index 0000000000..c03b431d0d --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java @@ -0,0 +1,146 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + + +package org.opensearch.sql.expression.datetime; + +import java.time.LocalDate; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.opensearch.sql.data.model.ExprDateValue; +import org.opensearch.sql.data.model.ExprTimeValue; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.exception.SemanticCheckException; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.Expression; +import org.opensearch.sql.expression.ExpressionTestBase; +import org.opensearch.sql.expression.FunctionExpression; +import org.opensearch.sql.expression.LiteralExpression; +import org.opensearch.sql.expression.env.Environment; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; +import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; + +@ExtendWith(MockitoExtension.class) +class WeekdayTest extends ExpressionTestBase { + + @Mock + Environment env; + + private void weekdayQuery( + FunctionExpression dateExpression, + int dayOfWeek, + String testExpr) { + + assertAll( + () -> assertEquals(INTEGER, dateExpression.type()), + () -> assertEquals(integerValue(dayOfWeek), eval(dateExpression)), + () -> assertEquals(testExpr, dateExpression.toString()) + ); + } + + private static Stream getTestDataForWeekday() { + return Stream.of( + Arguments.of( + DSL.literal(new ExprDateValue("2020-08-07")), + 4, + "weekday(DATE '2020-08-07')"), + Arguments.of( + DSL.literal(new ExprDateValue("2020-08-09")), + 6, + "weekday(DATE '2020-08-09')"), + Arguments.of( + DSL.literal("2020-08-09"), + 6, + "weekday(\"2020-08-09\")"), + Arguments.of( + DSL.literal("2020-08-09 01:02:03"), + 6, + "weekday(\"2020-08-09 01:02:03\")") + ); + } + + @MethodSource("getTestDataForWeekday") + @ParameterizedTest + public void weekday(LiteralExpression arg, int expectedInt, String expectedString) { + FunctionExpression expression = DSL.weekday( + functionProperties, + arg); + + weekdayQuery(expression, expectedInt, expectedString); + } + + @Test + public void testWeekdayWithTimeType() { + FunctionExpression expression = DSL.weekday( + functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); + + assertAll( + () -> assertEquals(INTEGER, eval(expression).type()), + () -> assertEquals(( + LocalDate.now( + functionProperties.getQueryStartClock()).getDayOfWeek().getValue() - 1), + eval(expression).integerValue()), + () -> assertEquals("weekday(TIME '12:23:34')", expression.toString()) + ); + } + + private void testInvalidWeekday(String date) { + FunctionExpression expression = DSL.weekday( + functionProperties, DSL.literal(new ExprDateValue(date))); + eval(expression); + } + + @Test + public void weekdayLeapYear() { + assertAll( + //Feb. 29 of a leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2020-02-29")), 5, "weekday(\"2020-02-29\")"), + //day after Feb. 29 of a leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2020-03-01")), 6, "weekday(\"2020-03-01\")"), + //Feb. 28 of a non-leap year + () -> weekdayQuery(DSL.weekday( + functionProperties, + DSL.literal("2021-02-28")), 6, "weekday(\"2021-02-28\")"), + //Feb. 29 of a non-leap year + () -> assertThrows( + SemanticCheckException.class, () -> testInvalidWeekday("2021-02-29")) + ); + } + + @Test + public void weekdayInvalidArgument() { + assertAll( + //40th day of the month + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("2021-02-40")), + + //13th month of the year + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("2021-13-29")), + + //incorrect format + () -> assertThrows(SemanticCheckException.class, + () -> testInvalidWeekday("asdfasdf")) + ); + } + + private ExprValue eval(Expression expression) { + return expression.valueOf(env); + } +} diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index ed62af85a0..ed9bfc3240 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -2633,11 +2633,11 @@ _______ Description >>>>>>>>>>> -Usage: weekday(date) returns the weekday index for date (0 = Monday, 1 = Tuesday, …, 6 = Sunday). +Usage: weekday(date) returns the weekday index for date (0 = Monday, 1 = Tuesday, ..., 6 = Sunday). It is similar to the `dayofweek`_ function, but returns different indexes for each day. -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP Return type: INTEGER From 2900c28035b3dc63fc4f13e8951b06636ac8844b Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 1 Mar 2023 08:10:53 -0800 Subject: [PATCH 08/11] Cleaned WeekdayTest File Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/WeekdayTest.java | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java b/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java index c03b431d0d..4b97639996 100644 --- a/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/datetime/WeekdayTest.java @@ -6,15 +6,18 @@ package org.opensearch.sql.expression.datetime; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; +import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; + import java.time.LocalDate; import java.util.stream.Stream; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; import org.opensearch.sql.data.model.ExprDateValue; import org.opensearch.sql.data.model.ExprTimeValue; import org.opensearch.sql.data.model.ExprValue; @@ -24,20 +27,10 @@ import org.opensearch.sql.expression.ExpressionTestBase; import org.opensearch.sql.expression.FunctionExpression; import org.opensearch.sql.expression.LiteralExpression; -import org.opensearch.sql.expression.env.Environment; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.opensearch.sql.data.model.ExprValueUtils.integerValue; -import static org.opensearch.sql.data.type.ExprCoreType.INTEGER; -@ExtendWith(MockitoExtension.class) class WeekdayTest extends ExpressionTestBase { - @Mock - Environment env; - private void weekdayQuery( FunctionExpression dateExpression, int dayOfWeek, @@ -141,6 +134,6 @@ public void weekdayInvalidArgument() { } private ExprValue eval(Expression expression) { - return expression.valueOf(env); + return expression.valueOf(); } } From 1f719ac071aef51fd830d194f9304feb58dd6d91 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 1 Mar 2023 08:28:53 -0800 Subject: [PATCH 09/11] Fixed Docs Signed-off-by: GabeFernandez310 --- docs/user/dql/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index ed9bfc3240..b064799dbd 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -2643,7 +2643,7 @@ Return type: INTEGER Example:: - os> SELECT weekday('2020-08-26'), weekday('2020-08-26') + os> SELECT weekday('2020-08-26'), weekday('2020-08-27') fetched rows / total rows = 1/1 +---------------------------------------------------+ | weekday('2020-08-26') | weekday('2020-08-27') | From dc537b2144c08723bcbb3a6e35ebf00f9d36f74d Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Tue, 7 Mar 2023 09:11:45 -0800 Subject: [PATCH 10/11] Fixed Doctest Signed-off-by: GabeFernandez310 --- docs/user/dql/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index b064799dbd..23c9a8e29c 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -2645,7 +2645,7 @@ Example:: os> SELECT weekday('2020-08-26'), weekday('2020-08-27') fetched rows / total rows = 1/1 - +---------------------------------------------------+ + +-------------------------+-------------------------+ | weekday('2020-08-26') | weekday('2020-08-27') | |-------------------------+-------------------------| | 2 | 3 | From 87c3f9ee724168af6276256415d875fd8511781a Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 8 Mar 2023 08:50:58 -0800 Subject: [PATCH 11/11] Removed Unneeded Function Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunction.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java index 3f1d27d3f9..05cd35e25e 100644 --- a/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java @@ -892,8 +892,9 @@ private DefaultFunctionResolver week(BuiltinFunctionName week) { private DefaultFunctionResolver weekday() { return define(BuiltinFunctionName.WEEKDAY.getName(), implWithProperties(nullMissingHandlingWithProperties( - (functionProperties, arg) -> DateTimeFunction.weekdayToday( - functionProperties.getQueryStartClock())), INTEGER, TIME), + (functionProperties, arg) -> new ExprIntegerValue( + formatNow(functionProperties.getQueryStartClock()).getDayOfWeek().getValue() - 1)), + INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekday), INTEGER, TIMESTAMP), @@ -1660,16 +1661,6 @@ private ExprValue exprWeekday(ExprValue date) { return new ExprIntegerValue(date.dateValue().getDayOfWeek().getValue() - 1); } - /** - * weekday implementation for ExprValue when passing in an arguemt of type TIME. - * - * @param clock Current clock taken from function properties - * @return ExprValue. - */ - private ExprValue weekdayToday(Clock clock) { - return new ExprIntegerValue(formatNow(clock).getDayOfWeek().getValue() - 1); - } - private ExprValue unixTimeStamp(Clock clock) { return new ExprLongValue(Instant.now(clock).getEpochSecond()); }