Skip to content

Commit

Permalink
Add Minute_Of_Day Function To SQL Plugin (#1207)
Browse files Browse the repository at this point in the history
Signed-off-by: GabeFernandez310 <gabrielf@bitquilltech.com>

Signed-off-by: GabeFernandez310 <gabrielf@bitquilltech.com>
  • Loading branch information
GabeFernandez310 authored Jan 3, 2023
1 parent 7714819 commit 2c46797
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 0 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 @@ -354,6 +354,10 @@ public static FunctionExpression minute(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.MINUTE, expressions);
}

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

public static FunctionExpression month(Expression... expressions) {
return compile(FunctionProperties.None, BuiltinFunctionName.MONTH, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package org.opensearch.sql.expression.datetime;

import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.MONTHS;
import static org.opensearch.sql.data.type.ExprCoreType.DATE;
import static org.opensearch.sql.data.type.ExprCoreType.DATETIME;
Expand Down Expand Up @@ -114,6 +115,7 @@ public void register(BuiltinFunctionRepository repository) {
repository.register(maketime());
repository.register(microsecond());
repository.register(minute());
repository.register(minute_of_day());
repository.register(month(BuiltinFunctionName.MONTH));
repository.register(month(BuiltinFunctionName.MONTH_OF_YEAR));
repository.register(monthName());
Expand Down Expand Up @@ -436,6 +438,19 @@ private DefaultFunctionResolver minute() {
);
}

/**
* MINUTE(STRING/TIME/DATETIME/TIMESTAMP). return the minute value for time.
*/
private DefaultFunctionResolver minute_of_day() {
return define(BuiltinFunctionName.MINUTE_OF_DAY.getName(),
impl(nullMissingHandling(DateTimeFunction::exprMinuteOfDay), INTEGER, STRING),
impl(nullMissingHandling(DateTimeFunction::exprMinuteOfDay), INTEGER, TIME),
impl(nullMissingHandling(DateTimeFunction::exprMinuteOfDay), INTEGER, DATE),
impl(nullMissingHandling(DateTimeFunction::exprMinuteOfDay), INTEGER, DATETIME),
impl(nullMissingHandling(DateTimeFunction::exprMinuteOfDay), INTEGER, TIMESTAMP)
);
}

/**
* MONTH(STRING/DATE/DATETIME/TIMESTAMP). return the month for date (1-12).
*/
Expand Down Expand Up @@ -933,6 +948,17 @@ private ExprValue exprMinute(ExprValue time) {
return new ExprIntegerValue(time.timeValue().getMinute());
}

/**
* Minute_of_day implementation for ExprValue.
*
* @param time ExprValue of Time/String type.
* @return ExprValue.
*/
private ExprValue exprMinuteOfDay(ExprValue time) {
return new ExprIntegerValue(
MINUTES.between(LocalTime.MIN, time.timeValue()));
}

/**
* Month for date implementation for ExprValue.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public enum BuiltinFunctionName {
MAKETIME(FunctionName.of("maketime")),
MICROSECOND(FunctionName.of("microsecond")),
MINUTE(FunctionName.of("minute")),
MINUTE_OF_DAY(FunctionName.of("minute_of_day")),
MONTH(FunctionName.of("month")),
MONTH_OF_YEAR(FunctionName.of("month_of_year")),
MONTHNAME(FunctionName.of("monthname")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,37 @@ public void hour() {
assertEquals("hour(\"2020-08-17 01:02:03\")", expression.toString());
}

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

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

assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("2022-12-14 12:23:3400"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("2022-12-14 12:2300:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("2022-12-14 1200:23:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("2022-12-1400 12:23:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("2022-1200-14 12:23:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("12:23:3400"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("12:2300:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("1200:23:34"));
assertThrows(SemanticCheckException.class,
() -> testInvalidMinuteOfDay("asdfasdfasdf"));

}

@Test
public void microsecond() {
when(nullRef.type()).thenReturn(TIME);
Expand Down Expand Up @@ -691,6 +722,48 @@ public void minute() {
assertEquals("minute(\"2020-08-17 01:02:03\")", expression.toString());
}

private void testMinuteOfDay(String date, int value) {
FunctionExpression expression = DSL.minute_of_day(DSL.literal(new ExprTimeValue(date)));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(value), eval(expression));
}

@Test
public void minuteOfDay() {
when(nullRef.type()).thenReturn(TIME);
when(missingRef.type()).thenReturn(TIME);
assertEquals(nullValue(), eval(DSL.minute_of_day(nullRef)));
assertEquals(missingValue(), eval(DSL.minute_of_day(missingRef)));

FunctionExpression expression = DSL.minute_of_day(DSL.literal(new ExprTimeValue("01:02:03")));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(62), eval(expression));
assertEquals("minute_of_day(TIME '01:02:03')", expression.toString());

expression = DSL.minute_of_day(DSL.literal("01:02:03"));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(62), eval(expression));
assertEquals("minute_of_day(\"01:02:03\")", expression.toString());

expression = DSL.minute_of_day(DSL.literal(new ExprTimestampValue("2020-08-17 01:02:03")));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(62), expression.valueOf(env));
assertEquals("minute_of_day(TIMESTAMP '2020-08-17 01:02:03')", expression.toString());

expression = DSL.minute_of_day(DSL.literal(new ExprDatetimeValue("2020-08-17 01:02:03")));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(62), expression.valueOf(env));
assertEquals("minute_of_day(DATETIME '2020-08-17 01:02:03')", expression.toString());

expression = DSL.minute_of_day(DSL.literal("2020-08-17 01:02:03"));
assertEquals(INTEGER, expression.type());
assertEquals(integerValue(62), expression.valueOf(env));
assertEquals("minute_of_day(\"2020-08-17 01:02:03\")", expression.toString());

testMinuteOfDay("2020-08-17 23:59:59", 1439);
testMinuteOfDay("2020-08-17 00:00:01", 0);
}

@Test
public void month() {
when(nullRef.type()).thenReturn(DATE);
Expand Down
22 changes: 22 additions & 0 deletions docs/user/dql/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,28 @@ Example::
| 2 |
+-----------------------------+

MINUTE_OF_DAY
------

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

Usage: minute_of_day(time) returns the minute value for time within a 24 hour day, in the range 0 to 1439.

Argument type: STRING/TIME/DATETIME/TIMESTAMP

Return type: INTEGER

Example::

os> SELECT MINUTE_OF_DAY((TIME '01:02:03'))
fetched rows / total rows = 1/1
+------------------------------------+
| MINUTE_OF_DAY((TIME '01:02:03')) |
|------------------------------------|
| 62 |
+------------------------------------+


MONTH
-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,30 @@ public void testMinute() throws IOException {
verifyDataRows(result, rows(30));
}


@Test
public void testMinuteOfDay() throws IOException {
JSONObject result = executeQuery("select minute_of_day(timestamp('2020-09-16 17:30:00'))");
verifySchema(result, schema("minute_of_day(timestamp('2020-09-16 17:30:00'))", null, "integer"));
verifyDataRows(result, rows(1050));

result = executeQuery("select minute_of_day(datetime('2020-09-16 17:30:00'))");
verifySchema(result, schema("minute_of_day(datetime('2020-09-16 17:30:00'))", null, "integer"));
verifyDataRows(result, rows(1050));

result = executeQuery("select minute_of_day(time('17:30:00'))");
verifySchema(result, schema("minute_of_day(time('17:30:00'))", null, "integer"));
verifyDataRows(result, rows(1050));

result = executeQuery("select minute_of_day('2020-09-16 17:30:00')");
verifySchema(result, schema("minute_of_day('2020-09-16 17:30:00')", null, "integer"));
verifyDataRows(result, rows(1050));

result = executeQuery("select minute_of_day('17:30:00')");
verifySchema(result, schema("minute_of_day('17:30:00')", null, "integer"));
verifyDataRows(result, rows(1050));
}

@Test
public void testMonth() throws IOException {
JSONObject result = executeQuery("select month(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 @@ -433,6 +433,7 @@ dateTimeFunctionName
| MAKETIME
| MICROSECOND
| MINUTE
| MINUTE_OF_DAY
| MONTH
| MONTHNAME
| NOW
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,14 @@ public void can_parse_match_phrase_relevance_function() {
assertNotNull(parser.parse("SELECT * FROM test WHERE match_phrase(column, 100500)"));
}

@Test
public void can_parse_minute_of_day_function() {
assertNotNull(parser.parse("SELECT minute_of_day(\"12:23:34\");"));
assertNotNull(parser.parse("SELECT minute_of_day('12:23:34');"));;
assertNotNull(parser.parse("SELECT minute_of_day(\"2022-12-14 12:23:34\");"));;
assertNotNull(parser.parse("SELECT minute_of_day('2022-12-14 12:23:34');"));;
}

@Test
public void can_parse_wildcard_query_relevance_function() {
assertNotNull(
Expand Down

0 comments on commit 2c46797

Please sign in to comment.