From 847b9044f1dbada08b455360d9f08bb97b0561fe Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Tue, 27 Dec 2022 08:55:49 -0800 Subject: [PATCH 01/20] Changed Location Of *_of_year Functions In Parser Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunction.java | 1 + sql/src/main/antlr/OpenSearchSQLParser.g4 | 6 +++--- 2 files changed, 4 insertions(+), 3 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 ed8063d8ff0..112e92f8a9f 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 @@ -371,6 +371,7 @@ private DefaultFunctionResolver dayOfYear(BuiltinFunctionName dayOfYear) { impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, TIMESTAMP), + impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, STRING) ); } diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index 47a43362eaa..48cea16b9a0 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -244,14 +244,11 @@ datetimeConstantLiteral : CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP - | DAY_OF_YEAR | LOCALTIME | LOCALTIMESTAMP - | MONTH_OF_YEAR | UTC_TIMESTAMP | UTC_DATE | UTC_TIME - | WEEK_OF_YEAR ; intervalLiteral @@ -428,6 +425,9 @@ dateTimeFunctionName | DAYOFMONTH | DAYOFWEEK | DAYOFYEAR + | DAY_OF_MONTH + | DAY_OF_WEEK + | DAY_OF_YEAR | FROM_DAYS | FROM_UNIXTIME | HOUR From cf3ef865f8ad15594194e3405b4a595cddc48c17 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Tue, 27 Dec 2022 11:58:09 -0800 Subject: [PATCH 02/20] Added Implementation Signed-off-by: GabeFernandez310 --- .../expression/datetime/DateTimeFunction.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 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 112e92f8a9f..6fcd585252e 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 @@ -368,10 +368,11 @@ private DefaultFunctionResolver dayOfWeek() { */ private DefaultFunctionResolver dayOfYear(BuiltinFunctionName dayOfYear) { return define(dayOfYear.getName(), + implWithProperties((functionProperties, arg) -> DateTimeFunction.dayOfYearToday( + functionProperties.getQueryStartClock()), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, TIMESTAMP), - impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, STRING) ); } @@ -442,6 +443,8 @@ private DefaultFunctionResolver minute() { */ private DefaultFunctionResolver month(BuiltinFunctionName month) { return define(month.getName(), + implWithProperties((functionProperties, arg) -> DateTimeFunction.monthOfYearToday( + functionProperties.getQueryStartClock()), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, TIMESTAMP), @@ -606,10 +609,12 @@ private DefaultFunctionResolver week(BuiltinFunctionName week) { impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), + impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, STRING), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATE, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATETIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, TIMESTAMP, INTEGER), + impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, STRING, INTEGER) ); } @@ -647,6 +652,10 @@ private DefaultFunctionResolver date_format() { ); } + private ExprValue dayOfYearToday(Clock clock) { + return new ExprIntegerValue((formatNow(clock).getDayOfYear())); + } + /** * ADDDATE function implementation for ExprValue. * @@ -1140,12 +1149,19 @@ private ExprValue exprToDays(ExprValue date) { /** * Week for date implementation for ExprValue. * - * @param date ExprValue of Date/Datetime/Timestamp/String type. + * @param expr ExprValue of Date/Datetime/Time/Timestamp/String type. * @param mode ExprValue of Integer type. */ - private ExprValue exprWeek(ExprValue date, ExprValue mode) { - return new ExprIntegerValue( - CalendarLookup.getWeekNumber(mode.integerValue(), date.dateValue())); + private ExprValue exprWeek(ExprValue expr, ExprValue mode) { + switch ((ExprCoreType)expr.type()){ + case TIME: + return new ExprIntegerValue( + CalendarLookup.getWeekNumber(mode.integerValue(), + formatNow(Clock.systemDefaultZone()).toLocalDate())); + default: + return new ExprIntegerValue( + CalendarLookup.getWeekNumber(mode.integerValue(), expr.dateValue())); + } } private ExprValue unixTimeStamp(Clock clock) { @@ -1225,11 +1241,11 @@ private Double unixTimeStampOfImpl(ExprValue value) { * Week for date implementation for ExprValue. * When mode is not specified default value mode 0 is used for default_week_format. * - * @param date ExprValue of Date/Datetime/Timestamp/String type. + * @param expr ExprValue of Date/Datetime/Time/Timestamp/String type. * @return ExprValue. */ - private ExprValue exprWeekWithoutMode(ExprValue date) { - return exprWeek(date, new ExprIntegerValue(0)); + private ExprValue exprWeekWithoutMode(ExprValue expr) { + return exprWeek(expr, new ExprIntegerValue(0)); } /** @@ -1242,6 +1258,10 @@ private ExprValue exprYear(ExprValue date) { return new ExprIntegerValue(date.dateValue().getYear()); } + private ExprValue monthOfYearToday(Clock clock) { + return new ExprIntegerValue((formatNow(clock).getMonthValue())); + } + private LocalDateTime formatNow(Clock clock) { return formatNow(clock, 0); } From a7b55c9f8c24c581dfae43978a42f12f24ad7e34 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 28 Dec 2022 09:09:38 -0800 Subject: [PATCH 03/20] Fixed Parser And Added Tests Signed-off-by: GabeFernandez310 --- .../org/opensearch/sql/expression/DSL.java | 15 +- .../datetime/DateTimeFunctionTest.java | 142 +++++++++++++++--- sql/src/main/antlr/OpenSearchSQLParser.g4 | 4 +- 3 files changed, 129 insertions(+), 32 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 26a15c0ee47..c2ac3a2b058 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -334,8 +334,9 @@ public static FunctionExpression dayofyear(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.DAYOFYEAR, expressions); } - public static FunctionExpression day_of_year(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.DAY_OF_YEAR, expressions); + public static FunctionExpression day_of_year( + FunctionProperties functionProperties, Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.DAY_OF_YEAR, expressions); } public static FunctionExpression from_days(Expression... expressions) { @@ -358,8 +359,9 @@ public static FunctionExpression month(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.MONTH, expressions); } - public static FunctionExpression month_of_year(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.MONTH_OF_YEAR, expressions); + public static FunctionExpression month_of_year( + FunctionProperties functionProperties, Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.MONTH_OF_YEAR, expressions); } public static FunctionExpression monthname(Expression... expressions) { @@ -402,8 +404,9 @@ public static FunctionExpression week(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.WEEK, expressions); } - public static FunctionExpression week_of_year(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.WEEK_OF_YEAR, expressions); + public static FunctionExpression week_of_year( + FunctionProperties functionProperties, Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.WEEK_OF_YEAR, expressions); } public static FunctionExpression year(Expression... expressions) { 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 092b64d5d75..8164ab3fe9a 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 @@ -6,6 +6,7 @@ package org.opensearch.sql.expression.datetime; +import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -481,8 +482,25 @@ public void dayOfYear() { assertEquals(integerValue(220), eval(expression)); } + @Test + public void testDayOfYearWithTimeType() { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + FunctionExpression expression = DSL.day_of_year( + functionProperties, + DSL.literal(new ExprTimeValue("12:23:34"))); + + assertEquals(INTEGER, eval(expression).type()); + assertEquals(LocalDate.now( + functionProperties.getQueryStartClock()).getDayOfYear(), + eval(expression).integerValue()); + assertEquals("day_of_year(TIME '12:23:34')", expression.toString()); + } + public void testDayOfYearWithUnderscores(String date, int dayOfYear) { - FunctionExpression expression = DSL.day_of_year(DSL.literal(new ExprDateValue(date))); + FunctionExpression expression = DSL.day_of_year( + functionProperties, + DSL.literal(new ExprDateValue(date))); assertEquals(INTEGER, expression.type()); assertEquals(integerValue(dayOfYear), eval(expression)); } @@ -492,9 +510,15 @@ public void dayOfYearWithUnderscoresDifferentArgumentFormats() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression1 = DSL.day_of_year(DSL.literal(new ExprDateValue("2020-08-07"))); - FunctionExpression expression2 = DSL.day_of_year(DSL.literal("2020-08-07")); - FunctionExpression expression3 = DSL.day_of_year(DSL.literal("2020-08-07 01:02:03")); + FunctionExpression expression1 = DSL.day_of_year( + functionProperties, + DSL.literal(new ExprDateValue("2020-08-07"))); + FunctionExpression expression2 = DSL.day_of_year( + functionProperties, + DSL.literal("2020-08-07")); + FunctionExpression expression3 = DSL.day_of_year( + functionProperties, + DSL.literal("2020-08-07 01:02:03")); assertAll( () -> testDayOfYearWithUnderscores("2020-08-07", 220), @@ -549,7 +573,9 @@ public void dayOfYearWithUnderscoresLeapYear() { } public void testInvalidDayOfYear(String date) { - FunctionExpression expression = DSL.day_of_year(DSL.literal(new ExprDateValue(date))); + FunctionExpression expression = DSL.day_of_year( + functionProperties, + DSL.literal(new ExprDateValue(date))); eval(expression); } @@ -557,8 +583,12 @@ public void testInvalidDayOfYear(String date) { public void invalidDayOfYearArgument() { when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.day_of_year(nullRef))); - assertEquals(missingValue(), eval(DSL.day_of_year(missingRef))); + assertEquals(nullValue(), eval(DSL.day_of_year( + functionProperties, + nullRef))); + assertEquals(missingValue(), eval(DSL.day_of_year( + functionProperties, + missingRef))); //29th of Feb non-leapyear assertThrows(SemanticCheckException.class, () -> testInvalidDayOfYear("2019-02-29")); @@ -714,16 +744,37 @@ public void month() { assertEquals(integerValue(8), eval(expression)); } + @Test + public void testMonthOfYearWithTimeType() { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + FunctionExpression expression = DSL.month_of_year( + functionProperties, + DSL.literal(new ExprTimeValue("12:23:34"))); + + assertEquals(INTEGER, eval(expression).type()); + assertEquals(LocalDate.now( + functionProperties.getQueryStartClock()).getMonthValue(), + eval(expression).integerValue()); + assertEquals("month_of_year(TIME '12:23:34')", expression.toString()); + } + public void testInvalidDates(String date) throws SemanticCheckException { - FunctionExpression expression = DSL.month_of_year(DSL.literal(new ExprDateValue(date))); + FunctionExpression expression = DSL.month_of_year( + functionProperties, + DSL.literal(new ExprDateValue(date))); eval(expression); } @Test void monthOfYearInvalidDates() { when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.month_of_year(nullRef))); - assertEquals(missingValue(), eval(DSL.month_of_year(missingRef))); + assertEquals(nullValue(), eval(DSL.month_of_year( + functionProperties, + nullRef))); + assertEquals(missingValue(), eval(DSL.month_of_year( + functionProperties, + missingRef))); assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-01-50")); assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-02-29")); @@ -736,17 +787,23 @@ public void monthOfYearAlternateArgumentSyntaxes() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.month_of_year(DSL.literal(new ExprDateValue("2020-08-07"))); + FunctionExpression expression = DSL.month_of_year( + functionProperties, + DSL.literal(new ExprDateValue("2020-08-07"))); assertEquals(INTEGER, expression.type()); assertEquals("month_of_year(DATE '2020-08-07')", expression.toString()); assertEquals(integerValue(8), eval(expression)); - expression = DSL.month_of_year(DSL.literal("2020-08-07")); + expression = DSL.month_of_year( + functionProperties, + DSL.literal("2020-08-07")); assertEquals(INTEGER, expression.type()); assertEquals("month_of_year(\"2020-08-07\")", expression.toString()); assertEquals(integerValue(8), eval(expression)); - expression = DSL.month_of_year(DSL.literal("2020-08-07 01:02:03")); + expression = DSL.month_of_year( + functionProperties, + DSL.literal("2020-08-07 01:02:03")); assertEquals(INTEGER, expression.type()); assertEquals("month_of_year(\"2020-08-07 01:02:03\")", expression.toString()); assertEquals(integerValue(8), eval(expression)); @@ -1058,6 +1115,21 @@ public void week() { testWeek("1999-12-31", 0, 52); } + @Test + public void testWeekOfYearWithTimeType() { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + FunctionExpression expression = DSL.week_of_year( + functionProperties, + DSL.literal(new ExprTimeValue("12:23:34"))); + + assertEquals(INTEGER, eval(expression).type()); + assertEquals(LocalDate.now( + functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR), + eval(expression).integerValue()); + assertEquals("week_of_year(TIME '12:23:34')", expression.toString()); + } + @Test public void modeInUnsupportedFormat() { testNullMissingWeek(DATE); @@ -1078,7 +1150,9 @@ public void modeInUnsupportedFormat() { private void testWeekOfYear(String date, int mode, int expectedResult) { FunctionExpression expression = DSL - .week_of_year(DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); + .week_of_year( + functionProperties, + DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); assertEquals(INTEGER, expression.type()); assertEquals(String.format("week_of_year(DATE '%s', %d)", date, mode), expression.toString()); assertEquals(integerValue(expectedResult), eval(expression)); @@ -1087,8 +1161,12 @@ private void testWeekOfYear(String date, int mode, int expectedResult) { private void testNullMissingWeekOfYear(ExprCoreType date) { when(nullRef.type()).thenReturn(date); when(missingRef.type()).thenReturn(date); - assertEquals(nullValue(), eval(DSL.week_of_year(nullRef))); - assertEquals(missingValue(), eval(DSL.week_of_year(missingRef))); + assertEquals(nullValue(), eval(DSL.week_of_year( + functionProperties, + nullRef))); + assertEquals(missingValue(), eval(DSL.week_of_year( + functionProperties, + missingRef))); } @Test @@ -1100,12 +1178,18 @@ public void testInvalidWeekOfYear() { when(nullRef.type()).thenReturn(INTEGER); when(missingRef.type()).thenReturn(INTEGER); - assertEquals(nullValue(), eval(DSL.week_of_year(DSL.literal("2019-01-05"), nullRef))); - assertEquals(missingValue(), eval(DSL.week_of_year(DSL.literal("2019-01-05"), missingRef))); + assertEquals(nullValue(), eval(DSL.week_of_year( + functionProperties, + DSL.literal("2019-01-05"), nullRef))); + assertEquals(missingValue(), eval(DSL.week_of_year( + functionProperties, + DSL.literal("2019-01-05"), missingRef))); when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(INTEGER); - assertEquals(missingValue(), eval(DSL.week_of_year(nullRef, missingRef))); + assertEquals(missingValue(), eval(DSL.week_of_year( + functionProperties, + nullRef, missingRef))); //test invalid month assertThrows(SemanticCheckException.class, () -> testWeekOfYear("2019-13-05 01:02:03", 0, 0)); @@ -1121,17 +1205,23 @@ public void testWeekOfYearAlternateArgumentFormats() { lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); FunctionExpression expression = DSL - .week_of_year(DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); + .week_of_year( + functionProperties, + DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals("week_of_year(TIMESTAMP '2019-01-05 01:02:03')", expression.toString()); assertEquals(integerValue(0), eval(expression)); - expression = DSL.week_of_year(DSL.literal("2019-01-05")); + expression = DSL.week_of_year( + functionProperties, + DSL.literal("2019-01-05")); assertEquals(INTEGER, expression.type()); assertEquals("week_of_year(\"2019-01-05\")", expression.toString()); assertEquals(integerValue(0), eval(expression)); - expression = DSL.week_of_year(DSL.literal("2019-01-05 00:01:00")); + expression = DSL.week_of_year( + functionProperties, + DSL.literal("2019-01-05 00:01:00")); assertEquals(INTEGER, expression.type()); assertEquals("week_of_year(\"2019-01-05 00:01:00\")", expression.toString()); assertEquals(integerValue(0), eval(expression)); @@ -1181,14 +1271,18 @@ public void weekOfYearModeInUnsupportedFormat() { testNullMissingWeekOfYear(DATE); FunctionExpression expression1 = DSL - .week_of_year(DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); + .week_of_year( + functionProperties, + DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); SemanticCheckException exception = assertThrows(SemanticCheckException.class, () -> eval(expression1)); assertEquals("mode:8 is invalid, please use mode value between 0-7", exception.getMessage()); FunctionExpression expression2 = DSL - .week_of_year(DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(-1)); + .week_of_year( + functionProperties, + DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(-1)); exception = assertThrows(SemanticCheckException.class, () -> eval(expression2)); assertEquals("mode:-1 is invalid, please use mode value between 0-7", exception.getMessage()); diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index 48cea16b9a0..e4353e9d84c 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -425,8 +425,6 @@ dateTimeFunctionName | DAYOFMONTH | DAYOFWEEK | DAYOFYEAR - | DAY_OF_MONTH - | DAY_OF_WEEK | DAY_OF_YEAR | FROM_DAYS | FROM_UNIXTIME @@ -437,6 +435,7 @@ dateTimeFunctionName | MINUTE | MONTH | MONTHNAME + | MONTH_OF_YEAR | NOW | PERIOD_ADD | PERIOD_DIFF @@ -450,6 +449,7 @@ dateTimeFunctionName | TO_DAYS | UNIX_TIMESTAMP | WEEK + | WEEK_OF_YEAR | YEAR ; From e787dff40f293230b6d47fc0723175d24ff7a16b Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 28 Dec 2022 09:40:22 -0800 Subject: [PATCH 04/20] Fixed Checkstyle Issue Signed-off-by: GabeFernandez310 --- .../opensearch/sql/expression/datetime/DateTimeFunction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6fcd585252e..d06db6df56c 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 @@ -1153,7 +1153,7 @@ private ExprValue exprToDays(ExprValue date) { * @param mode ExprValue of Integer type. */ private ExprValue exprWeek(ExprValue expr, ExprValue mode) { - switch ((ExprCoreType)expr.type()){ + switch ((ExprCoreType)expr.type()) { case TIME: return new ExprIntegerValue( CalendarLookup.getWeekNumber(mode.integerValue(), From 9d883618255172bceb965aefdf0d417ee4b05273 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 28 Dec 2022 10:59:31 -0800 Subject: [PATCH 05/20] Added Documentation Signed-off-by: GabeFernandez310 --- docs/user/dql/functions.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 733a555c81c..4d1a176252f 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -1457,9 +1457,10 @@ Description >>>>>>>>>>> Usage: dayofyear(date) returns the day of the year for date, in the range 1 to 366. +If an argument of type `TIME` is given, the function will use the current date to calculate an output. The function `day_of_year`_ is also provided as an alias. -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP Return type: INTEGER @@ -1496,9 +1497,10 @@ DAY_OF_YEAR Description >>>>>>>>>>> +If an argument of type `TIME` is given, the function will use the current date to calculate an output. This function is an alias to the `dayofyear`_ function -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP Return type: INTEGER @@ -1770,9 +1772,10 @@ Description >>>>>>>>>>> Usage: month(date) returns the month for date, in the range 1 to 12 for January to December. The dates with value 0 such as '0000-00-00' or '2008-00-00' are invalid. -The function month_of_year is also provided as an alias +If an argument of type `TIME` is given, the function will use the current date to calculate an output. +The function month_of_year is also provided as an alias. -Argument type: STRING/DATE/DATETIME/TIMESTAMP +Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP Return type: INTEGER @@ -2194,6 +2197,7 @@ Description >>>>>>>>>>> Usage: week(date[, mode]) returns the week number for date. If the mode argument is omitted, the default mode 0 is used. +If an argument of type `TIME` is given, the function will use the current date to calculate an output. The function `week_of_year` is also provided as an alias. .. list-table:: The following table describes how the mode argument works. @@ -2237,7 +2241,7 @@ The function `week_of_year` is also provided as an alias. - 1-53 - with a Monday in this year -Argument type: DATE/DATETIME/TIMESTAMP/STRING +Argument type: DATE/DATETIME/TIME/TIMESTAMP/STRING Return type: INTEGER @@ -2258,8 +2262,9 @@ Description >>>>>>>>>>> The week_of_year function is a synonym for the `week`_ function. +If an argument of type `TIME` is given, the function will use the current date to calculate an output. -Argument type: DATE/DATETIME/TIMESTAMP/STRING +Argument type: DATE/DATETIME/TIME/TIMESTAMP/STRING Return type: INTEGER From 2b01f8155e5c88efc080f6bd8d4aef45d3542611 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 29 Dec 2022 11:32:04 -0800 Subject: [PATCH 06/20] Fixed Implementation For TIME Type For Week_Of_Year Function Signed-off-by: GabeFernandez310 --- .../org/opensearch/sql/expression/DSL.java | 5 +- .../expression/datetime/DateTimeFunction.java | 21 ++++----- .../sql/expression/function/FunctionDSL.java | 46 +++++++++++++++++++ .../datetime/DateTimeFunctionTest.java | 40 ++++++++++------ 4 files changed, 86 insertions(+), 26 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 c2ac3a2b058..2547ed88478 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -400,8 +400,9 @@ public static FunctionExpression to_days(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.TO_DAYS, expressions); } - public static FunctionExpression week(Expression... expressions) { - return compile(FunctionProperties.None, BuiltinFunctionName.WEEK, expressions); + public static FunctionExpression week( + FunctionProperties functionProperties, Expression... expressions) { + return compile(functionProperties, BuiltinFunctionName.WEEK, expressions); } public static FunctionExpression week_of_year( 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 d06db6df56c..f1e82592916 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 @@ -606,15 +606,17 @@ private DefaultFunctionResolver utc_timestamp() { */ private DefaultFunctionResolver week(BuiltinFunctionName week) { return define(week.getName(), + implWithProperties((functionProperties, arg) -> DateTimeFunction.weekOfYearToday(new ExprIntegerValue(0), + functionProperties.getQueryStartClock()), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), - impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, STRING), + implWithProperties((functionProperties, arg1, arg2) -> DateTimeFunction.weekOfYearToday(arg2, + functionProperties.getQueryStartClock()), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATE, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATETIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, TIMESTAMP, INTEGER), - impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, STRING, INTEGER) ); } @@ -656,6 +658,10 @@ private ExprValue dayOfYearToday(Clock clock) { return new ExprIntegerValue((formatNow(clock).getDayOfYear())); } + private ExprValue weekOfYearToday(ExprValue mode, Clock clock) { + return new ExprIntegerValue(CalendarLookup.getWeekNumber(mode.integerValue(), formatNow(clock).toLocalDate())); + } + /** * ADDDATE function implementation for ExprValue. * @@ -1153,15 +1159,8 @@ private ExprValue exprToDays(ExprValue date) { * @param mode ExprValue of Integer type. */ private ExprValue exprWeek(ExprValue expr, ExprValue mode) { - switch ((ExprCoreType)expr.type()) { - case TIME: - return new ExprIntegerValue( - CalendarLookup.getWeekNumber(mode.integerValue(), - formatNow(Clock.systemDefaultZone()).toLocalDate())); - default: - return new ExprIntegerValue( - CalendarLookup.getWeekNumber(mode.integerValue(), expr.dateValue())); - } + return new ExprIntegerValue( + CalendarLookup.getWeekNumber(mode.integerValue(), expr.dateValue())); } private ExprValue unixTimeStamp(Clock clock) { diff --git a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java index 5b182f76f4f..f257646963d 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java @@ -137,6 +137,52 @@ public String toString() { }; } + /** + * Implementation of a function that takes two argument, returns a value, and + * requires FunctionProperties to complete. + * + * @param function {@link ExprValue} based binary function. + * @param returnType return type. + * @param args1Type first argument type. + * @param args2Type second argument type. + * @return Binary Function Implementation. + */ + public static SerializableFunction> + implWithProperties( + SerializableTriFunction function, + ExprType returnType, + ExprType args1Type, + ExprType args2Type) { + + return functionName -> { + FunctionSignature functionSignature = + new FunctionSignature(functionName, Arrays.asList(args1Type, args2Type)); + FunctionBuilder functionBuilder = + (functionProperties, arguments) -> new FunctionExpression(functionName, arguments) { + @Override + public ExprValue valueOf(Environment valueEnv) { + ExprValue arg1 = arguments.get(0).valueOf(valueEnv); + ExprValue arg2 = arguments.get(1).valueOf(valueEnv); + return function.apply(functionProperties, arg1, arg2); + } + + @Override + public ExprType type() { + return returnType; + } + + @Override + public String toString() { + return String.format("%s(%s)", functionName, + arguments.stream() + .map(Object::toString) + .collect(Collectors.joining(", "))); + } + }; + return Pair.of(functionSignature, functionBuilder); + }; + } + /** * No Arg Function Implementation. * 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 8164ab3fe9a..40938fc2366 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 @@ -1038,7 +1038,7 @@ public void timestamp() { private void testWeek(String date, int mode, int expectedResult) { FunctionExpression expression = DSL - .week(DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); + .week(functionProperties, DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); assertEquals(INTEGER, expression.type()); assertEquals(String.format("week(DATE '%s', %d)", date, mode), expression.toString()); assertEquals(integerValue(expectedResult), eval(expression)); @@ -1047,8 +1047,8 @@ private void testWeek(String date, int mode, int expectedResult) { private void testNullMissingWeek(ExprCoreType date) { when(nullRef.type()).thenReturn(date); when(missingRef.type()).thenReturn(date); - assertEquals(nullValue(), eval(DSL.week(nullRef))); - assertEquals(missingValue(), eval(DSL.week(missingRef))); + assertEquals(nullValue(), eval(DSL.week(functionProperties, nullRef))); + assertEquals(missingValue(), eval(DSL.week(functionProperties, missingRef))); } @Test @@ -1060,25 +1060,31 @@ public void week() { when(nullRef.type()).thenReturn(INTEGER); when(missingRef.type()).thenReturn(INTEGER); - assertEquals(nullValue(), eval(DSL.week(DSL.literal("2019-01-05"), nullRef))); - assertEquals(missingValue(), eval(DSL.week(DSL.literal("2019-01-05"), missingRef))); + assertEquals(nullValue(), eval(DSL.week( + functionProperties, + DSL.literal("2019-01-05"), nullRef))); + assertEquals(missingValue(), eval(DSL.week( + functionProperties, + DSL.literal("2019-01-05"), missingRef))); when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(INTEGER); - assertEquals(missingValue(), eval(DSL.week(nullRef, missingRef))); + assertEquals(missingValue(), eval(DSL.week( + functionProperties, + nullRef, missingRef))); FunctionExpression expression = DSL - .week(DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); + .week(functionProperties, DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); assertEquals(INTEGER, expression.type()); assertEquals("week(TIMESTAMP '2019-01-05 01:02:03')", expression.toString()); assertEquals(integerValue(0), eval(expression)); - expression = DSL.week(DSL.literal("2019-01-05")); + expression = DSL.week(functionProperties, DSL.literal("2019-01-05")); assertEquals(INTEGER, expression.type()); assertEquals("week(\"2019-01-05\")", expression.toString()); assertEquals(integerValue(0), eval(expression)); - expression = DSL.week(DSL.literal("2019-01-05 00:01:00")); + expression = DSL.week(functionProperties, DSL.literal("2019-01-05 00:01:00")); assertEquals(INTEGER, expression.type()); assertEquals("week(\"2019-01-05 00:01:00\")", expression.toString()); assertEquals(integerValue(0), eval(expression)); @@ -1119,10 +1125,18 @@ public void week() { public void testWeekOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.week_of_year( + + FunctionExpression expression = DSL + .week(functionProperties, DSL.literal(new ExprTimeValue("12:23:34")), DSL.literal(0)); + assertEquals(INTEGER, eval(expression).type()); + assertEquals(LocalDate.now( + functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR), + eval(expression).integerValue()); + assertEquals("week(TIME '12:23:34', 0)", expression.toString()); + + expression = DSL.week_of_year( functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))); - assertEquals(INTEGER, eval(expression).type()); assertEquals(LocalDate.now( functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR), @@ -1135,14 +1149,14 @@ public void modeInUnsupportedFormat() { testNullMissingWeek(DATE); FunctionExpression expression1 = DSL - .week(DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); + .week(functionProperties, DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); SemanticCheckException exception = assertThrows(SemanticCheckException.class, () -> eval(expression1)); assertEquals("mode:8 is invalid, please use mode value between 0-7", exception.getMessage()); FunctionExpression expression2 = DSL - .week(DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(-1)); + .week(functionProperties, DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(-1)); exception = assertThrows(SemanticCheckException.class, () -> eval(expression2)); assertEquals("mode:-1 is invalid, please use mode value between 0-7", exception.getMessage()); From 92454980bb6453abbeb08e40e694f773e2c17d10 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 29 Dec 2022 11:38:56 -0800 Subject: [PATCH 07/20] Removed Unneccessary Formatting Changes Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunction.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 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 f1e82592916..f72708f7fa3 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 @@ -1155,12 +1155,12 @@ private ExprValue exprToDays(ExprValue date) { /** * Week for date implementation for ExprValue. * - * @param expr ExprValue of Date/Datetime/Time/Timestamp/String type. + * @param date ExprValue of Date/Datetime/Timestamp/String type. * @param mode ExprValue of Integer type. */ - private ExprValue exprWeek(ExprValue expr, ExprValue mode) { - return new ExprIntegerValue( - CalendarLookup.getWeekNumber(mode.integerValue(), expr.dateValue())); + private ExprValue exprWeek(ExprValue date, ExprValue mode) { + return new ExprIntegerValue( + CalendarLookup.getWeekNumber(mode.integerValue(), date.dateValue())); } private ExprValue unixTimeStamp(Clock clock) { @@ -1240,11 +1240,11 @@ private Double unixTimeStampOfImpl(ExprValue value) { * Week for date implementation for ExprValue. * When mode is not specified default value mode 0 is used for default_week_format. * - * @param expr ExprValue of Date/Datetime/Time/Timestamp/String type. + * @param date ExprValue of Date/Datetime/Timestamp/String type. * @return ExprValue. */ - private ExprValue exprWeekWithoutMode(ExprValue expr) { - return exprWeek(expr, new ExprIntegerValue(0)); + private ExprValue exprWeekWithoutMode(ExprValue date) { + return exprWeek(date, new ExprIntegerValue(0)); } /** From 08608d5f0c618558df506e32036c1e2cf35a9e6a Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 29 Dec 2022 12:38:23 -0800 Subject: [PATCH 08/20] Fixed Checkstyle Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunction.java | 9 ++++++--- .../opensearch/sql/expression/function/FunctionDSL.java | 2 +- 2 files changed, 7 insertions(+), 4 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 f72708f7fa3..9be9f24c81e 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 @@ -606,13 +606,15 @@ private DefaultFunctionResolver utc_timestamp() { */ private DefaultFunctionResolver week(BuiltinFunctionName week) { return define(week.getName(), - implWithProperties((functionProperties, arg) -> DateTimeFunction.weekOfYearToday(new ExprIntegerValue(0), + implWithProperties((functionProperties, arg) -> DateTimeFunction.weekOfYearToday( + new ExprIntegerValue(0), functionProperties.getQueryStartClock()), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, STRING), - implWithProperties((functionProperties, arg1, arg2) -> DateTimeFunction.weekOfYearToday(arg2, + implWithProperties((functionProperties, arg1, arg2) -> DateTimeFunction.weekOfYearToday( + arg2, functionProperties.getQueryStartClock()), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATE, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATETIME, INTEGER), @@ -659,7 +661,8 @@ private ExprValue dayOfYearToday(Clock clock) { } private ExprValue weekOfYearToday(ExprValue mode, Clock clock) { - return new ExprIntegerValue(CalendarLookup.getWeekNumber(mode.integerValue(), formatNow(clock).toLocalDate())); + return new ExprIntegerValue( + CalendarLookup.getWeekNumber(mode.integerValue(), formatNow(clock).toLocalDate())); } /** diff --git a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java index f257646963d..764448c2ea1 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java @@ -148,7 +148,7 @@ public String toString() { * @return Binary Function Implementation. */ public static SerializableFunction> - implWithProperties( + implWithProperties( SerializableTriFunction function, ExprType returnType, ExprType args1Type, From 85c93e677ba64de401fa4b4115acfe428005e003 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Thu, 29 Dec 2022 15:47:38 -0800 Subject: [PATCH 09/20] Fixed Naming Of Args And Functions Signed-off-by: GabeFernandez310 --- .../expression/datetime/DateTimeFunction.java | 9 ++-- .../datetime/DateTimeFunctionTest.java | 46 +++++++++---------- 2 files changed, 29 insertions(+), 26 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 9be9f24c81e..0d1078b774e 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 @@ -82,6 +82,9 @@ public class DateTimeFunction { // 32536771199.999999, or equivalent '3001-01-18 23:59:59.999999' UTC private static final Double MYSQL_MAX_TIMESTAMP = 32536771200d; + // Mode used for week/week_of_year function by default when no argument is provided + private static final ExprIntegerValue DEFAULT_WEEK_OF_YEAR_MODE = new ExprIntegerValue(0); + /** * Register Date and Time Functions. * @@ -607,14 +610,14 @@ private DefaultFunctionResolver utc_timestamp() { private DefaultFunctionResolver week(BuiltinFunctionName week) { return define(week.getName(), implWithProperties((functionProperties, arg) -> DateTimeFunction.weekOfYearToday( - new ExprIntegerValue(0), + DEFAULT_WEEK_OF_YEAR_MODE, functionProperties.getQueryStartClock()), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, STRING), - implWithProperties((functionProperties, arg1, arg2) -> DateTimeFunction.weekOfYearToday( - arg2, + implWithProperties((functionProperties, time, modeArg) -> DateTimeFunction.weekOfYearToday( + modeArg, functionProperties.getQueryStartClock()), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATE, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATETIME, INTEGER), 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 40938fc2366..ad968e9c166 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 @@ -497,7 +497,7 @@ public void testDayOfYearWithTimeType() { assertEquals("day_of_year(TIME '12:23:34')", expression.toString()); } - public void testDayOfYearWithUnderscores(String date, int dayOfYear) { + public void dayOfYearWithUnderscoresQuery(String date, int dayOfYear) { FunctionExpression expression = DSL.day_of_year( functionProperties, DSL.literal(new ExprDateValue(date))); @@ -521,13 +521,13 @@ public void dayOfYearWithUnderscoresDifferentArgumentFormats() { DSL.literal("2020-08-07 01:02:03")); assertAll( - () -> testDayOfYearWithUnderscores("2020-08-07", 220), + () -> dayOfYearWithUnderscoresQuery("2020-08-07", 220), () -> assertEquals("day_of_year(DATE '2020-08-07')", expression1.toString()), - () -> testDayOfYearWithUnderscores("2020-08-07", 220), + () -> dayOfYearWithUnderscoresQuery("2020-08-07", 220), () -> assertEquals("day_of_year(\"2020-08-07\")", expression2.toString()), - () -> testDayOfYearWithUnderscores("2020-08-07 01:02:03", 220), + () -> dayOfYearWithUnderscoresQuery("2020-08-07 01:02:03", 220), () -> assertEquals("day_of_year(\"2020-08-07 01:02:03\")", expression3.toString()) ); } @@ -539,11 +539,11 @@ public void dayOfYearWithUnderscoresCornerCaseDates() { assertAll( //31st of December during non leap year (should be 365) - () -> testDayOfYearWithUnderscores("2019-12-31", 365), + () -> dayOfYearWithUnderscoresQuery("2019-12-31", 365), //Year 1200 - () -> testDayOfYearWithUnderscores("1200-02-28", 59), + () -> dayOfYearWithUnderscoresQuery("1200-02-28", 59), //Year 4000 - () -> testDayOfYearWithUnderscores("4000-02-28", 59) + () -> dayOfYearWithUnderscoresQuery("4000-02-28", 59) ); } @@ -554,25 +554,25 @@ public void dayOfYearWithUnderscoresLeapYear() { assertAll( //28th of Feb - () -> testDayOfYearWithUnderscores("2020-02-28", 59), + () -> dayOfYearWithUnderscoresQuery("2020-02-28", 59), //29th of Feb during leap year - () -> testDayOfYearWithUnderscores("2020-02-29 23:59:59", 60), - () -> testDayOfYearWithUnderscores("2020-02-29", 60), + () -> dayOfYearWithUnderscoresQuery("2020-02-29 23:59:59", 60), + () -> dayOfYearWithUnderscoresQuery("2020-02-29", 60), //1st of March during leap year - () -> testDayOfYearWithUnderscores("2020-03-01 00:00:00", 61), - () -> testDayOfYearWithUnderscores("2020-03-01", 61), + () -> dayOfYearWithUnderscoresQuery("2020-03-01 00:00:00", 61), + () -> dayOfYearWithUnderscoresQuery("2020-03-01", 61), //1st of March during non leap year - () -> testDayOfYearWithUnderscores("2019-03-01", 60), + () -> dayOfYearWithUnderscoresQuery("2019-03-01", 60), //31st of December during leap year (should be 366) - () -> testDayOfYearWithUnderscores("2020-12-31", 366) + () -> dayOfYearWithUnderscoresQuery("2020-12-31", 366) ); } - public void testInvalidDayOfYear(String date) { + public void invalidDayOfYearQuery(String date) { FunctionExpression expression = DSL.day_of_year( functionProperties, DSL.literal(new ExprDateValue(date))); @@ -591,11 +591,11 @@ public void invalidDayOfYearArgument() { missingRef))); //29th of Feb non-leapyear - assertThrows(SemanticCheckException.class, () -> testInvalidDayOfYear("2019-02-29")); + assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("2019-02-29")); //13th month - assertThrows(SemanticCheckException.class, () -> testInvalidDayOfYear("2019-13-15")); + assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("2019-13-15")); //incorrect format for type - assertThrows(SemanticCheckException.class, () -> testInvalidDayOfYear("asdfasdfasdf")); + assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("asdfasdfasdf")); } @Test @@ -759,7 +759,7 @@ public void testMonthOfYearWithTimeType() { assertEquals("month_of_year(TIME '12:23:34')", expression.toString()); } - public void testInvalidDates(String date) throws SemanticCheckException { + public void invalidDatesQuery(String date) throws SemanticCheckException { FunctionExpression expression = DSL.month_of_year( functionProperties, DSL.literal(new ExprDateValue(date))); @@ -776,10 +776,10 @@ public void testInvalidDates(String date) throws SemanticCheckException { functionProperties, missingRef))); - assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-01-50")); - assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-02-29")); - assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-02-31")); - assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-13-05")); + assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-01-50")); + assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-29")); + assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-31")); + assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-13-05")); } @Test From 2926623ebc5aeaeb404f49e21c5bc026646d4738 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 30 Dec 2022 09:23:45 -0800 Subject: [PATCH 10/20] Added Base Test Class Signed-off-by: GabeFernandez310 --- ...ctionDSLimplWithPropertiesTwoArgsTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java new file mode 100644 index 00000000000..c0d9bbf132d --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java @@ -0,0 +1,35 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.expression.function; + + +import org.apache.commons.lang3.tuple.Pair; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.Expression; + +import java.util.List; + +class FunctionDSLimplWithPropertiesTwoArgsTest extends FunctionDSLimplTestBase { + + @Override + SerializableFunction> + getImplementationGenerator() { + SerializableTriFunction functionBody + = (fp, arg1, arg2) -> ANY; + return FunctionDSL.implWithProperties(functionBody, ANY_TYPE, ANY_TYPE, ANY_TYPE); + } + + @Override + List getSampleArguments() { + return List.of(DSL.literal(ANY), DSL.literal(ANY)); + } + + @Override + String getExpected_toString() { + return "sample(ANY, ANY)"; + } +} From 8eea6302b9a2e22afd74879d5b1b06ef684b3d64 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 30 Dec 2022 09:33:31 -0800 Subject: [PATCH 11/20] Changed Helper Function Names Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 133 +++++++++--------- 1 file changed, 67 insertions(+), 66 deletions(-) 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 ad968e9c166..14dec3b504b 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 @@ -766,7 +766,8 @@ public void invalidDatesQuery(String date) throws SemanticCheckException { eval(expression); } - @Test void monthOfYearInvalidDates() { + @Test + public void monthOfYearInvalidDates() { when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(DATE); assertEquals(nullValue(), eval(DSL.month_of_year( @@ -1036,7 +1037,7 @@ public void timestamp() { assertEquals("timestamp(TIMESTAMP '2020-08-17 01:01:01')", expr.toString()); } - private void testWeek(String date, int mode, int expectedResult) { + private void weekQuery(String date, int mode, int expectedResult) { FunctionExpression expression = DSL .week(functionProperties, DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); assertEquals(INTEGER, expression.type()); @@ -1089,36 +1090,36 @@ public void week() { assertEquals("week(\"2019-01-05 00:01:00\")", expression.toString()); assertEquals(integerValue(0), eval(expression)); - testWeek("2019-01-05", 0, 0); - testWeek("2019-01-05", 1, 1); - testWeek("2019-01-05", 2, 52); - testWeek("2019-01-05", 3, 1); - testWeek("2019-01-05", 4, 1); - testWeek("2019-01-05", 5, 0); - testWeek("2019-01-05", 6, 1); - testWeek("2019-01-05", 7, 53); - - testWeek("2019-01-06", 0, 1); - testWeek("2019-01-06", 1, 1); - testWeek("2019-01-06", 2, 1); - testWeek("2019-01-06", 3, 1); - testWeek("2019-01-06", 4, 2); - testWeek("2019-01-06", 5, 0); - testWeek("2019-01-06", 6, 2); - testWeek("2019-01-06", 7, 53); - - testWeek("2019-01-07", 0, 1); - testWeek("2019-01-07", 1, 2); - testWeek("2019-01-07", 2, 1); - testWeek("2019-01-07", 3, 2); - testWeek("2019-01-07", 4, 2); - testWeek("2019-01-07", 5, 1); - testWeek("2019-01-07", 6, 2); - testWeek("2019-01-07", 7, 1); - - testWeek("2000-01-01", 0, 0); - testWeek("2000-01-01", 2, 52); - testWeek("1999-12-31", 0, 52); + weekQuery("2019-01-05", 0, 0); + weekQuery("2019-01-05", 1, 1); + weekQuery("2019-01-05", 2, 52); + weekQuery("2019-01-05", 3, 1); + weekQuery("2019-01-05", 4, 1); + weekQuery("2019-01-05", 5, 0); + weekQuery("2019-01-05", 6, 1); + weekQuery("2019-01-05", 7, 53); + + weekQuery("2019-01-06", 0, 1); + weekQuery("2019-01-06", 1, 1); + weekQuery("2019-01-06", 2, 1); + weekQuery("2019-01-06", 3, 1); + weekQuery("2019-01-06", 4, 2); + weekQuery("2019-01-06", 5, 0); + weekQuery("2019-01-06", 6, 2); + weekQuery("2019-01-06", 7, 53); + + weekQuery("2019-01-07", 0, 1); + weekQuery("2019-01-07", 1, 2); + weekQuery("2019-01-07", 2, 1); + weekQuery("2019-01-07", 3, 2); + weekQuery("2019-01-07", 4, 2); + weekQuery("2019-01-07", 5, 1); + weekQuery("2019-01-07", 6, 2); + weekQuery("2019-01-07", 7, 1); + + weekQuery("2000-01-01", 0, 0); + weekQuery("2000-01-01", 2, 52); + weekQuery("1999-12-31", 0, 52); } @Test @@ -1162,7 +1163,7 @@ public void modeInUnsupportedFormat() { exception.getMessage()); } - private void testWeekOfYear(String date, int mode, int expectedResult) { + private void weekOfYearQuery(String date, int mode, int expectedResult) { FunctionExpression expression = DSL .week_of_year( functionProperties, @@ -1206,11 +1207,11 @@ public void testInvalidWeekOfYear() { nullRef, missingRef))); //test invalid month - assertThrows(SemanticCheckException.class, () -> testWeekOfYear("2019-13-05 01:02:03", 0, 0)); + assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-13-05 01:02:03", 0, 0)); //test invalid day - assertThrows(SemanticCheckException.class, () -> testWeekOfYear("2019-01-50 01:02:03", 0, 0)); + assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-01-50 01:02:03", 0, 0)); //test invalid leap year - assertThrows(SemanticCheckException.class, () -> testWeekOfYear("2019-02-29 01:02:03", 0, 0)); + assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-02-29 01:02:03", 0, 0)); } @Test @@ -1247,36 +1248,36 @@ public void testWeekOfYearDifferentModes() { lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); //Test the behavior of different modes passed into the 'week_of_year' function - testWeekOfYear("2019-01-05", 0, 0); - testWeekOfYear("2019-01-05", 1, 1); - testWeekOfYear("2019-01-05", 2, 52); - testWeekOfYear("2019-01-05", 3, 1); - testWeekOfYear("2019-01-05", 4, 1); - testWeekOfYear("2019-01-05", 5, 0); - testWeekOfYear("2019-01-05", 6, 1); - testWeekOfYear("2019-01-05", 7, 53); - - testWeekOfYear("2019-01-06", 0, 1); - testWeekOfYear("2019-01-06", 1, 1); - testWeekOfYear("2019-01-06", 2, 1); - testWeekOfYear("2019-01-06", 3, 1); - testWeekOfYear("2019-01-06", 4, 2); - testWeekOfYear("2019-01-06", 5, 0); - testWeekOfYear("2019-01-06", 6, 2); - testWeekOfYear("2019-01-06", 7, 53); - - testWeekOfYear("2019-01-07", 0, 1); - testWeekOfYear("2019-01-07", 1, 2); - testWeekOfYear("2019-01-07", 2, 1); - testWeekOfYear("2019-01-07", 3, 2); - testWeekOfYear("2019-01-07", 4, 2); - testWeekOfYear("2019-01-07", 5, 1); - testWeekOfYear("2019-01-07", 6, 2); - testWeekOfYear("2019-01-07", 7, 1); - - testWeekOfYear("2000-01-01", 0, 0); - testWeekOfYear("2000-01-01", 2, 52); - testWeekOfYear("1999-12-31", 0, 52); + weekOfYearQuery("2019-01-05", 0, 0); + weekOfYearQuery("2019-01-05", 1, 1); + weekOfYearQuery("2019-01-05", 2, 52); + weekOfYearQuery("2019-01-05", 3, 1); + weekOfYearQuery("2019-01-05", 4, 1); + weekOfYearQuery("2019-01-05", 5, 0); + weekOfYearQuery("2019-01-05", 6, 1); + weekOfYearQuery("2019-01-05", 7, 53); + + weekOfYearQuery("2019-01-06", 0, 1); + weekOfYearQuery("2019-01-06", 1, 1); + weekOfYearQuery("2019-01-06", 2, 1); + weekOfYearQuery("2019-01-06", 3, 1); + weekOfYearQuery("2019-01-06", 4, 2); + weekOfYearQuery("2019-01-06", 5, 0); + weekOfYearQuery("2019-01-06", 6, 2); + weekOfYearQuery("2019-01-06", 7, 53); + + weekOfYearQuery("2019-01-07", 0, 1); + weekOfYearQuery("2019-01-07", 1, 2); + weekOfYearQuery("2019-01-07", 2, 1); + weekOfYearQuery("2019-01-07", 3, 2); + weekOfYearQuery("2019-01-07", 4, 2); + weekOfYearQuery("2019-01-07", 5, 1); + weekOfYearQuery("2019-01-07", 6, 2); + weekOfYearQuery("2019-01-07", 7, 1); + + weekOfYearQuery("2000-01-01", 0, 0); + weekOfYearQuery("2000-01-01", 2, 52); + weekOfYearQuery("1999-12-31", 0, 52); } From eac4b4e2ca1fb8a3041a572b9915a9be212981e4 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 30 Dec 2022 09:37:33 -0800 Subject: [PATCH 12/20] Changed Documentation Signed-off-by: GabeFernandez310 --- docs/user/dql/functions.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 4d1a176252f..608c5451ecc 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -1457,7 +1457,7 @@ Description >>>>>>>>>>> Usage: dayofyear(date) returns the day of the year for date, in the range 1 to 366. -If an argument of type `TIME` is given, the function will use the current date to calculate an output. +If an argument of type `TIME` is given, the function will use the current date. The function `day_of_year`_ is also provided as an alias. Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP @@ -1497,7 +1497,7 @@ DAY_OF_YEAR Description >>>>>>>>>>> -If an argument of type `TIME` is given, the function will use the current date to calculate an output. +If an argument of type `TIME` is given, the function will use the current date. This function is an alias to the `dayofyear`_ function Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP @@ -1772,8 +1772,8 @@ Description >>>>>>>>>>> Usage: month(date) returns the month for date, in the range 1 to 12 for January to December. The dates with value 0 such as '0000-00-00' or '2008-00-00' are invalid. -If an argument of type `TIME` is given, the function will use the current date to calculate an output. -The function month_of_year is also provided as an alias. +If an argument of type `TIME` is given, the function will use the current date. +The function `month_of_year`_ is also provided as an alias. Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP @@ -2197,7 +2197,7 @@ Description >>>>>>>>>>> Usage: week(date[, mode]) returns the week number for date. If the mode argument is omitted, the default mode 0 is used. -If an argument of type `TIME` is given, the function will use the current date to calculate an output. +If an argument of type `TIME` is given, the function will use the current date. The function `week_of_year` is also provided as an alias. .. list-table:: The following table describes how the mode argument works. @@ -2262,7 +2262,7 @@ Description >>>>>>>>>>> The week_of_year function is a synonym for the `week`_ function. -If an argument of type `TIME` is given, the function will use the current date to calculate an output. +If an argument of type `TIME` is given, the function will use the current date. Argument type: DATE/DATETIME/TIME/TIMESTAMP/STRING From 4d4afa59ad3d2efe41a964952457d33ece8e30be Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Fri, 30 Dec 2022 11:07:55 -0800 Subject: [PATCH 13/20] Fixed Checkstyle Signed-off-by: GabeFernandez310 --- .../function/FunctionDSLimplWithPropertiesTwoArgsTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java index c0d9bbf132d..f6904858012 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgsTest.java @@ -6,13 +6,12 @@ package org.opensearch.sql.expression.function; +import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.expression.DSL; import org.opensearch.sql.expression.Expression; -import java.util.List; - class FunctionDSLimplWithPropertiesTwoArgsTest extends FunctionDSLimplTestBase { @Override From 6465ec867cb5a13d21058604391687fe7cc03cb5 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Tue, 3 Jan 2023 11:55:34 -0800 Subject: [PATCH 14/20] Addressed Some PR Comments Signed-off-by: GabeFernandez310 --- .../expression/datetime/DateTimeFunction.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 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 0d1078b774e..6714f5c2524 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 @@ -20,6 +20,7 @@ import static org.opensearch.sql.expression.function.FunctionDSL.impl; import static org.opensearch.sql.expression.function.FunctionDSL.implWithProperties; import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling; +import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandlingWithProperties; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_FORMATTER_LONG_YEAR; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_FORMATTER_SHORT_YEAR; import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_LONG_YEAR; @@ -371,8 +372,9 @@ private DefaultFunctionResolver dayOfWeek() { */ private DefaultFunctionResolver dayOfYear(BuiltinFunctionName dayOfYear) { return define(dayOfYear.getName(), - implWithProperties((functionProperties, arg) -> DateTimeFunction.dayOfYearToday( - functionProperties.getQueryStartClock()), INTEGER, TIME), + implWithProperties(nullMissingHandlingWithProperties((functionProperties, arg) + -> DateTimeFunction.dayOfYearToday( + functionProperties.getQueryStartClock())), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprDayOfYear), INTEGER, TIMESTAMP), @@ -446,8 +448,9 @@ private DefaultFunctionResolver minute() { */ private DefaultFunctionResolver month(BuiltinFunctionName month) { return define(month.getName(), - implWithProperties((functionProperties, arg) -> DateTimeFunction.monthOfYearToday( - functionProperties.getQueryStartClock()), INTEGER, TIME), + implWithProperties(nullMissingHandlingWithProperties((functionProperties, arg) + -> DateTimeFunction.monthOfYearToday( + functionProperties.getQueryStartClock())), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, TIMESTAMP), @@ -609,9 +612,10 @@ private DefaultFunctionResolver utc_timestamp() { */ private DefaultFunctionResolver week(BuiltinFunctionName week) { return define(week.getName(), - implWithProperties((functionProperties, arg) -> DateTimeFunction.weekOfYearToday( + implWithProperties(nullMissingHandlingWithProperties((functionProperties, arg) + -> DateTimeFunction.weekOfYearToday( DEFAULT_WEEK_OF_YEAR_MODE, - functionProperties.getQueryStartClock()), INTEGER, TIME), + functionProperties.getQueryStartClock())), INTEGER, TIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATE), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), From 2517b31f4ed5688dcaa7baa78aa4a025a71a28a4 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 08:25:21 -0800 Subject: [PATCH 15/20] Added Support For Null/Missing Args Signed-off-by: GabeFernandez310 --- .../expression/datetime/DateTimeFunction.java | 13 ++--- .../sql/expression/function/FunctionDSL.java | 49 +++++++++---------- .../function/FunctionDSLTestBase.java | 2 + ...nctionDSLimplWithPropertiesTwoArgTest.java | 33 +++++++++++++ .../FunctionDSLnullMissingHandlingTest.java | 35 +++++++++++++ 5 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java 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 6714f5c2524..ab22509a9bc 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 @@ -620,9 +620,10 @@ private DefaultFunctionResolver week(BuiltinFunctionName week) { impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, DATETIME), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, TIMESTAMP), impl(nullMissingHandling(DateTimeFunction::exprWeekWithoutMode), INTEGER, STRING), - implWithProperties((functionProperties, time, modeArg) -> DateTimeFunction.weekOfYearToday( - modeArg, - functionProperties.getQueryStartClock()), INTEGER, TIME, INTEGER), + implWithProperties(nullMissingHandlingWithProperties((functionProperties, time, modeArg) + -> DateTimeFunction.weekOfYearToday( + modeArg, + functionProperties.getQueryStartClock())), INTEGER, TIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATE, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, DATETIME, INTEGER), impl(nullMissingHandling(DateTimeFunction::exprWeek), INTEGER, TIMESTAMP, INTEGER), @@ -664,12 +665,12 @@ private DefaultFunctionResolver date_format() { } private ExprValue dayOfYearToday(Clock clock) { - return new ExprIntegerValue((formatNow(clock).getDayOfYear())); + return new ExprIntegerValue(LocalDateTime.now(clock).getDayOfYear()); } private ExprValue weekOfYearToday(ExprValue mode, Clock clock) { return new ExprIntegerValue( - CalendarLookup.getWeekNumber(mode.integerValue(), formatNow(clock).toLocalDate())); + CalendarLookup.getWeekNumber(mode.integerValue(), LocalDateTime.now(clock).toLocalDate())); } /** @@ -1268,7 +1269,7 @@ private ExprValue exprYear(ExprValue date) { } private ExprValue monthOfYearToday(Clock clock) { - return new ExprIntegerValue((formatNow(clock).getMonthValue())); + return new ExprIntegerValue(LocalDateTime.now(clock).getMonthValue()); } private LocalDateTime formatNow(Clock clock) { diff --git a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java index 764448c2ea1..d94d7cdf601 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/FunctionDSL.java @@ -138,10 +138,10 @@ public String toString() { } /** - * Implementation of a function that takes two argument, returns a value, and + * Implementation of a function that takes two arguments, returns a value, and * requires FunctionProperties to complete. * - * @param function {@link ExprValue} based binary function. + * @param function {@link ExprValue} based Binary function. * @param returnType return type. * @param args1Type first argument type. * @param args2Type second argument type. @@ -227,31 +227,8 @@ public static SerializableFunction { - FunctionSignature functionSignature = - new FunctionSignature(functionName, Arrays.asList(args1Type, args2Type)); - FunctionBuilder functionBuilder = - (functionProperties, arguments) -> new FunctionExpression(functionName, arguments) { - @Override - public ExprValue valueOf(Environment valueEnv) { - ExprValue arg1 = arguments.get(0).valueOf(valueEnv); - ExprValue arg2 = arguments.get(1).valueOf(valueEnv); - return function.apply(arg1, arg2); - } - - @Override - public ExprType type() { - return returnType; - } - - @Override - public String toString() { - return String.format("%s(%s, %s)", functionName, arguments.get(0).toString(), - arguments.get(1).toString()); - } - }; - return Pair.of(functionSignature, functionBuilder); - }; + return implWithProperties((fp, arg1, arg2) -> + function.apply(arg1, arg2), returnType, args1Type, args2Type); } /** @@ -363,4 +340,22 @@ public SerializableTriFunction nullM } }; } + + /** + * Wrapper for the ExprValue function that takes 2 arguments and is aware of FunctionProperties, + * with default NULL and MISSING handling. + */ + public static SerializableTriFunction + nullMissingHandlingWithProperties( + SerializableTriFunction implementation) { + return (functionProperties, v1, v2) -> { + if (v1.isMissing() || v2.isMissing()) { + return ExprValueUtils.missingValue(); + } else if (v1.isNull() || v2.isNull()) { + return ExprValueUtils.nullValue(); + } else { + return implementation.apply(functionProperties, v1, v2); + } + }; + } } diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java index 193066e626f..63c6ea33296 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLTestBase.java @@ -52,6 +52,8 @@ public int compareTo(ExprValue o) { static final SerializableFunction oneArg = v -> ANY; static final SerializableBiFunction oneArgWithProperties = (functionProperties, v) -> ANY; + static final SerializableTriFunction + twoArgWithProperties = (functionProperties, v1, v2) -> ANY; static final SerializableBiFunction twoArgs = (v1, v2) -> ANY; diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java new file mode 100644 index 00000000000..18444a476ec --- /dev/null +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLimplWithPropertiesTwoArgTest.java @@ -0,0 +1,33 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.sql.expression.function; + +import java.util.List; +import org.apache.commons.lang3.tuple.Pair; +import org.opensearch.sql.data.model.ExprValue; +import org.opensearch.sql.expression.DSL; +import org.opensearch.sql.expression.Expression; + +class FunctionDSLimplWithPropertiesTwoArgTest extends FunctionDSLimplTestBase { + + @Override + SerializableFunction> + getImplementationGenerator() { + SerializableTriFunction functionBody + = (fp, arg1, arg2) -> ANY; + return FunctionDSL.implWithProperties(functionBody, ANY_TYPE, ANY_TYPE, ANY_TYPE); + } + + @Override + List getSampleArguments() { + return List.of(DSL.literal(ANY), DSL.literal(ANY)); + } + + @Override + String getExpected_toString() { + return "sample(ANY, ANY)"; + } +} diff --git a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java index 64cac278f6b..17f1de355f2 100644 --- a/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/function/FunctionDSLnullMissingHandlingTest.java @@ -47,6 +47,41 @@ void nullMissingHandling_oneArg_FunctionProperties_apply() { nullMissingHandlingWithProperties(oneArgWithProperties).apply(functionProperties, ANY)); } + @Test + void nullMissingHandling_twoArgs_FunctionProperties_nullValue_firstArg() { + assertEquals(NULL, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, NULL, ANY)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_nullValue_secondArg() { + assertEquals(NULL, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, NULL)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_missingValue_firstArg() { + assertEquals(MISSING, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, MISSING, ANY)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_missingValue_secondArg() { + assertEquals(MISSING, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, MISSING)); + } + + @Test + void nullMissingHandling_twoArgs_FunctionProperties_apply() { + assertEquals(ANY, + nullMissingHandlingWithProperties(twoArgWithProperties) + .apply(functionProperties, ANY, ANY)); + } + @Test void nullMissingHandling_twoArgs_firstArg_nullValue() { assertEquals(NULL, nullMissingHandling(twoArgs).apply(NULL, ANY)); From 109af62c121b7eb400e7d3044c5296d9786c690d Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 11:08:32 -0800 Subject: [PATCH 16/20] Refactored Tests For Week And Week_Of_Year Functionsa Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 287 ++++++++---------- 1 file changed, 132 insertions(+), 155 deletions(-) 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 14dec3b504b..4c7b7d39282 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 @@ -29,10 +29,15 @@ import com.google.common.collect.ImmutableList; import java.time.LocalDate; import java.util.List; +import java.util.stream.Stream; + import lombok.AllArgsConstructor; import org.junit.jupiter.api.BeforeEach; 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; @@ -47,6 +52,7 @@ 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; @ExtendWith(MockitoExtension.class) @@ -1045,7 +1051,17 @@ private void weekQuery(String date, int mode, int expectedResult) { assertEquals(integerValue(expectedResult), eval(expression)); } - private void testNullMissingWeek(ExprCoreType date) { + private void weekOfYearQuery(String date, int mode, int expectedResult) { + FunctionExpression expression = DSL + .week_of_year( + functionProperties, + DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); + assertEquals(INTEGER, expression.type()); + assertEquals(String.format("week_of_year(DATE '%s', %d)", date, mode), expression.toString()); + assertEquals(integerValue(expectedResult), eval(expression)); + } + + private void nullMissingWeekQuery(ExprCoreType date) { when(nullRef.type()).thenReturn(date); when(missingRef.type()).thenReturn(date); assertEquals(nullValue(), eval(DSL.week(functionProperties, nullRef))); @@ -1053,11 +1069,11 @@ private void testNullMissingWeek(ExprCoreType date) { } @Test - public void week() { - testNullMissingWeek(DATE); - testNullMissingWeek(DATETIME); - testNullMissingWeek(TIMESTAMP); - testNullMissingWeek(STRING); + public void testNullMissingWeek(){ + nullMissingWeekQuery(DATE); + nullMissingWeekQuery(DATETIME); + nullMissingWeekQuery(TIMESTAMP); + nullMissingWeekQuery(STRING); when(nullRef.type()).thenReturn(INTEGER); when(missingRef.type()).thenReturn(INTEGER); @@ -1073,53 +1089,94 @@ public void week() { assertEquals(missingValue(), eval(DSL.week( functionProperties, nullRef, missingRef))); + } - FunctionExpression expression = DSL - .week(functionProperties, DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); - assertEquals(INTEGER, expression.type()); - assertEquals("week(TIMESTAMP '2019-01-05 01:02:03')", expression.toString()); - assertEquals(integerValue(0), eval(expression)); + private static Stream getTestDataForWeek() { + //Test the behavior of different modes passed into the 'week_of_year' function + return Stream.of( + Arguments.of("2019-01-05", 0, 0), + Arguments.of("2019-01-05", 1, 1), + Arguments.of("2019-01-05", 2, 52), + Arguments.of("2019-01-05", 3, 1), + Arguments.of("2019-01-05", 4, 1), + Arguments.of("2019-01-05", 5, 0), + Arguments.of("2019-01-05", 6, 1), + Arguments.of("2019-01-05", 7, 53), + + Arguments.of("2019-01-06", 0, 1), + Arguments.of("2019-01-06", 1, 1), + Arguments.of("2019-01-06", 2, 1), + Arguments.of("2019-01-06", 3, 1), + Arguments.of("2019-01-06", 4, 2), + Arguments.of("2019-01-06", 5, 0), + Arguments.of("2019-01-06", 6, 2), + Arguments.of("2019-01-06", 7, 53), + + Arguments.of("2019-01-07", 0, 1), + Arguments.of("2019-01-07", 1, 2), + Arguments.of("2019-01-07", 2, 1), + Arguments.of("2019-01-07", 3, 2), + Arguments.of("2019-01-07", 4, 2), + Arguments.of("2019-01-07", 5, 1), + Arguments.of("2019-01-07", 6, 2), + Arguments.of("2019-01-07", 7, 1), + + Arguments.of("2000-01-01", 0, 0), + Arguments.of("2000-01-01", 2, 52), + Arguments.of("1999-12-31", 0, 52) + ); + } - expression = DSL.week(functionProperties, DSL.literal("2019-01-05")); - assertEquals(INTEGER, expression.type()); - assertEquals("week(\"2019-01-05\")", expression.toString()); - assertEquals(integerValue(0), eval(expression)); + @ParameterizedTest(name = "{1}{2}") + @MethodSource("getTestDataForWeek") + public void testWeek(String date, int mode, int expected) { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + weekQuery(date, mode, expected); + weekOfYearQuery(date, mode, expected); + } - expression = DSL.week(functionProperties, DSL.literal("2019-01-05 00:01:00")); - assertEquals(INTEGER, expression.type()); - assertEquals("week(\"2019-01-05 00:01:00\")", expression.toString()); - assertEquals(integerValue(0), eval(expression)); + private void validateStringFormat( + FunctionExpression expr, + String expectedString, + int expectedResult) { + assertAll( + () -> assertEquals(INTEGER, expr.type()), + () -> assertEquals(expectedString, expr.toString()), + () -> assertEquals(integerValue(expectedResult), eval(expr)) + ); + } - weekQuery("2019-01-05", 0, 0); - weekQuery("2019-01-05", 1, 1); - weekQuery("2019-01-05", 2, 52); - weekQuery("2019-01-05", 3, 1); - weekQuery("2019-01-05", 4, 1); - weekQuery("2019-01-05", 5, 0); - weekQuery("2019-01-05", 6, 1); - weekQuery("2019-01-05", 7, 53); - - weekQuery("2019-01-06", 0, 1); - weekQuery("2019-01-06", 1, 1); - weekQuery("2019-01-06", 2, 1); - weekQuery("2019-01-06", 3, 1); - weekQuery("2019-01-06", 4, 2); - weekQuery("2019-01-06", 5, 0); - weekQuery("2019-01-06", 6, 2); - weekQuery("2019-01-06", 7, 53); - - weekQuery("2019-01-07", 0, 1); - weekQuery("2019-01-07", 1, 2); - weekQuery("2019-01-07", 2, 1); - weekQuery("2019-01-07", 3, 2); - weekQuery("2019-01-07", 4, 2); - weekQuery("2019-01-07", 5, 1); - weekQuery("2019-01-07", 6, 2); - weekQuery("2019-01-07", 7, 1); - - weekQuery("2000-01-01", 0, 0); - weekQuery("2000-01-01", 2, 52); - weekQuery("1999-12-31", 0, 52); + private static Stream getTestDataForWeekFormats() { + return Stream.of( + Arguments.of(DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03")), + "TIMESTAMP '2019-01-05 01:02:03'", + 0), + Arguments.of( + DSL.literal("2019-01-05"), + "\"2019-01-05\"", + 0), + Arguments.of( + DSL.literal("2019-01-05 00:01:00"), + "\"2019-01-05 00:01:00\"", + 0) + ); + } + + @ParameterizedTest(name = "{1}{2}") + @MethodSource("getTestDataForWeekFormats") + public void testWeekFormats( + LiteralExpression arg, + String expectedString, + Integer expectedInteger) { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + validateStringFormat( + DSL.week(functionProperties, arg), + String.format("week(%s)", expectedString), expectedInteger); + validateStringFormat( + DSL.week_of_year(functionProperties, arg), + String.format("week_of_year(%s)", expectedString), expectedInteger); } @Test @@ -1127,27 +1184,22 @@ public void testWeekOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL - .week(functionProperties, DSL.literal(new ExprTimeValue("12:23:34")), DSL.literal(0)); - assertEquals(INTEGER, eval(expression).type()); - assertEquals(LocalDate.now( - functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR), - eval(expression).integerValue()); - assertEquals("week(TIME '12:23:34', 0)", expression.toString()); - - expression = DSL.week_of_year( - functionProperties, - DSL.literal(new ExprTimeValue("12:23:34"))); - assertEquals(INTEGER, eval(expression).type()); - assertEquals(LocalDate.now( - functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR), - eval(expression).integerValue()); - assertEquals("week_of_year(TIME '12:23:34')", expression.toString()); + assertAll( + () -> validateStringFormat( + DSL.week(functionProperties, DSL.literal(new ExprTimeValue("12:23:34")), DSL.literal(0)), + "week(TIME '12:23:34', 0)", + LocalDate.now(functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR)), + + () -> validateStringFormat( + DSL.week_of_year(functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))), + "week_of_year(TIME '12:23:34')", + LocalDate.now(functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR)) + ); } @Test public void modeInUnsupportedFormat() { - testNullMissingWeek(DATE); + nullMissingWeekQuery(DATE); FunctionExpression expression1 = DSL .week(functionProperties, DSL.literal(new ExprDateValue("2019-01-05")), DSL.literal(8)); @@ -1163,17 +1215,7 @@ public void modeInUnsupportedFormat() { exception.getMessage()); } - private void weekOfYearQuery(String date, int mode, int expectedResult) { - FunctionExpression expression = DSL - .week_of_year( - functionProperties, - DSL.literal(new ExprDateValue(date)), DSL.literal(mode)); - assertEquals(INTEGER, expression.type()); - assertEquals(String.format("week_of_year(DATE '%s', %d)", date, mode), expression.toString()); - assertEquals(integerValue(expectedResult), eval(expression)); - } - - private void testNullMissingWeekOfYear(ExprCoreType date) { + private void nullMissingWeekOfYearQuery(ExprCoreType date) { when(nullRef.type()).thenReturn(date); when(missingRef.type()).thenReturn(date); assertEquals(nullValue(), eval(DSL.week_of_year( @@ -1186,10 +1228,10 @@ private void testNullMissingWeekOfYear(ExprCoreType date) { @Test public void testInvalidWeekOfYear() { - testNullMissingWeekOfYear(DATE); - testNullMissingWeekOfYear(DATETIME); - testNullMissingWeekOfYear(TIMESTAMP); - testNullMissingWeekOfYear(STRING); + nullMissingWeekOfYearQuery(DATE); + nullMissingWeekOfYearQuery(DATETIME); + nullMissingWeekOfYearQuery(TIMESTAMP); + nullMissingWeekOfYearQuery(STRING); when(nullRef.type()).thenReturn(INTEGER); when(missingRef.type()).thenReturn(INTEGER); @@ -1206,84 +1248,19 @@ public void testInvalidWeekOfYear() { functionProperties, nullRef, missingRef))); - //test invalid month - assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-13-05 01:02:03", 0, 0)); - //test invalid day - assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-01-50 01:02:03", 0, 0)); - //test invalid leap year - assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-02-29 01:02:03", 0, 0)); - } - - @Test - public void testWeekOfYearAlternateArgumentFormats() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - - FunctionExpression expression = DSL - .week_of_year( - functionProperties, - DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03"))); - assertEquals(INTEGER, expression.type()); - assertEquals("week_of_year(TIMESTAMP '2019-01-05 01:02:03')", expression.toString()); - assertEquals(integerValue(0), eval(expression)); - - expression = DSL.week_of_year( - functionProperties, - DSL.literal("2019-01-05")); - assertEquals(INTEGER, expression.type()); - assertEquals("week_of_year(\"2019-01-05\")", expression.toString()); - assertEquals(integerValue(0), eval(expression)); - - expression = DSL.week_of_year( - functionProperties, - DSL.literal("2019-01-05 00:01:00")); - assertEquals(INTEGER, expression.type()); - assertEquals("week_of_year(\"2019-01-05 00:01:00\")", expression.toString()); - assertEquals(integerValue(0), eval(expression)); - } - - @Test - public void testWeekOfYearDifferentModes() { - lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); - lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - - //Test the behavior of different modes passed into the 'week_of_year' function - weekOfYearQuery("2019-01-05", 0, 0); - weekOfYearQuery("2019-01-05", 1, 1); - weekOfYearQuery("2019-01-05", 2, 52); - weekOfYearQuery("2019-01-05", 3, 1); - weekOfYearQuery("2019-01-05", 4, 1); - weekOfYearQuery("2019-01-05", 5, 0); - weekOfYearQuery("2019-01-05", 6, 1); - weekOfYearQuery("2019-01-05", 7, 53); - - weekOfYearQuery("2019-01-06", 0, 1); - weekOfYearQuery("2019-01-06", 1, 1); - weekOfYearQuery("2019-01-06", 2, 1); - weekOfYearQuery("2019-01-06", 3, 1); - weekOfYearQuery("2019-01-06", 4, 2); - weekOfYearQuery("2019-01-06", 5, 0); - weekOfYearQuery("2019-01-06", 6, 2); - weekOfYearQuery("2019-01-06", 7, 53); - - weekOfYearQuery("2019-01-07", 0, 1); - weekOfYearQuery("2019-01-07", 1, 2); - weekOfYearQuery("2019-01-07", 2, 1); - weekOfYearQuery("2019-01-07", 3, 2); - weekOfYearQuery("2019-01-07", 4, 2); - weekOfYearQuery("2019-01-07", 5, 1); - weekOfYearQuery("2019-01-07", 6, 2); - weekOfYearQuery("2019-01-07", 7, 1); - - weekOfYearQuery("2000-01-01", 0, 0); - weekOfYearQuery("2000-01-01", 2, 52); - weekOfYearQuery("1999-12-31", 0, 52); - + assertAll( + //test invalid month + () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-13-05 01:02:03", 0, 0)), + //test invalid day + () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-01-50 01:02:03", 0, 0)), + //test invalid leap year + () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-02-29 01:02:03", 0, 0)) + ); } @Test public void weekOfYearModeInUnsupportedFormat() { - testNullMissingWeekOfYear(DATE); + nullMissingWeekOfYearQuery(DATE); FunctionExpression expression1 = DSL .week_of_year( From 3c843ba8cff46cca9ff731b204245ef8adab58bc Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 11:23:35 -0800 Subject: [PATCH 17/20] Refactored Tests For Month_Of_Year Function Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) 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 4c7b7d39282..63ef6106091 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 @@ -754,15 +754,11 @@ public void month() { public void testMonthOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.month_of_year( - functionProperties, - DSL.literal(new ExprTimeValue("12:23:34"))); - assertEquals(INTEGER, eval(expression).type()); - assertEquals(LocalDate.now( - functionProperties.getQueryStartClock()).getMonthValue(), - eval(expression).integerValue()); - assertEquals("month_of_year(TIME '12:23:34')", expression.toString()); + validateStringFormat( + DSL.month_of_year(functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))), + "month_of_year(TIME '12:23:34')", + LocalDate.now(functionProperties.getQueryStartClock()).getMonthValue()); } public void invalidDatesQuery(String date) throws SemanticCheckException { @@ -776,17 +772,22 @@ public void invalidDatesQuery(String date) throws SemanticCheckException { public void monthOfYearInvalidDates() { when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.month_of_year( - functionProperties, - nullRef))); - assertEquals(missingValue(), eval(DSL.month_of_year( - functionProperties, - missingRef))); - assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-01-50")); - assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-29")); - assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-31")); - assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-13-05")); + assertAll( + () -> assertEquals(nullValue(), eval(DSL.month_of_year( + functionProperties, + nullRef))), + () -> assertEquals(missingValue(), eval(DSL.month_of_year( + functionProperties, + missingRef))), + () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-01-50")), + () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-29")), + () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-02-31")), + () -> assertThrows(SemanticCheckException.class, () -> invalidDatesQuery("2019-13-05")) + ); + + + } @Test @@ -1250,11 +1251,17 @@ public void testInvalidWeekOfYear() { assertAll( //test invalid month - () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-13-05 01:02:03", 0, 0)), + () -> assertThrows( + SemanticCheckException.class, + () -> weekOfYearQuery("2019-13-05 01:02:03", 0, 0)), //test invalid day - () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-01-50 01:02:03", 0, 0)), + () -> assertThrows( + SemanticCheckException.class, + () -> weekOfYearQuery("2019-01-50 01:02:03", 0, 0)), //test invalid leap year - () -> assertThrows(SemanticCheckException.class, () -> weekOfYearQuery("2019-02-29 01:02:03", 0, 0)) + () -> assertThrows( + SemanticCheckException.class, + () -> weekOfYearQuery("2019-02-29 01:02:03", 0, 0)) ); } From c664af7ba579b2eba3147ff9b05e2a6971ae8cd1 Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 13:56:38 -0800 Subject: [PATCH 18/20] Refactored Tests For Day_Of_Year Function Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) 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 63ef6106091..f01474fa8d5 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 @@ -492,23 +492,21 @@ public void dayOfYear() { public void testDayOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); - FunctionExpression expression = DSL.day_of_year( - functionProperties, - DSL.literal(new ExprTimeValue("12:23:34"))); - assertEquals(INTEGER, eval(expression).type()); - assertEquals(LocalDate.now( - functionProperties.getQueryStartClock()).getDayOfYear(), - eval(expression).integerValue()); - assertEquals("day_of_year(TIME '12:23:34')", expression.toString()); + validateStringFormat( + DSL.day_of_year(functionProperties, DSL.literal(new ExprTimeValue("12:23:34"))), + "day_of_year(TIME '12:23:34')", + LocalDate.now(functionProperties.getQueryStartClock()).getDayOfYear()); } public void dayOfYearWithUnderscoresQuery(String date, int dayOfYear) { FunctionExpression expression = DSL.day_of_year( functionProperties, DSL.literal(new ExprDateValue(date))); - assertEquals(INTEGER, expression.type()); - assertEquals(integerValue(dayOfYear), eval(expression)); + assertAll( + () -> assertEquals(INTEGER, expression.type()), + () -> assertEquals(integerValue(dayOfYear), eval(expression)) + ); } @Test @@ -589,19 +587,26 @@ public void invalidDayOfYearQuery(String date) { public void invalidDayOfYearArgument() { when(nullRef.type()).thenReturn(DATE); when(missingRef.type()).thenReturn(DATE); - assertEquals(nullValue(), eval(DSL.day_of_year( - functionProperties, - nullRef))); - assertEquals(missingValue(), eval(DSL.day_of_year( - functionProperties, - missingRef))); - //29th of Feb non-leapyear - assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("2019-02-29")); - //13th month - assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("2019-13-15")); - //incorrect format for type - assertThrows(SemanticCheckException.class, () -> invalidDayOfYearQuery("asdfasdfasdf")); + assertAll( + () -> assertEquals(nullValue(), eval(DSL.day_of_year(functionProperties, nullRef))), + () -> assertEquals(missingValue(), eval(DSL.day_of_year(functionProperties, missingRef))), + + //29th of Feb non-leapyear + () -> assertThrows( + SemanticCheckException.class, + () -> invalidDayOfYearQuery("2019-02-29")), + + //13th month + () -> assertThrows( + SemanticCheckException.class, + () -> invalidDayOfYearQuery("2019-13-15")), + + //incorrect format for type + () -> assertThrows( + SemanticCheckException.class, + () -> invalidDayOfYearQuery("asdfasdfasdf")) + ); } @Test From dcbe2e22598d5404f4dee2e606ce5228aa1b7a9f Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 15:10:23 -0800 Subject: [PATCH 19/20] Added Tests for Month_Of_Year Function Signed-off-by: GabeFernandez310 --- .../datetime/DateTimeFunctionTest.java | 88 ++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) 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 f01474fa8d5..ef066c25f51 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 @@ -488,6 +488,47 @@ public void dayOfYear() { assertEquals(integerValue(220), eval(expression)); } + private static Stream getTestDataForDayOfYear() { + return Stream.of( + Arguments.of(DSL.literal( + new ExprDateValue("2020-08-07")), + "day_of_year(DATE '2020-08-07')", + 220), + Arguments.of(DSL.literal( + new ExprDatetimeValue("2020-08-07 12:23:34")), + "day_of_year(DATETIME '2020-08-07 12:23:34')", + 220), + Arguments.of(DSL.literal( + new ExprTimestampValue("2020-08-07 12:23:34")), + "day_of_year(TIMESTAMP '2020-08-07 12:23:34')", + 220), + Arguments.of(DSL.literal( + "2020-08-07"), + "day_of_year(\"2020-08-07\")", + 220), + Arguments.of(DSL.literal( + "2020-08-07 01:02:03"), + "day_of_year(\"2020-08-07 01:02:03\")", + 220) + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("getTestDataForDayOfYear") + public void dayOfYearWithUnderscores( + LiteralExpression arg, + String expectedString, + int expectedResult) { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + + validateStringFormat( + DSL.day_of_year(functionProperties, arg), + expectedString, + expectedResult + ); + } + @Test public void testDayOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); @@ -601,7 +642,7 @@ public void invalidDayOfYearArgument() { () -> assertThrows( SemanticCheckException.class, () -> invalidDayOfYearQuery("2019-13-15")), - + //incorrect format for type () -> assertThrows( SemanticCheckException.class, @@ -755,6 +796,43 @@ public void month() { assertEquals(integerValue(8), eval(expression)); } + private static Stream getTestDataForMonthOfYear() { + return Stream.of( + Arguments.of( + DSL.literal(new ExprDateValue("2020-08-07")), + "month_of_year(DATE '2020-08-07')", + 8), + Arguments.of( + DSL.literal(new ExprDatetimeValue("2020-08-07 12:23:34")), + "month_of_year(DATETIME '2020-08-07 12:23:34')", + 8), + Arguments.of( + DSL.literal(new ExprTimestampValue("2020-08-07 12:23:34")), + "month_of_year(TIMESTAMP '2020-08-07 12:23:34')", + 8), + Arguments.of( + DSL.literal("2020-08-07"), + "month_of_year(\"2020-08-07\")", + 8), + Arguments.of( + DSL.literal("2020-08-07 01:02:03"), + "month_of_year(\"2020-08-07 01:02:03\")", + 8) + ); + } + @ParameterizedTest(name = "{0}") + @MethodSource("getTestDataForMonthOfYear") + public void monthOfYear(LiteralExpression arg, String expectedString, int expectedResult) { + lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); + lenient().when(missingRef.valueOf(env)).thenReturn(missingValue()); + + validateStringFormat( + DSL.month_of_year(functionProperties, arg), + expectedString, + expectedResult + ); + } + @Test public void testMonthOfYearWithTimeType() { lenient().when(nullRef.valueOf(env)).thenReturn(nullValue()); @@ -1155,6 +1233,12 @@ private void validateStringFormat( private static Stream getTestDataForWeekFormats() { return Stream.of( + Arguments.of(DSL.literal(new ExprDateValue("2019-01-05")), + "DATE '2019-01-05'", + 0), + Arguments.of(DSL.literal(new ExprDatetimeValue("2019-01-05 01:02:03")), + "DATETIME '2019-01-05 01:02:03'", + 0), Arguments.of(DSL.literal(new ExprTimestampValue("2019-01-05 01:02:03")), "TIMESTAMP '2019-01-05 01:02:03'", 0), @@ -1169,7 +1253,7 @@ private static Stream getTestDataForWeekFormats() { ); } - @ParameterizedTest(name = "{1}{2}") + @ParameterizedTest(name = "{0}") @MethodSource("getTestDataForWeekFormats") public void testWeekFormats( LiteralExpression arg, From 2d8049f7cd237a13e3c2ba34882b156d492c534b Mon Sep 17 00:00:00 2001 From: GabeFernandez310 Date: Wed, 4 Jan 2023 18:44:35 -0800 Subject: [PATCH 20/20] Fixed Checkstyle Signed-off-by: GabeFernandez310 --- .../sql/expression/datetime/DateTimeFunctionTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 ef066c25f51..14671e7ce32 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 @@ -30,7 +30,6 @@ import java.time.LocalDate; import java.util.List; import java.util.stream.Stream; - import lombok.AllArgsConstructor; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -820,6 +819,7 @@ private static Stream getTestDataForMonthOfYear() { 8) ); } + @ParameterizedTest(name = "{0}") @MethodSource("getTestDataForMonthOfYear") public void monthOfYear(LiteralExpression arg, String expectedString, int expectedResult) { @@ -1153,7 +1153,7 @@ private void nullMissingWeekQuery(ExprCoreType date) { } @Test - public void testNullMissingWeek(){ + public void testNullMissingWeek() { nullMissingWeekQuery(DATE); nullMissingWeekQuery(DATETIME); nullMissingWeekQuery(TIMESTAMP); @@ -1276,7 +1276,10 @@ public void testWeekOfYearWithTimeType() { assertAll( () -> validateStringFormat( - DSL.week(functionProperties, DSL.literal(new ExprTimeValue("12:23:34")), DSL.literal(0)), + DSL.week( + functionProperties, + DSL.literal(new ExprTimeValue("12:23:34")), + DSL.literal(0)), "week(TIME '12:23:34', 0)", LocalDate.now(functionProperties.getQueryStartClock()).get(ALIGNED_WEEK_OF_YEAR)),