Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
4 changes: 4 additions & 0 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ public static FunctionExpression day_of_year(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.DAY_OF_YEAR, expressions);
}

public static FunctionExpression day_of_week(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.DAY_OF_WEEK, expressions);
}

public static FunctionExpression from_days(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.FROM_DAYS, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ public void register(BuiltinFunctionRepository repository) {
repository.register(day());
repository.register(dayName());
repository.register(dayOfMonth());
repository.register(dayOfWeek());
repository.register(dayOfWeek(BuiltinFunctionName.DAYOFWEEK.getName()));
repository.register(dayOfWeek(BuiltinFunctionName.DAY_OF_WEEK.getName()));
repository.register(dayOfYear(BuiltinFunctionName.DAYOFYEAR));
repository.register(dayOfYear(BuiltinFunctionName.DAY_OF_YEAR));
repository.register(from_days());
Expand Down Expand Up @@ -349,8 +350,8 @@ private DefaultFunctionResolver dayOfMonth() {
* DAYOFWEEK(STRING/DATE/DATETIME/TIMESTAMP).
* return the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday).
*/
private DefaultFunctionResolver dayOfWeek() {
return define(BuiltinFunctionName.DAYOFWEEK.getName(),
private DefaultFunctionResolver dayOfWeek(FunctionName name) {
return define(name,
impl(nullMissingHandling(DateTimeFunction::exprDayOfWeek), INTEGER, DATE),
impl(nullMissingHandling(DateTimeFunction::exprDayOfWeek), INTEGER, DATETIME),
impl(nullMissingHandling(DateTimeFunction::exprDayOfWeek), INTEGER, TIMESTAMP),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public enum BuiltinFunctionName {
DAYOFMONTH(FunctionName.of("dayofmonth")),
DAYOFWEEK(FunctionName.of("dayofweek")),
DAYOFYEAR(FunctionName.of("dayofyear")),
DAY_OF_WEEK(FunctionName.of("day_of_week")),
DAY_OF_YEAR(FunctionName.of("day_of_year")),
FROM_DAYS(FunctionName.of("from_days")),
FROM_UNIXTIME(FunctionName.of("from_unixtime")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,78 @@ public void dayOfWeek() {
assertEquals(integerValue(1), eval(expression));
}

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

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

FunctionExpression expression1 = DSL.day_of_week(DSL.literal(new ExprDateValue("2020-08-07")));
FunctionExpression expression2 = DSL.day_of_week(DSL.literal(new ExprDateValue("2020-08-09")));
FunctionExpression expression3 = DSL.day_of_week(DSL.literal("2020-08-09"));
FunctionExpression expression4 = DSL.day_of_week(DSL.literal("2020-08-09 01:02:03"));

assertAll(
() -> testDayOfWeekWithUnderscores(expression1, 6),
() -> assertEquals("day_of_week(DATE '2020-08-07')", expression1.toString()),

() -> testDayOfWeekWithUnderscores(expression2, 1),
() -> assertEquals("day_of_week(DATE '2020-08-09')", expression2.toString()),


() -> testDayOfWeekWithUnderscores(expression3, 1),
() -> assertEquals("day_of_week(\"2020-08-09\")", expression3.toString()),

() -> testDayOfWeekWithUnderscores(expression4, 1),
() -> assertEquals("day_of_week(\"2020-08-09 01:02:03\")", expression4.toString())
);
}

private void testInvalidDayOfWeek(String date) {
FunctionExpression expression = DSL.day_of_week(DSL.literal(new ExprDateValue(date)));
eval(expression);
}

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

//Feb. 29 of a leap year
testDayOfWeekWithUnderscores(DSL.day_of_week(DSL.literal("2020-02-29")), 7);

//day after Feb. 29 of a leap year
testDayOfWeekWithUnderscores(DSL.day_of_week(DSL.literal("2020-03-01")), 1);

//Feb. 28 of a non-leap year
testDayOfWeekWithUnderscores(DSL.day_of_week(DSL.literal("2021-02-28")), 1);

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️


}

@Test
public void dayOfWeekWithUnderscoresInvalidArgument() {
when(nullRef.type()).thenReturn(DATE);
when(missingRef.type()).thenReturn(DATE);
assertEquals(nullValue(), eval(DSL.day_of_week(nullRef)));
assertEquals(missingValue(), eval(DSL.day_of_week(missingRef)));

//40th day of the month
assertThrows(SemanticCheckException.class, () -> testInvalidDayOfWeek("2021-02-40"));

//13th month of the year
assertThrows(SemanticCheckException.class, () -> testInvalidDayOfWeek("2021-13-29"));

//incorrect format
assertThrows(SemanticCheckException.class, () -> testInvalidDayOfWeek("asdfasdf"));
}

@Test
public void dayOfYear() {
when(nullRef.type()).thenReturn(DATE);
Expand All @@ -481,7 +553,7 @@ public void dayOfYear() {
assertEquals(integerValue(220), eval(expression));
}

public void testDayOfYearWithUnderscores(String date, int dayOfYear) {
private void testDayOfYearWithUnderscores(String date, int dayOfYear) {
FunctionExpression expression = DSL.day_of_year(DSL.literal(new ExprDateValue(date)));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(dayOfYear), eval(expression));
Expand Down Expand Up @@ -548,7 +620,7 @@ public void dayOfYearWithUnderscoresLeapYear() {
);
}

public void testInvalidDayOfYear(String date) {
private void testInvalidDayOfYear(String date) {
FunctionExpression expression = DSL.day_of_year(DSL.literal(new ExprDateValue(date)));
eval(expression);
}
Expand Down Expand Up @@ -714,7 +786,7 @@ public void month() {
assertEquals(integerValue(8), eval(expression));
}

public void testInvalidDates(String date) throws SemanticCheckException {
private void testInvalidDates(String date) throws SemanticCheckException {
FunctionExpression expression = DSL.month_of_year(DSL.literal(new ExprDateValue(date)));
eval(expression);
}
Expand Down
15 changes: 8 additions & 7 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1434,20 +1434,21 @@ Description

Usage: dayofweek(date) returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday).

The `day_of_week` function is also provided as an alias.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need an underscore to use this as an alias?

@GabeFernandez310 GabeFernandez310 Dec 29, 2022

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you do need the underscores. Both dayofweek and day_of_week work, but the version with the underscores is an alias to dayofweek which already exists and is implemented. However, day_ofweek and dayof_week do not work if that is what you are asking.


Argument type: STRING/DATE/DATETIME/TIMESTAMP

Return type: INTEGER

Example::

os> SELECT DAYOFWEEK(DATE('2020-08-26'))
os> SELECT DAYOFWEEK('2020-08-26'), DAY_OF_WEEK('2020-08-26')
fetched rows / total rows = 1/1
+---------------------------------+
| DAYOFWEEK(DATE('2020-08-26')) |
|---------------------------------|
| 4 |
+---------------------------------+

+---------------------------+-----------------------------+
| DAYOFWEEK('2020-08-26') | DAY_OF_WEEK('2020-08-26') |
|---------------------------+-----------------------------|
| 4 | 4 |
+---------------------------+-----------------------------+


DAYOFYEAR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,49 @@ public void testDayOfWeek() throws IOException {
verifyDataRows(result, rows(4));
}

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

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

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

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

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

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

result1 = executeQuery(String.format(
"SELECT dayofweek(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
result2 = executeQuery(String.format(
"SELECT day_of_week(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
}

@Test
public void testDayOfYear() throws IOException {
JSONObject result = executeQuery("select dayofyear(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 @@ -426,6 +426,7 @@ dateTimeFunctionName
| DAYOFMONTH
| DAYOFWEEK
| DAYOFYEAR
| DAY_OF_WEEK
| FROM_DAYS
| FROM_UNIXTIME
| HOUR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ public void can_parse_week_of_year_functions() {
assertNotNull(parser.parse("SELECT week_of_year('2022-11-18')"));
}

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

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