diff --git a/docs/reference/sql/endpoints/rest.asciidoc b/docs/reference/sql/endpoints/rest.asciidoc index 2f9be5da17d65..1e8f1ae8b977e 100644 --- a/docs/reference/sql/endpoints/rest.asciidoc +++ b/docs/reference/sql/endpoints/rest.asciidoc @@ -305,7 +305,12 @@ Which looks like: -------------------------------------------------- // TESTRESPONSE[s/sDXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAAEWODRMaXBUaVlRN21iTlRyWHZWYUdrdw==:BAFmBmF1dGhvcgFmBG5hbWUBZgpwYWdlX2NvdW50AWYMcmVsZWFzZV9kYXRl9f\/\/\/w8=/$body.cursor/] -Note that the `columns` object is only part of the first page. +[NOTE] +The `columns` object is only part of the first page. +[NOTE] +If in the initial HTTP request, that specifies the SQL query, there was a <> +param passed, the same `time_zone` parameter should be passed to the subsequent `cursor` requests in order to keep +applying the same `time_zone` (as in the initial HTTP request) the result data of each subsequent page. You've reached the last page when there is no `cursor` returned in the results. Like Elasticsearch's <>, @@ -509,6 +514,7 @@ s|Description |45s |The timeout before a pagination request fails. +[[sql-rest-param-timezone]] |time_zone |`Z` (or `UTC`) |Time-zone in ISO 8601 used for executing the query on the server. @@ -533,4 +539,4 @@ More information available https://docs.oracle.com/javase/8/docs/api/java/time/Z |=== Do note that most parameters (outside the timeout and `columnar` ones) make sense only during the initial query - any follow-up pagination request only requires the `cursor` parameter as explained in the <> chapter. -That's because the query has already been executed and the calls are simply about returning the found results - thus the parameters are simply ignored. \ No newline at end of file +That's because the query has already been executed and the calls are simply about returning the found results - thus the parameters are simply ignored. diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java index 925187db405aa..b51d16a018133 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/JdbcHttpClient.java @@ -75,7 +75,7 @@ Cursor query(String sql, List params, RequestMeta meta) thro * the scroll id to use to fetch the next page. */ Tuple>> nextPage(String cursor, RequestMeta meta) throws SQLException { - SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, TimeValue.timeValueMillis(meta.timeoutInMs()), + SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, conCfg.zoneId(), TimeValue.timeValueMillis(meta.timeoutInMs()), TimeValue.timeValueMillis(meta.queryTimeoutInMs()), new RequestInfo(Mode.JDBC), conCfg.binaryCommunication()); SqlQueryResponse response = httpClient.query(sqlRequest); return new Tuple<>(response.cursor(), response.rows()); diff --git a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/FetchSizeTestCase.java b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/FetchSizeTestCase.java index 61cd6e93c1831..d7b2742838e5a 100644 --- a/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/FetchSizeTestCase.java +++ b/x-pack/plugin/sql/qa/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/FetchSizeTestCase.java @@ -16,7 +16,12 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Properties; +import static org.elasticsearch.xpack.sql.qa.jdbc.JdbcTestUtils.JDBC_TIMEZONE; import static org.elasticsearch.xpack.sql.qa.rest.RestSqlTestCase.assertNoSearchContexts; /** @@ -121,6 +126,52 @@ public void testAggregation() throws SQLException { } } } + + public void testWithDatetimeAndTimezoneParam() throws IOException, SQLException { + Request request = new Request("PUT", "/test_date_timezone"); + XContentBuilder createIndex = JsonXContent.contentBuilder().startObject(); + createIndex.startObject("mappings"); + { + createIndex.startObject("properties"); + { + createIndex.startObject("date").field("type", "date").field("format", "epoch_millis"); + createIndex.endObject(); + } + createIndex.endObject(); + } + createIndex.endObject().endObject(); + request.setJsonEntity(Strings.toString(createIndex)); + client().performRequest(request); + + request = new Request("PUT", "/test_date_timezone/_bulk"); + request.addParameter("refresh", "true"); + StringBuilder bulk = new StringBuilder(); + long[] datetimes = new long[] { 1_000, 10_000, 100_000, 1_000_000, 10_000_000 }; + for (int i = 0; i < datetimes.length; i++) { + bulk.append("{\"index\":{}}\n"); + bulk.append("{\"date\":").append(datetimes[i]).append("}\n"); + } + request.setJsonEntity(bulk.toString()); + assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); + + ZoneId zoneId = randomZone(); + Properties connectionProperties = connectionProperties(); + connectionProperties.put(JDBC_TIMEZONE, zoneId.toString()); + try (Connection c = esJdbc(connectionProperties); + Statement s = c.createStatement()) { + s.setFetchSize(2); + try (ResultSet rs = + s.executeQuery("SELECT DATE_PART('TZOFFSET', date) FROM test_date_timezone ORDER BY date")) { + for (int i = 0; i < datetimes.length; i++) { + assertEquals(2, rs.getFetchSize()); + assertTrue("No more entries left at " + i, rs.next()); + assertEquals(ZonedDateTime.ofInstant(Instant.ofEpochMilli(datetimes[i]), zoneId).getOffset() + .getTotalSeconds()/ 60, rs.getInt(1)); + } + assertFalse(rs.next()); + } + } + } /** * Test for nested documents. @@ -237,4 +288,4 @@ private void addPivotData() throws Exception { request.setJsonEntity(bulk.toString()); assertEquals(200, client().performRequest(request).getStatusLine().getStatusCode()); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java index 32630abb94370..bd52d64a39878 100644 --- a/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java +++ b/x-pack/plugin/sql/sql-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java @@ -83,7 +83,7 @@ public SqlQueryResponse query(SqlQueryRequest sqlRequest) throws SQLException { public SqlQueryResponse nextPage(String cursor) throws SQLException { // method called only from CLI - SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, TimeValue.timeValueMillis(cfg.queryTimeout()), + SqlQueryRequest sqlRequest = new SqlQueryRequest(cursor, Protocol.TIME_ZONE, TimeValue.timeValueMillis(cfg.queryTimeout()), TimeValue.timeValueMillis(cfg.pageTimeout()), new RequestInfo(Mode.CLI), cfg.binaryCommunication()); return post(Protocol.SQL_QUERY_REST_ENDPOINT, sqlRequest, SqlQueryResponse::fromXContent); } diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java index e6d42c3898a91..755a50f6f27a7 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java @@ -55,9 +55,9 @@ public SqlQueryRequest(String query, List params, ZoneId zon this.binaryCommunication = binaryCommunication; } - public SqlQueryRequest(String cursor, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo, + public SqlQueryRequest(String cursor, ZoneId zoneId, TimeValue requestTimeout, TimeValue pageTimeout, RequestInfo requestInfo, boolean binaryCommunication) { - this("", Collections.emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, + this("", Collections.emptyList(), zoneId, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, null, false, cursor, requestInfo, Protocol.FIELD_MULTI_VALUE_LENIENCY, Protocol.INDEX_INCLUDE_FROZEN, binaryCommunication); } @@ -220,4 +220,4 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws } return builder; } -} \ No newline at end of file +}