Skip to content

Commit

Permalink
Add Day_Of_Month Function As An Alias Of DayOfMonth (#1227)
Browse files Browse the repository at this point in the history
* Add Day_Of_Month Function As An Alias Of DayOfMonth (#194)

Signed-off-by: GabeFernandez310 <Gabriel.Fernandez@improving.com>
  • Loading branch information
GabeFernandez310 authored Jan 10, 2023
1 parent 6e72f18 commit 1108379
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 19 deletions.
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 @@ -431,6 +431,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 @@ -201,6 +201,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

0 comments on commit 1108379

Please sign in to comment.