Skip to content

Commit

Permalink
Add Month_Of_Year Function To OpenSearch
Browse files Browse the repository at this point in the history
Signed-off-by: GabeFernandez310 <[email protected]>
  • Loading branch information
GabeFernandez310 committed Dec 1, 2022
1 parent e280866 commit c5c5c74
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 4 deletions.
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 @@ -345,6 +345,10 @@ public static FunctionExpression month(Expression... expressions) {
return compile(BuiltinFunctionName.MONTH, expressions);
}

public static FunctionExpression month_of_year(Expression... expressions) {
return compile(BuiltinFunctionName.MONTH_OF_YEAR, expressions);
}

public static FunctionExpression monthname(Expression... expressions) {
return compile(BuiltinFunctionName.MONTHNAME, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ public void register(BuiltinFunctionRepository repository) {
repository.register(maketime());
repository.register(microsecond());
repository.register(minute());
repository.register(month());
repository.register(month(BuiltinFunctionName.MONTH));
repository.register(month(BuiltinFunctionName.MONTH_OF_YEAR));
repository.register(monthName());
repository.register(now());
repository.register(period_add());
Expand Down Expand Up @@ -415,8 +416,8 @@ private DefaultFunctionResolver minute() {
/**
* MONTH(STRING/DATE/DATETIME/TIMESTAMP). return the month for date (1-12).
*/
private DefaultFunctionResolver month() {
return define(BuiltinFunctionName.MONTH.getName(),
private DefaultFunctionResolver month(BuiltinFunctionName month) {
return define(month.getName(),
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATE),
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATETIME),
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, TIMESTAMP),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public enum BuiltinFunctionName {
MICROSECOND(FunctionName.of("microsecond")),
MINUTE(FunctionName.of("minute")),
MONTH(FunctionName.of("month")),
MONTH_OF_YEAR(FunctionName.of("month_of_year")),
MONTHNAME(FunctionName.of("monthname")),
PERIOD_ADD(FunctionName.of("period_add")),
PERIOD_DIFF(FunctionName.of("period_diff")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.when;
import static org.opensearch.sql.data.model.ExprValueUtils.integerValue;
import static org.opensearch.sql.data.model.ExprValueUtils.longValue;
Expand Down Expand Up @@ -625,6 +626,44 @@ public void month() {
assertEquals(integerValue(8), eval(expression));
}

public void testInvalidDates(String date) throws SemanticCheckException {
FunctionExpression expression = DSL.month_of_year(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)));

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"));
}

@Test
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")));
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"));
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"));
assertEquals(INTEGER, expression.type());
assertEquals("month_of_year(\"2020-08-07 01:02:03\")", expression.toString());
assertEquals(integerValue(8), eval(expression));
}

@Test
public void monthName() {
when(nullRef.type()).thenReturn(DATE);
Expand Down
10 changes: 10 additions & 0 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,7 @@ 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

Argument type: STRING/DATE/DATETIME/TIMESTAMP

Expand All @@ -1715,6 +1716,15 @@ Example::
+-----------------------------+


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


MONTHNAME
---------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package org.opensearch.sql.sql;

import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_CALCS;
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_PEOPLE2;
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
import static org.opensearch.sql.util.MatcherUtils.rows;
Expand Down Expand Up @@ -49,6 +50,7 @@ public void init() throws Exception {
super.init();
loadIndex(Index.BANK);
loadIndex(Index.PEOPLE2);
loadIndex(Index.CALCS);
}

@Test
Expand Down Expand Up @@ -322,6 +324,57 @@ public void testMonth() throws IOException {
verifyDataRows(result, rows(9));
}

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

result = executeQuery("select month_of_year(datetime('2020-09-16 00:00:00'))");
verifySchema(result, schema("month_of_year(datetime('2020-09-16 00:00:00'))", null, "integer"));
verifyDataRows(result, rows(9));

result = executeQuery("select month_of_year(timestamp('2020-09-16 00:00:00'))");
verifySchema(result, schema("month_of_year(timestamp('2020-09-16 00:00:00'))", null, "integer"));
verifyDataRows(result, rows(9));

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

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

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

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

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

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

@Test
public void testMonthName() throws IOException {
JSONObject result = executeQuery("select monthname(date('2020-09-16'))");
Expand Down
2 changes: 1 addition & 1 deletion sql/src/main/antlr/OpenSearchSQLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ trigonometricFunctionName
dateTimeFunctionName
: ADDDATE | CONVERT_TZ | DATE | DATE_ADD | DATE_FORMAT | DATE_SUB
| DATETIME | DAY | DAYNAME | DAYOFMONTH | DAYOFWEEK | DAYOFYEAR | FROM_DAYS | FROM_UNIXTIME
| HOUR | MAKEDATE | MAKETIME | MICROSECOND | MINUTE | MONTH | MONTHNAME | PERIOD_ADD
| HOUR | MAKEDATE | MAKETIME | MICROSECOND | MINUTE | MONTH | MONTHNAME | MONTH_OF_YEAR | PERIOD_ADD
| PERIOD_DIFF | QUARTER | SECOND | SUBDATE | SYSDATE | TIME | TIME_TO_SEC
| TIMESTAMP | TO_DAYS | UNIX_TIMESTAMP | WEEK | YEAR
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,22 @@ public void can_parse_now_like_functions(String name, Boolean hasFsp, Boolean ha
assertNotNull(parser.parse("SELECT id FROM test WHERE " + String.join(" AND ", calls)));
}

@Test
public void can_parse_month_of_year_function() {
assertNotNull(parser.parse("SELECT month('2022-11-18')"));
assertNotNull(parser.parse("SELECT month_of_year('2022-11-18')"));

assertNotNull(parser.parse("SELECT month(date('2022-11-18'))"));
assertNotNull(parser.parse("SELECT month_of_year(date('2022-11-18'))"));

assertNotNull(parser.parse("SELECT month(datetime('2022-11-18 00:00:00'))"));
assertNotNull(parser.parse("SELECT month_of_year(datetime('2022-11-18 00:00:00'))"));

assertNotNull(parser.parse("SELECT month(timestamp('2022-11-18 00:00:00'))"));
assertNotNull(parser.parse("SELECT month_of_year(timestamp('2022-11-18 00:00:00'))"));

}

@Test
public void can_parse_multi_match_relevance_function() {
assertNotNull(parser.parse(
Expand Down

0 comments on commit c5c5c74

Please sign in to comment.