Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport 2.5] Add Day_Of_Month Function As An Alias Of DayOfMonth #1265

Merged
merged 1 commit into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,10 @@ public static FunctionExpression dayname(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.DAYNAME, expressions);
}

public static FunctionExpression dayofmonth(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.DAYOFMONTH, expressions);
public static FunctionExpression dayofmonth(
FunctionProperties functionProperties,
Expression... expressions) {
return compile(functionProperties, BuiltinFunctionName.DAYOFMONTH, expressions);
}

public static FunctionExpression dayofweek(
Expand All @@ -335,6 +337,12 @@ public static FunctionExpression dayofyear(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.DAYOFYEAR, expressions);
}

public static FunctionExpression day_of_month(
FunctionProperties functionProperties,
Expression... expressions) {
return compile(functionProperties, BuiltinFunctionName.DAY_OF_MONTH, expressions);
}

public static FunctionExpression day_of_year(
FunctionProperties functionProperties, Expression... expressions) {
return compile(functionProperties, BuiltinFunctionName.DAY_OF_YEAR, expressions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.exception.ExpressionEvaluationException;
import org.opensearch.sql.exception.SemanticCheckException;
import org.opensearch.sql.expression.function.BuiltinFunctionName;
import org.opensearch.sql.expression.function.BuiltinFunctionRepository;
import org.opensearch.sql.expression.function.DefaultFunctionResolver;
Expand Down Expand Up @@ -113,7 +112,8 @@ public void register(BuiltinFunctionRepository repository) {
repository.register(date_sub());
repository.register(day());
repository.register(dayName());
repository.register(dayOfMonth());
repository.register(dayOfMonth(BuiltinFunctionName.DAYOFMONTH));
repository.register(dayOfMonth(BuiltinFunctionName.DAY_OF_MONTH));
repository.register(dayOfWeek(BuiltinFunctionName.DAYOFWEEK.getName()));
repository.register(dayOfWeek(BuiltinFunctionName.DAY_OF_WEEK.getName()));
repository.register(dayOfYear(BuiltinFunctionName.DAYOFYEAR));
Expand Down Expand Up @@ -444,12 +444,15 @@ private DefaultFunctionResolver dayName() {
/**
* DAYOFMONTH(STRING/DATE/DATETIME/TIMESTAMP). return the day of the month (1-31).
*/
private DefaultFunctionResolver dayOfMonth() {
return define(BuiltinFunctionName.DAYOFMONTH.getName(),
private DefaultFunctionResolver dayOfMonth(BuiltinFunctionName name) {
return define(name.getName(),
implWithProperties(nullMissingHandlingWithProperties(
(functionProperties, arg) -> DateTimeFunction.dayOfMonthToday(
functionProperties.getQueryStartClock())), INTEGER, TIME),
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, DATE),
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, DATETIME),
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, TIMESTAMP),
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, STRING)
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, STRING),
impl(nullMissingHandling(DateTimeFunction::exprDayOfMonth), INTEGER, TIMESTAMP)
);
}

Expand Down Expand Up @@ -844,6 +847,11 @@ private DefaultFunctionResolver date_format() {
);
}


private ExprValue dayOfMonthToday(Clock clock) {
return new ExprIntegerValue(LocalDateTime.now(clock).getDayOfMonth());
}

private ExprValue dayOfYearToday(Clock clock) {
return new ExprIntegerValue(LocalDateTime.now(clock).getDayOfYear());
}
Expand Down Expand Up @@ -1058,7 +1066,7 @@ private ExprValue exprDayName(ExprValue date) {
/**
* Day of Month implementation for ExprValue.
*
* @param date ExprValue of Date/String type.
* @param date ExprValue of Date/Datetime/String/Time/Timestamp type.
* @return ExprValue.
*/
private ExprValue exprDayOfMonth(ExprValue date) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public enum BuiltinFunctionName {
DAY(FunctionName.of("day")),
DAYNAME(FunctionName.of("dayname")),
DAYOFMONTH(FunctionName.of("dayofmonth")),
DAY_OF_MONTH(FunctionName.of("day_of_month")),
DAYOFWEEK(FunctionName.of("dayofweek")),
DAYOFYEAR(FunctionName.of("dayofyear")),
DAY_OF_WEEK(FunctionName.of("day_of_week")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,20 +422,101 @@ public void dayName() {
public void dayOfMonth() {
when(nullRef.type()).thenReturn(DATE);
when(missingRef.type()).thenReturn(DATE);
assertEquals(nullValue(), eval(DSL.dayofmonth(nullRef)));
assertEquals(missingValue(), eval(DSL.dayofmonth(missingRef)));
assertEquals(nullValue(), eval(DSL.dayofmonth(functionProperties, nullRef)));
assertEquals(missingValue(), eval(DSL.dayofmonth(functionProperties, missingRef)));

FunctionExpression expression = DSL.dayofmonth(DSL.literal(new ExprDateValue("2020-08-07")));
FunctionExpression expression = DSL.dayofmonth(
functionProperties, DSL.literal(new ExprDateValue("2020-08-07")));
assertEquals(INTEGER, expression.type());
assertEquals("dayofmonth(DATE '2020-08-07')", expression.toString());
assertEquals(integerValue(7), eval(expression));

expression = DSL.dayofmonth(DSL.literal("2020-07-08"));
expression = DSL.dayofmonth(functionProperties, DSL.literal("2020-07-08"));
assertEquals(INTEGER, expression.type());
assertEquals("dayofmonth(\"2020-07-08\")", expression.toString());
assertEquals(integerValue(8), eval(expression));
}

private void testDayOfMonthWithUnderscores(FunctionExpression dateExpression, int dayOfMonth) {
assertEquals(INTEGER, dateExpression.type());
assertEquals(integerValue(dayOfMonth), eval(dateExpression));
}

@Test
public void dayOfMonthWithUnderscores() {
lenient().when(nullRef.valueOf(env)).thenReturn(nullValue());
lenient().when(missingRef.valueOf(env)).thenReturn(missingValue());


FunctionExpression expression1 = DSL.dayofmonth(
functionProperties, DSL.literal(new ExprDateValue("2020-08-07")));
FunctionExpression expression2 = DSL.dayofmonth(functionProperties, DSL.literal("2020-07-08"));

assertAll(
() -> testDayOfMonthWithUnderscores(expression1, 7),
() -> assertEquals("dayofmonth(DATE '2020-08-07')", expression1.toString()),

() -> testDayOfMonthWithUnderscores(expression2, 8),
() -> assertEquals("dayofmonth(\"2020-07-08\")", expression2.toString())

);
}

@Test
public void testDayOfMonthWithTimeType() {
lenient().when(nullRef.valueOf(env)).thenReturn(nullValue());
lenient().when(missingRef.valueOf(env)).thenReturn(missingValue());
FunctionExpression expression = DSL.day_of_month(
functionProperties, DSL.literal(new ExprTimeValue("12:23:34")));

assertEquals(INTEGER, eval(expression).type());
assertEquals(
LocalDate.now(functionProperties.getQueryStartClock()).getDayOfMonth(),
eval(expression).integerValue());
assertEquals("day_of_month(TIME '12:23:34')", expression.toString());
}

private void testInvalidDayOfMonth(String date) {
FunctionExpression expression = DSL.day_of_month(
functionProperties, DSL.literal(new ExprDateValue(date)));
eval(expression);
}

@Test
public void dayOfMonthWithUnderscoresLeapYear() {
lenient().when(nullRef.valueOf(env)).thenReturn(nullValue());
lenient().when(missingRef.valueOf(env)).thenReturn(missingValue());

//Feb. 29 of a leap year
testDayOfMonthWithUnderscores(DSL.day_of_month(
functionProperties, DSL.literal("2020-02-29")), 29);

//Feb. 29 of a non-leap year
assertThrows(SemanticCheckException.class, () -> testInvalidDayOfMonth("2021-02-29"));
}

@Test
public void dayOfMonthWithUnderscoresInvalidArguments() {
lenient().when(nullRef.type()).thenReturn(DATE);
lenient().when(missingRef.type()).thenReturn(DATE);

assertAll(
() -> assertEquals(nullValue(), eval(DSL.day_of_month(functionProperties, nullRef))),
() -> assertEquals(
missingValue(), eval(DSL.day_of_month(functionProperties, missingRef))),

//40th day of the month
() -> assertThrows(
SemanticCheckException.class, () -> testInvalidDayOfMonth("2021-02-40")),
//13th month of the year
() -> assertThrows(
SemanticCheckException.class, () -> testInvalidDayOfMonth("2021-13-40")),
//incorrect format
() -> assertThrows(
SemanticCheckException.class, () -> testInvalidDayOfMonth("asdfasdfasdf"))
);
}

private void dayOfWeekQuery(
FunctionExpression dateExpression,
int dayOfWeek,
Expand Down
35 changes: 29 additions & 6 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1499,13 +1499,13 @@ DAY
Description
>>>>>>>>>>>

Usage: day(date) extracts the day of the month for date, in the range 1 to 31. The dates with value 0 such as '0000-00-00' or '2008-00-00' are invalid.
Usage: day(date) extracts the day of the month for date, in the range 1 to 31.

Argument type: STRING/DATE/DATETIME/TIMESTAMP
Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP

Return type: INTEGER

Synonyms: DAYOFMONTH
Synonyms: `DAYOFMONTH`_, `DAY_OF_MONTH`_

Example::

Expand Down Expand Up @@ -1547,13 +1547,13 @@ DAYOFMONTH
Description
>>>>>>>>>>>

Usage: dayofmonth(date) extracts the day of the month for date, in the range 1 to 31. The dates with value 0 such as '0000-00-00' or '2008-00-00' are invalid.
Usage: dayofmonth(date) extracts the day of the month for date, in the range 1 to 31.

Argument type: STRING/DATE/DATETIME/TIMESTAMP
Argument type: STRING/DATE/DATETIME/TIME/TIMESTAMP

Return type: INTEGER

Synonyms: DAY
Synonyms: `DAY`_, `DAY_OF_MONTH`_

Example::

Expand All @@ -1565,6 +1565,29 @@ Example::
| 26 |
+----------------------------------+

DAY_OF_MONTH
------------

Description
>>>>>>>>>>>

Usage: day_of_month(date) extracts the day of the month for date, in the range 1 to 31.

Argument type: STRING/DATE/TIME/DATETIME/TIMESTAMP

Return type: INTEGER

Synonyms: `DAY`_, `DAYOFMONTH`_

Example::

os> SELECT DAY_OF_MONTH('2020-08-26')
fetched rows / total rows = 1/1
+------------------------------+
| DAY_OF_MONTH('2020-08-26') |
|------------------------------|
| 26 |
+------------------------------+

DAYOFWEEK
---------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,48 @@ public void testDayOfMonth() throws IOException {
verifyDataRows(result, rows(16));
}

@Test
public void testDayOfMonthWithUnderscores() throws IOException {
JSONObject result = executeQuery("select day_of_month(date('2020-09-16'))");
verifySchema(result, schema("day_of_month(date('2020-09-16'))", null, "integer"));
verifyDataRows(result, rows(16));

result = executeQuery("select day_of_month('2020-09-16')");
verifySchema(result, schema("day_of_month('2020-09-16')", null, "integer"));
verifyDataRows(result, rows(16));
}

@Test
public void testDayOfMonthAliasesReturnTheSameResults() throws IOException {
JSONObject result1 = executeQuery("SELECT dayofmonth(date('2022-11-22'))");
JSONObject result2 = executeQuery("SELECT day_of_month(date('2022-11-22'))");
verifyDataRows(result1, rows(22));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));

result1 = executeQuery(String.format(
"SELECT dayofmonth(CAST(date0 AS date)) FROM %s", TEST_INDEX_CALCS));
result2 = executeQuery(String.format(
"SELECT day_of_month(CAST(date0 AS date)) FROM %s", TEST_INDEX_CALCS));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));

result1 = executeQuery(String.format(
"SELECT dayofmonth(datetime(CAST(time0 AS STRING))) FROM %s", TEST_INDEX_CALCS));
result2 = executeQuery(String.format(
"SELECT day_of_month(datetime(CAST(time0 AS STRING))) FROM %s", TEST_INDEX_CALCS));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));

result1 = executeQuery(String.format(
"SELECT dayofmonth(CAST(time0 AS STRING)) FROM %s", TEST_INDEX_CALCS));
result2 = executeQuery(String.format(
"SELECT day_of_month(CAST(time0 AS STRING)) FROM %s", TEST_INDEX_CALCS));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));

result1 = executeQuery(String.format(
"SELECT dayofmonth(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
result2 = executeQuery(String.format(
"SELECT day_of_month(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
}
@Test
public void testDayOfWeek() throws IOException {
JSONObject result = executeQuery("select dayofweek(date('2020-09-16'))");
Expand Down
1 change: 1 addition & 0 deletions sql/src/main/antlr/OpenSearchSQLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ dateTimeFunctionName
| DAY
| DAYNAME
| DAYOFMONTH
| DAY_OF_MONTH
| DAYOFWEEK
| DAYOFYEAR
| DAY_OF_YEAR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ public void can_parse_week_of_year_functions() {
assertNotNull(parser.parse("SELECT week_of_year('2022-11-18')"));
}

@Test
public void can_parse_dayofmonth_functions() {
assertNotNull(parser.parse("SELECT dayofmonth('2022-11-18')"));
assertNotNull(parser.parse("SELECT day_of_month('2022-11-18')"));
}

@Test
public void can_parse_day_of_week_functions() {
assertNotNull(parser.parse("SELECT dayofweek('2022-11-18')"));
Expand Down