Skip to content

Commit 9ec1cc1

Browse files
Add Month_Of_Year Function To OpenSearch (#1129)
Signed-off-by: GabeFernandez310 <[email protected]>
1 parent 8ed26e6 commit 9ec1cc1

File tree

8 files changed

+125
-3
lines changed

8 files changed

+125
-3
lines changed

core/src/main/java/org/opensearch/sql/expression/DSL.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ public static FunctionExpression month(Expression... expressions) {
354354
return compile(FunctionProperties.None, BuiltinFunctionName.MONTH, expressions);
355355
}
356356

357+
public static FunctionExpression month_of_year(Expression... expressions) {
358+
return compile(FunctionProperties.None, BuiltinFunctionName.MONTH_OF_YEAR, expressions);
359+
}
360+
357361
public static FunctionExpression monthname(Expression... expressions) {
358362
return compile(FunctionProperties.None, BuiltinFunctionName.MONTHNAME, expressions);
359363
}

core/src/main/java/org/opensearch/sql/expression/datetime/DateTimeFunction.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ public void register(BuiltinFunctionRepository repository) {
113113
repository.register(maketime());
114114
repository.register(microsecond());
115115
repository.register(minute());
116-
repository.register(month());
116+
repository.register(month(BuiltinFunctionName.MONTH));
117+
repository.register(month(BuiltinFunctionName.MONTH_OF_YEAR));
117118
repository.register(monthName());
118119
repository.register(now());
119120
repository.register(period_add());
@@ -434,8 +435,8 @@ private DefaultFunctionResolver minute() {
434435
/**
435436
* MONTH(STRING/DATE/DATETIME/TIMESTAMP). return the month for date (1-12).
436437
*/
437-
private DefaultFunctionResolver month() {
438-
return define(BuiltinFunctionName.MONTH.getName(),
438+
private DefaultFunctionResolver month(BuiltinFunctionName month) {
439+
return define(month.getName(),
439440
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATE),
440441
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, DATETIME),
441442
impl(nullMissingHandling(DateTimeFunction::exprMonth), INTEGER, TIMESTAMP),

core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public enum BuiltinFunctionName {
7878
MICROSECOND(FunctionName.of("microsecond")),
7979
MINUTE(FunctionName.of("minute")),
8080
MONTH(FunctionName.of("month")),
81+
MONTH_OF_YEAR(FunctionName.of("month_of_year")),
8182
MONTHNAME(FunctionName.of("monthname")),
8283
PERIOD_ADD(FunctionName.of("period_add")),
8384
PERIOD_DIFF(FunctionName.of("period_diff")),

core/src/test/java/org/opensearch/sql/expression/datetime/DateTimeFunctionTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,44 @@ public void month() {
714714
assertEquals(integerValue(8), eval(expression));
715715
}
716716

717+
public void testInvalidDates(String date) throws SemanticCheckException {
718+
FunctionExpression expression = DSL.month_of_year(DSL.literal(new ExprDateValue(date)));
719+
eval(expression);
720+
}
721+
722+
@Test void monthOfYearInvalidDates() {
723+
when(nullRef.type()).thenReturn(DATE);
724+
when(missingRef.type()).thenReturn(DATE);
725+
assertEquals(nullValue(), eval(DSL.month_of_year(nullRef)));
726+
assertEquals(missingValue(), eval(DSL.month_of_year(missingRef)));
727+
728+
assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-01-50"));
729+
assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-02-29"));
730+
assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-02-31"));
731+
assertThrows(SemanticCheckException.class, () -> testInvalidDates("2019-13-05"));
732+
}
733+
734+
@Test
735+
public void monthOfYearAlternateArgumentSyntaxes() {
736+
lenient().when(nullRef.valueOf(env)).thenReturn(nullValue());
737+
lenient().when(missingRef.valueOf(env)).thenReturn(missingValue());
738+
739+
FunctionExpression expression = DSL.month_of_year(DSL.literal(new ExprDateValue("2020-08-07")));
740+
assertEquals(INTEGER, expression.type());
741+
assertEquals("month_of_year(DATE '2020-08-07')", expression.toString());
742+
assertEquals(integerValue(8), eval(expression));
743+
744+
expression = DSL.month_of_year(DSL.literal("2020-08-07"));
745+
assertEquals(INTEGER, expression.type());
746+
assertEquals("month_of_year(\"2020-08-07\")", expression.toString());
747+
assertEquals(integerValue(8), eval(expression));
748+
749+
expression = DSL.month_of_year(DSL.literal("2020-08-07 01:02:03"));
750+
assertEquals(INTEGER, expression.type());
751+
assertEquals("month_of_year(\"2020-08-07 01:02:03\")", expression.toString());
752+
assertEquals(integerValue(8), eval(expression));
753+
}
754+
717755
@Test
718756
public void monthName() {
719757
when(nullRef.type()).thenReturn(DATE);

docs/user/dql/functions.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,7 @@ Description
17701770
>>>>>>>>>>>
17711771

17721772
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.
1773+
The function month_of_year is also provided as an alias
17731774

17741775
Argument type: STRING/DATE/DATETIME/TIMESTAMP
17751776

@@ -1786,6 +1787,15 @@ Example::
17861787
+-----------------------------+
17871788

17881789

1790+
os> SELECT MONTH_OF_YEAR(DATE('2020-08-26'))
1791+
fetched rows / total rows = 1/1
1792+
+-------------------------------------+
1793+
| MONTH_OF_YEAR(DATE('2020-08-26')) |
1794+
|-------------------------------------|
1795+
| 8 |
1796+
+-------------------------------------+
1797+
1798+
17891799
MONTHNAME
17901800
---------
17911801

integ-test/src/test/java/org/opensearch/sql/sql/DateTimeFunctionIT.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,57 @@ public void testMonth() throws IOException {
375375
verifyDataRows(result, rows(9));
376376
}
377377

378+
@Test
379+
public void testMonthOfYearTypes() throws IOException {
380+
JSONObject result = executeQuery("select month_of_year(date('2020-09-16'))");
381+
verifySchema(result, schema("month_of_year(date('2020-09-16'))", null, "integer"));
382+
verifyDataRows(result, rows(9));
383+
384+
result = executeQuery("select month_of_year(datetime('2020-09-16 00:00:00'))");
385+
verifySchema(result, schema("month_of_year(datetime('2020-09-16 00:00:00'))", null, "integer"));
386+
verifyDataRows(result, rows(9));
387+
388+
result = executeQuery("select month_of_year(timestamp('2020-09-16 00:00:00'))");
389+
verifySchema(result, schema("month_of_year(timestamp('2020-09-16 00:00:00'))", null, "integer"));
390+
verifyDataRows(result, rows(9));
391+
392+
result = executeQuery("select month_of_year('2020-09-16')");
393+
verifySchema(result, schema("month_of_year('2020-09-16')", null, "integer"));
394+
verifyDataRows(result, rows(9));
395+
}
396+
397+
@Test
398+
public void testMonthAlternateSyntaxesReturnTheSameResults() throws IOException {
399+
JSONObject result1 = executeQuery("SELECT month(date('2022-11-22'))");
400+
JSONObject result2 = executeQuery("SELECT month_of_year(date('2022-11-22'))");
401+
verifyDataRows(result1, rows(11));
402+
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
403+
404+
result1 = executeQuery(String.format(
405+
"SELECT month(CAST(date0 AS date)) FROM %s", TEST_INDEX_CALCS));
406+
result2 = executeQuery(String.format(
407+
"SELECT month_of_year(CAST(date0 AS date)) FROM %s", TEST_INDEX_CALCS));
408+
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
409+
410+
result1 = executeQuery(String.format(
411+
"SELECT month(datetime(CAST(time0 AS STRING))) FROM %s", TEST_INDEX_CALCS));
412+
result2 = executeQuery(String.format(
413+
"SELECT month_of_year(datetime(CAST(time0 AS STRING))) FROM %s", TEST_INDEX_CALCS));
414+
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
415+
416+
result1 = executeQuery(String.format(
417+
"SELECT month(CAST(time0 AS STRING)) FROM %s", TEST_INDEX_CALCS));
418+
result2 = executeQuery(String.format(
419+
"SELECT month_of_year(CAST(time0 AS STRING)) FROM %s", TEST_INDEX_CALCS));
420+
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
421+
422+
result1 = executeQuery(String.format(
423+
"SELECT month(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
424+
result2 = executeQuery(String.format(
425+
"SELECT month_of_year(CAST(datetime0 AS timestamp)) FROM %s", TEST_INDEX_CALCS));
426+
result1.getJSONArray("datarows").similar(result2.getJSONArray("datarows"));
427+
}
428+
378429
@Test
379430
public void testMonthName() throws IOException {
380431
JSONObject result = executeQuery("select monthname(date('2020-09-16'))");

sql/src/main/antlr/OpenSearchSQLParser.g4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ datetimeConstantLiteral
247247
| DAY_OF_YEAR
248248
| LOCALTIME
249249
| LOCALTIMESTAMP
250+
| MONTH_OF_YEAR
250251
| UTC_TIMESTAMP
251252
| UTC_DATE
252253
| UTC_TIME

sql/src/test/java/org/opensearch/sql/sql/antlr/SQLSyntaxParserTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,22 @@ public void can_parse_dayofyear_functions() {
204204
assertNotNull(parser.parse("SELECT day_of_year('2022-11-18')"));
205205
}
206206

207+
@Test
208+
public void can_parse_month_of_year_function() {
209+
assertNotNull(parser.parse("SELECT month('2022-11-18')"));
210+
assertNotNull(parser.parse("SELECT month_of_year('2022-11-18')"));
211+
212+
assertNotNull(parser.parse("SELECT month(date('2022-11-18'))"));
213+
assertNotNull(parser.parse("SELECT month_of_year(date('2022-11-18'))"));
214+
215+
assertNotNull(parser.parse("SELECT month(datetime('2022-11-18 00:00:00'))"));
216+
assertNotNull(parser.parse("SELECT month_of_year(datetime('2022-11-18 00:00:00'))"));
217+
218+
assertNotNull(parser.parse("SELECT month(timestamp('2022-11-18 00:00:00'))"));
219+
assertNotNull(parser.parse("SELECT month_of_year(timestamp('2022-11-18 00:00:00'))"));
220+
221+
}
222+
207223
@Test
208224
public void can_parse_multi_match_relevance_function() {
209225
assertNotNull(parser.parse(

0 commit comments

Comments
 (0)