Skip to content

Commit

Permalink
Added support of timestamp/date/time using curly brackets (#1894)
Browse files Browse the repository at this point in the history
* Added support of timestamp/date/time using curly brackets (#297)

* added bracketed time/date/timestamp input, tests, and documentation

Signed-off-by: Matthew Wells <[email protected]>

* improved failing tests

Signed-off-by: Matthew Wells <[email protected]>

* simplified tests for checking for failure

Signed-off-by: Matthew Wells <[email protected]>

* fixed redundant tests and improved tests that should fail

Signed-off-by: Matthew Wells <[email protected]>

---------

Signed-off-by: Matthew Wells <[email protected]>
  • Loading branch information
matthewryanwells authored Jul 26, 2023
1 parent c8d42a7 commit 1a7134b
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 4 deletions.
11 changes: 10 additions & 1 deletion docs/user/dql/expressions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ A literal is a symbol that represents a value. The most common literal values in
1. Numeric literals: specify numeric values such as integer and floating-point numbers.
2. String literals: specify a string enclosed by single or double quotes.
3. Boolean literals: ``true`` or ``false``.
4. Date and Time literals: DATE 'YYYY-MM-DD' represent the date, TIME 'hh:mm:ss' represent the time, TIMESTAMP 'YYYY-MM-DD hh:mm:ss' represent the timestamp.
4. Date and Time literals: DATE 'YYYY-MM-DD' represent the date, TIME 'hh:mm:ss' represent the time, TIMESTAMP 'YYYY-MM-DD hh:mm:ss' represent the timestamp. You can also surround the literals with curly brackets, if you do, you can replace date with d, time with t, and timestamp with ts

Examples
--------
Expand All @@ -49,6 +49,15 @@ Here is an example for different type of literals::
| Hello | Hello | It"s | It's | It's | "Its" | It's | It\'s | \I\t\s |
+-----------+-----------+-----------+-----------+----------+-----------+-----------+-------------+------------+


os> SELECT {DATE '2020-07-07'}, {D '2020-07-07'}, {TIME '01:01:01'}, {T '01:01:01'}, {TIMESTAMP '2020-07-07 01:01:01'}, {TS '2020-07-07 01:01:01'}
fetched rows / total rows = 1/1
+-----------------------+--------------------+---------------------+------------------+-------------------------------------+------------------------------+
| {DATE '2020-07-07'} | {D '2020-07-07'} | {TIME '01:01:01'} | {T '01:01:01'} | {TIMESTAMP '2020-07-07 01:01:01'} | {TS '2020-07-07 01:01:01'} |
|-----------------------+--------------------+---------------------+------------------+-------------------------------------+------------------------------|
| 2020-07-07 | 2020-07-07 | 01:01:01 | 01:01:01 | 2020-07-07 01:01:01 | 2020-07-07 01:01:01 |
+-----------------------+--------------------+---------------------+------------------+-------------------------------------+------------------------------+

Limitations
-----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.opensearch.client.Request;
import org.opensearch.client.RequestOptions;
import org.opensearch.client.Response;
import org.opensearch.client.ResponseException;
import org.opensearch.sql.common.utils.StringUtils;
import org.opensearch.sql.legacy.SQLIntegTestCase;

Expand Down Expand Up @@ -1288,4 +1289,85 @@ protected JSONObject executeQuery(String query) throws IOException {
Response response = client().performRequest(request);
return new JSONObject(getResponseBody(response));
}

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

result = executeQuery("select {ts '2020-09-16 17:30:00'}");
verifySchema(result, schema("{ts '2020-09-16 17:30:00'}", null, "timestamp"));
verifyDataRows(result, rows("2020-09-16 17:30:00"));

result = executeQuery("select {timestamp '2020-09-16 17:30:00.123'}");
verifySchema(result, schema("{timestamp '2020-09-16 17:30:00.123'}", null, "timestamp"));
verifyDataRows(result, rows("2020-09-16 17:30:00.123"));

result = executeQuery("select {ts '2020-09-16 17:30:00.123'}");
verifySchema(result, schema("{ts '2020-09-16 17:30:00.123'}", null, "timestamp"));
verifyDataRows(result, rows("2020-09-16 17:30:00.123"));
}

@Test
public void testTimeBracket() throws IOException {
JSONObject result = executeQuery("select {time '17:30:00'}");
verifySchema(result, schema("{time '17:30:00'}", null, "time"));
verifyDataRows(result, rows("17:30:00"));

result = executeQuery("select {t '17:30:00'}");
verifySchema(result, schema("{t '17:30:00'}", null, "time"));
verifyDataRows(result, rows("17:30:00"));

result = executeQuery("select {time '17:30:00.123'}");
verifySchema(result, schema("{time '17:30:00.123'}", null, "time"));
verifyDataRows(result, rows("17:30:00.123"));

result = executeQuery("select {t '17:30:00.123'}");
verifySchema(result, schema("{t '17:30:00.123'}", null, "time"));
verifyDataRows(result, rows("17:30:00.123"));
}

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

result = executeQuery("select {d '2020-09-16'}");
verifySchema(result, schema("{d '2020-09-16'}", null, "date"));
verifyDataRows(result, rows("2020-09-16"));
}

private void compareBrackets(String query1, String query2, String datetime) throws IOException {
JSONObject result1 = executeQuery("select " + query1 + " '" + datetime + "'");
JSONObject result2 = executeQuery("select {" + query2 + " '" + datetime + "'}");

verifyDataRows(result1, rows(datetime));
verifyDataRows(result2, rows(datetime));
}

@Test
public void testBracketedEquivalent() throws IOException {
compareBrackets("timestamp", "timestamp", "2020-09-16 17:30:00");
compareBrackets("timestamp", "ts", "2020-09-16 17:30:00");
compareBrackets("timestamp", "timestamp", "2020-09-16 17:30:00.123");
compareBrackets("timestamp", "ts", "2020-09-16 17:30:00.123");
compareBrackets("date", "date", "2020-09-16");
compareBrackets("date", "d", "2020-09-16");
compareBrackets("time", "time", "17:30:00");
compareBrackets("time", "t", "17:30:00");
}

@Test
public void testBracketFails() {
assertThrows(ResponseException.class, ()->executeQuery("select {time '2020-09-16'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {t '2020-09-16'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {date '17:30:00'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {d '17:30:00'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {timestamp '2020-09-16'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {ts '2020-09-16'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {timestamp '17:30:00'}"));
assertThrows(ResponseException.class, ()->executeQuery("select {ts '17:30:00'}"));
}
}
4 changes: 3 additions & 1 deletion sql/src/main/antlr/OpenSearchSQLParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ constant
// Doesn't support the following types for now
//| BIT_STRING
//| NOT? nullLiteral=(NULL_LITERAL | NULL_SPEC_LITERAL)
//| LEFT_BRACE dateType=(D | T | TS | DATE | TIME | TIMESTAMP) stringLiteral RIGHT_BRACE
;

decimalLiteral
Expand Down Expand Up @@ -227,14 +226,17 @@ datetimeLiteral

dateLiteral
: DATE date=stringLiteral
| LEFT_BRACE (DATE | D) date=stringLiteral RIGHT_BRACE
;

timeLiteral
: TIME time=stringLiteral
| LEFT_BRACE (TIME | T) time=stringLiteral RIGHT_BRACE
;

timestampLiteral
: TIMESTAMP timestamp=stringLiteral
| LEFT_BRACE (TIMESTAMP | TS) timestamp=stringLiteral RIGHT_BRACE
;

// Actually, these constants are shortcuts to the corresponding functions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package org.opensearch.sql.common.antlr;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.opensearch.sql.sql.antlr.SQLSyntaxParser;

/**
* A base class for tests for SQL or PPL parser.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/


package org.opensearch.sql.sql.antlr;

import org.junit.jupiter.api.Test;

public class BracketedTimestampTest extends SQLParserTest {
@Test
void date_shortened_test() {
acceptQuery("SELECT {d '2001-05-07'}");
}

@Test
void date_test() {
acceptQuery("SELECT {date '2001-05-07'}");
}

@Test
void time_shortened_test() {
acceptQuery("SELECT {t '10:11:12'}");
}

@Test
void time_test() {
acceptQuery("SELECT {time '10:11:12'}");
}

@Test
void timestamp_shortened_test() {
acceptQuery("SELECT {ts '2001-05-07 10:11:12'}");
}

@Test
void timestamp_test() {
acceptQuery("SELECT {timestamp '2001-05-07 10:11:12'}");
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/


package org.opensearch.sql.sql.antlr;

import org.opensearch.sql.common.antlr.SyntaxParserTestBase;
Expand Down

0 comments on commit 1a7134b

Please sign in to comment.