Skip to content

Commit 0e6a648

Browse files
GumpacGacarbonettoGabeFernandez310MaxKsyunz
authored andcommitted
Support Alternate Datetime Formats (opensearch-project#1664)
* Support Alternate Datetime Formats (#268) * Add OpenSearchDateType as a datatype for matching with Date/Time OpenSearch types Signed-off-by: Andrew Carbonetto <[email protected]> --------- Signed-off-by: Andrew Carbonetto <[email protected]> Signed-off-by: GabeFernandez310 <[email protected]> Signed-off-by: Guian Gumpac <[email protected]> Signed-off-by: MaxKsyunz <[email protected]> Co-authored-by: Andrew Carbonetto <[email protected]> Co-authored-by: GabeFernandez310 <[email protected]> Co-authored-by: MaxKsyunz <[email protected]> Signed-off-by: Mitchell Gale <[email protected]>
1 parent 401cd9b commit 0e6a648

File tree

20 files changed

+1536
-272
lines changed

20 files changed

+1536
-272
lines changed

docs/user/general/datatypes.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ The table below list the mapping between OpenSearch Data Type, OpenSearch SQL Da
9191
+-----------------+---------------------+-----------+
9292
| text | text | VARCHAR |
9393
+-----------------+---------------------+-----------+
94-
| date | timestamp | TIMESTAMP |
94+
| date* | timestamp | TIMESTAMP |
9595
+-----------------+---------------------+-----------+
9696
| date_nanos | timestamp | TIMESTAMP |
9797
+-----------------+---------------------+-----------+
@@ -104,7 +104,11 @@ The table below list the mapping between OpenSearch Data Type, OpenSearch SQL Da
104104
| nested | array | STRUCT |
105105
+-----------------+---------------------+-----------+
106106

107-
Notes: Not all the OpenSearch SQL Type has correspond OpenSearch Type. e.g. data and time. To use function which required such data type, user should explicitly convert the data type.
107+
Notes:
108+
* Not all the OpenSearch SQL Type has correspond OpenSearch Type. e.g. data and time. To use function which required such data type, user should explicitly convert the data type.
109+
* date*: Maps to `timestamp` by default. Based on the "format" property `date` can map to `date` or `time`. See list of supported named formats `here <https://opensearch.org/docs/latest/field-types/supported-field-types/date/>`_.
110+
For example, `basic_date` will map to a `date` type, and `basic_time` will map to a `time` type.
111+
108112

109113
Data Type Conversion
110114
====================

integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,10 @@ public enum Index {
651651
"calcs",
652652
getMappingFile("calcs_index_mappings.json"),
653653
"src/test/resources/calcs.json"),
654+
DATE_FORMATS(TestsConstants.TEST_INDEX_DATE_FORMATS,
655+
"date_formats",
656+
getMappingFile("date_formats_index_mapping.json"),
657+
"src/test/resources/date_formats.json"),
654658
WILDCARD(TestsConstants.TEST_INDEX_WILDCARD,
655659
"wildcard",
656660
getMappingFile("wildcard_index_mappings.json"),

integ-test/src/test/java/org/opensearch/sql/legacy/TestsConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public class TestsConstants {
5656
public final static String TEST_INDEX_BEER = TEST_INDEX + "_beer";
5757
public final static String TEST_INDEX_NULL_MISSING = TEST_INDEX + "_null_missing";
5858
public final static String TEST_INDEX_CALCS = TEST_INDEX + "_calcs";
59+
public final static String TEST_INDEX_DATE_FORMATS = TEST_INDEX + "_date_formats";
5960
public final static String TEST_INDEX_WILDCARD = TEST_INDEX + "_wildcard";
6061
public final static String TEST_INDEX_MULTI_NESTED_TYPE = TEST_INDEX + "_multi_nested";
6162
public final static String TEST_INDEX_NESTED_WITH_NULLS = TEST_INDEX + "_nested_with_nulls";

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

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -383,17 +383,17 @@ public void testAvgDoubleInMemory() throws IOException {
383383

384384
@Test
385385
public void testMaxDatePushedDown() throws IOException {
386-
var response = executeQuery(String.format("SELECT max(CAST(date0 AS date))"
386+
var response = executeQuery(String.format("SELECT max(date0)"
387387
+ " from %s", TEST_INDEX_CALCS));
388-
verifySchema(response, schema("max(CAST(date0 AS date))", null, "date"));
388+
verifySchema(response, schema("max(date0)", null, "date"));
389389
verifyDataRows(response, rows("2004-06-19"));
390390
}
391391

392392
@Test
393393
public void testAvgDatePushedDown() throws IOException {
394-
var response = executeQuery(String.format("SELECT avg(CAST(date0 AS date))"
394+
var response = executeQuery(String.format("SELECT avg(date0)"
395395
+ " from %s", TEST_INDEX_CALCS));
396-
verifySchema(response, schema("avg(CAST(date0 AS date))", null, "date"));
396+
verifySchema(response, schema("avg(date0)", null, "date"));
397397
verifyDataRows(response, rows("1992-04-23"));
398398
}
399399

@@ -423,25 +423,25 @@ public void testAvgDateTimePushedDown() throws IOException {
423423

424424
@Test
425425
public void testMinTimePushedDown() throws IOException {
426-
var response = executeQuery(String.format("SELECT min(CAST(time1 AS time))"
426+
var response = executeQuery(String.format("SELECT min(time1)"
427427
+ " from %s", TEST_INDEX_CALCS));
428-
verifySchema(response, schema("min(CAST(time1 AS time))", null, "time"));
428+
verifySchema(response, schema("min(time1)", null, "time"));
429429
verifyDataRows(response, rows("00:05:57"));
430430
}
431431

432432
@Test
433433
public void testMaxTimePushedDown() throws IOException {
434-
var response = executeQuery(String.format("SELECT max(CAST(time1 AS time))"
434+
var response = executeQuery(String.format("SELECT max(time1)"
435435
+ " from %s", TEST_INDEX_CALCS));
436-
verifySchema(response, schema("max(CAST(time1 AS time))", null, "time"));
436+
verifySchema(response, schema("max(time1)", null, "time"));
437437
verifyDataRows(response, rows("22:50:16"));
438438
}
439439

440440
@Test
441441
public void testAvgTimePushedDown() throws IOException {
442-
var response = executeQuery(String.format("SELECT avg(CAST(time1 AS time))"
442+
var response = executeQuery(String.format("SELECT avg(time1)"
443443
+ " from %s", TEST_INDEX_CALCS));
444-
verifySchema(response, schema("avg(CAST(time1 AS time))", null, "time"));
444+
verifySchema(response, schema("avg(time1)", null, "time"));
445445
verifyDataRows(response, rows("13:06:36.25"));
446446
}
447447

@@ -471,28 +471,28 @@ public void testAvgTimeStampPushedDown() throws IOException {
471471

472472
@Test
473473
public void testMinDateInMemory() throws IOException {
474-
var response = executeQuery(String.format("SELECT min(CAST(date0 AS date))"
474+
var response = executeQuery(String.format("SELECT min(date0)"
475475
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
476476
verifySchema(response,
477-
schema("min(CAST(date0 AS date)) OVER(PARTITION BY datetime1)", null, "date"));
477+
schema("min(date0) OVER(PARTITION BY datetime1)", null, "date"));
478478
verifySome(response.getJSONArray("datarows"), rows("1972-07-04"));
479479
}
480480

481481
@Test
482482
public void testMaxDateInMemory() throws IOException {
483-
var response = executeQuery(String.format("SELECT max(CAST(date0 AS date))"
483+
var response = executeQuery(String.format("SELECT max(date0)"
484484
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
485485
verifySchema(response,
486-
schema("max(CAST(date0 AS date)) OVER(PARTITION BY datetime1)", null, "date"));
486+
schema("max(date0) OVER(PARTITION BY datetime1)", null, "date"));
487487
verifySome(response.getJSONArray("datarows"), rows("2004-06-19"));
488488
}
489489

490490
@Test
491491
public void testAvgDateInMemory() throws IOException {
492-
var response = executeQuery(String.format("SELECT avg(CAST(date0 AS date))"
492+
var response = executeQuery(String.format("SELECT avg(date0)"
493493
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
494494
verifySchema(response,
495-
schema("avg(CAST(date0 AS date)) OVER(PARTITION BY datetime1)", null, "date"));
495+
schema("avg(date0) OVER(PARTITION BY datetime1)", null, "date"));
496496
verifySome(response.getJSONArray("datarows"), rows("1992-04-23"));
497497
}
498498

@@ -525,28 +525,28 @@ public void testAvgDateTimeInMemory() throws IOException {
525525

526526
@Test
527527
public void testMinTimeInMemory() throws IOException {
528-
var response = executeQuery(String.format("SELECT min(CAST(time1 AS time))"
528+
var response = executeQuery(String.format("SELECT min(time1)"
529529
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
530530
verifySchema(response,
531-
schema("min(CAST(time1 AS time)) OVER(PARTITION BY datetime1)", null, "time"));
531+
schema("min(time1) OVER(PARTITION BY datetime1)", null, "time"));
532532
verifySome(response.getJSONArray("datarows"), rows("00:05:57"));
533533
}
534534

535535
@Test
536536
public void testMaxTimeInMemory() throws IOException {
537-
var response = executeQuery(String.format("SELECT max(CAST(time1 AS time))"
537+
var response = executeQuery(String.format("SELECT max(time1)"
538538
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
539539
verifySchema(response,
540-
schema("max(CAST(time1 AS time)) OVER(PARTITION BY datetime1)", null, "time"));
540+
schema("max(time1) OVER(PARTITION BY datetime1)", null, "time"));
541541
verifySome(response.getJSONArray("datarows"), rows("22:50:16"));
542542
}
543543

544544
@Test
545545
public void testAvgTimeInMemory() throws IOException {
546-
var response = executeQuery(String.format("SELECT avg(CAST(time1 AS time))"
546+
var response = executeQuery(String.format("SELECT avg(time1)"
547547
+ " OVER(PARTITION BY datetime1) from %s", TEST_INDEX_CALCS));
548548
verifySchema(response,
549-
schema("avg(CAST(time1 AS time)) OVER(PARTITION BY datetime1)", null, "time"));
549+
schema("avg(time1) OVER(PARTITION BY datetime1)", null, "time"));
550550
verifySome(response.getJSONArray("datarows"), rows("13:06:36.25"));
551551
}
552552

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
7+
package org.opensearch.sql.sql;
8+
9+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATE_FORMATS;
10+
import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT;
11+
import static org.opensearch.sql.util.MatcherUtils.rows;
12+
import static org.opensearch.sql.util.MatcherUtils.schema;
13+
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
14+
import static org.opensearch.sql.util.MatcherUtils.verifySchema;
15+
import static org.opensearch.sql.util.TestUtils.getResponseBody;
16+
17+
import java.io.IOException;
18+
import java.util.Locale;
19+
import org.json.JSONObject;
20+
import org.junit.jupiter.api.Test;
21+
import org.opensearch.client.Request;
22+
import org.opensearch.client.RequestOptions;
23+
import org.opensearch.client.Response;
24+
import org.opensearch.sql.legacy.SQLIntegTestCase;
25+
26+
public class DateTimeFormatsIT extends SQLIntegTestCase {
27+
28+
@Override
29+
public void init() throws Exception {
30+
super.init();
31+
loadIndex(Index.DATE_FORMATS);
32+
}
33+
34+
@Test
35+
public void testReadingDateFormats() throws IOException {
36+
String query = String.format("SELECT weekyear_week_day, hour_minute_second_millis," +
37+
" strict_ordinal_date_time FROM %s LIMIT 1", TEST_INDEX_DATE_FORMATS);
38+
JSONObject result = executeQuery(query);
39+
verifySchema(result,
40+
schema("weekyear_week_day", null, "date"),
41+
schema("hour_minute_second_millis", null, "time"),
42+
schema("strict_ordinal_date_time", null, "timestamp"));
43+
verifyDataRows(result,
44+
rows("1984-04-12",
45+
"09:07:42",
46+
"1984-04-12 09:07:42.000123456"
47+
));
48+
}
49+
50+
@Test
51+
public void testDateFormatsWithOr() throws IOException {
52+
String query = String.format("SELECT yyyy-MM-dd_OR_epoch_millis FROM %s", TEST_INDEX_DATE_FORMATS);
53+
JSONObject result = executeQuery(query);
54+
verifyDataRows(result,
55+
rows("1984-04-12 00:00:00"),
56+
rows("1984-04-12 09:07:42.000123456"));
57+
}
58+
59+
protected JSONObject executeQuery(String query) throws IOException {
60+
Request request = new Request("POST", QUERY_API_ENDPOINT);
61+
request.setJsonEntity(String.format(Locale.ROOT, "{\n" + " \"query\": \"%s\"\n" + "}", query));
62+
63+
RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder();
64+
restOptionsBuilder.addHeader("Content-Type", "application/json");
65+
request.setOptions(restOptionsBuilder);
66+
67+
Response response = client().performRequest(request);
68+
return new JSONObject(getResponseBody(response));
69+
}
70+
}

0 commit comments

Comments
 (0)