diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcConnection.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcConnection.java index 17f8973cea386..0eb1888487cf1 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcConnection.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcConnection.java @@ -43,6 +43,10 @@ public class JdbcConnection implements Connection, JdbcWrapper { private String catalog; private String schema; + /** + * The SQLException is the only type of Exception the JDBC API can throw (and that the user expects). + * If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown + */ public JdbcConnection(JdbcConfiguration connectionInfo) throws SQLException { cfg = connectionInfo; client = new JdbcHttpClient(connectionInfo); @@ -428,4 +432,4 @@ int esInfoMajorVersion() throws SQLException { int esInfoMinorVersion() throws SQLException { return client.serverInfo().minorVersion; } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcStatement.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcStatement.java index fab21c541799e..c773dd5d17dc1 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcStatement.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcStatement.java @@ -7,7 +7,7 @@ import org.elasticsearch.xpack.sql.jdbc.net.client.Cursor; import org.elasticsearch.xpack.sql.jdbc.net.client.RequestMeta; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.sql.Connection; import java.sql.ResultSet; @@ -220,7 +220,7 @@ public int getFetchSize() throws SQLException { // unset (in this case -1 which the user cannot set) - in this case, the default fetch size is returned // 0 meaning the hint is disabled (the user has called setFetch) // >0 means actual hint - + // tl;dr - unless the user set it, returning the default is fine return requestMeta.fetchSize(); } @@ -402,4 +402,4 @@ final void resultSetWasClosed() throws SQLException { close(); } } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/PreparedQuery.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/PreparedQuery.java index 4aaf337f2b772..06825ee6e3f96 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/PreparedQuery.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/PreparedQuery.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.sql.jdbc.jdbc; import org.elasticsearch.xpack.sql.jdbc.JdbcSQLException; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.type.DataType; import java.sql.JDBCType; @@ -73,7 +73,7 @@ String sql() { */ List params() { return Arrays.stream(this.params).map( - paramInfo -> new SqlTypedParamValue(paramInfo.value, DataType.fromJdbcType(paramInfo.type)) + paramInfo -> new SqlTypedParamValue(DataType.fromJdbcType(paramInfo.type), paramInfo.value) ).collect(Collectors.toList()); } @@ -86,4 +86,4 @@ public String toString() { static PreparedQuery prepare(String sql) throws SQLException { return new PreparedQuery(sql, SqlQueryParameterAnalyzer.parametersCount(sql)); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/client/JdbcHttpClient.java b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/client/JdbcHttpClient.java index ab4cdff985863..89ee78e0bae9e 100644 --- a/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/client/JdbcHttpClient.java +++ b/x-pack/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/net/client/JdbcHttpClient.java @@ -5,22 +5,21 @@ */ package org.elasticsearch.xpack.sql.jdbc.net.client; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcConfiguration; import org.elasticsearch.xpack.sql.jdbc.net.protocol.ColumnInfo; import org.elasticsearch.xpack.sql.jdbc.net.protocol.InfoResponse; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest; -import org.elasticsearch.xpack.sql.plugin.SqlQueryRequest; -import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; +import org.elasticsearch.xpack.sql.proto.SqlQueryRequest; +import org.elasticsearch.xpack.sql.proto.MainResponse; +import org.elasticsearch.xpack.sql.proto.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.sql.SQLException; import java.util.List; -import java.util.TimeZone; import java.util.stream.Collectors; import static org.elasticsearch.xpack.sql.client.shared.StringUtils.EMPTY; @@ -34,6 +33,10 @@ public class JdbcHttpClient { private final JdbcConfiguration conCfg; private InfoResponse serverInfo; + /** + * The SQLException is the only type of Exception the JDBC API can throw (and that the user expects). + * If we remove it, we need to make sure no other types of Exceptions (runtime or otherwise) are thrown + */ public JdbcHttpClient(JdbcConfiguration conCfg) throws SQLException { httpClient = new HttpClient(conCfg); this.conCfg = conCfg; @@ -45,9 +48,9 @@ public boolean ping(long timeoutInMs) throws SQLException { public Cursor query(String sql, List params, RequestMeta meta) throws SQLException { int fetch = meta.fetchSize() > 0 ? meta.fetchSize() : conCfg.pageSize(); - SqlQueryRequest sqlRequest = new SqlQueryRequest(AbstractSqlRequest.Mode.JDBC, sql, params, null, - AbstractSqlQueryRequest.DEFAULT_TIME_ZONE, - fetch, TimeValue.timeValueMillis(meta.timeoutInMs()), TimeValue.timeValueMillis(meta.queryTimeoutInMs()), ""); + SqlQueryRequest sqlRequest = new SqlQueryRequest(Mode.JDBC, sql, params, null, + Protocol.TIME_ZONE, + fetch, TimeValue.timeValueMillis(meta.timeoutInMs()), TimeValue.timeValueMillis(meta.queryTimeoutInMs())); SqlQueryResponse response = httpClient.query(sqlRequest); return new DefaultCursor(this, response.cursor(), toJdbcColumnInfo(response.columns()), response.rows(), meta); } @@ -57,10 +60,8 @@ public Cursor query(String sql, List params, RequestMeta met * the scroll id to use to fetch the next page. */ public Tuple>> nextPage(String cursor, RequestMeta meta) throws SQLException { - SqlQueryRequest sqlRequest = new SqlQueryRequest().cursor(cursor); - sqlRequest.mode(AbstractSqlRequest.Mode.JDBC); - sqlRequest.requestTimeout(TimeValue.timeValueMillis(meta.timeoutInMs())); - sqlRequest.pageTimeout(TimeValue.timeValueMillis(meta.queryTimeoutInMs())); + SqlQueryRequest sqlRequest = new SqlQueryRequest(Mode.JDBC, cursor, TimeValue.timeValueMillis(meta.timeoutInMs()), + TimeValue.timeValueMillis(meta.queryTimeoutInMs())); SqlQueryResponse response = httpClient.query(sqlRequest); return new Tuple<>(response.cursor(), response.rows()); } @@ -78,13 +79,13 @@ public InfoResponse serverInfo() throws SQLException { private InfoResponse fetchServerInfo() throws SQLException { MainResponse mainResponse = httpClient.serverInfo(); - return new InfoResponse(mainResponse.getClusterName().value(), mainResponse.getVersion().major, mainResponse.getVersion().minor); + return new InfoResponse(mainResponse.getClusterName(), mainResponse.getVersion().major, mainResponse.getVersion().minor); } /** * Converts REST column metadata into JDBC column metadata */ - private List toJdbcColumnInfo(List columns) { + private List toJdbcColumnInfo(List columns) { return columns.stream().map(columnInfo -> new ColumnInfo(columnInfo.name(), columnInfo.jdbcType(), EMPTY, EMPTY, EMPTY, EMPTY, columnInfo.displaySize()) ).collect(Collectors.toList()); diff --git a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/jdbc/TypeConverterTests.java b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/jdbc/TypeConverterTests.java index 612c46fbe56ef..dc4ba9fa244b5 100644 --- a/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/jdbc/TypeConverterTests.java +++ b/x-pack/plugin/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/jdbc/TypeConverterTests.java @@ -10,8 +10,8 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest; import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.Mode; import org.joda.time.DateTime; import java.sql.JDBCType; @@ -51,7 +51,7 @@ private Object convertAsNative(Object value, JDBCType type) throws Exception { XContentBuilder builder = JsonXContent.contentBuilder(); builder.startObject(); builder.field("value"); - SqlQueryResponse.value(builder, AbstractSqlRequest.Mode.JDBC, value); + SqlQueryResponse.value(builder, Mode.JDBC, value); builder.endObject(); builder.close(); Object copy = XContentHelper.convertToMap(BytesReference.bytes(builder), false, builder.contentType()).v2().get("value"); diff --git a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java index 64f38c2254c5f..8e030f36dd042 100644 --- a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java +++ b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java @@ -5,11 +5,12 @@ */ package org.elasticsearch.xpack.sql.cli.command; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.shared.ClientException; import org.elasticsearch.xpack.sql.client.shared.Version; import org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest; +import org.elasticsearch.xpack.sql.proto.MainResponse; +import org.elasticsearch.xpack.sql.proto.Protocol; import java.sql.SQLException; @@ -18,7 +19,7 @@ */ public class CliSession { private final HttpClient httpClient; - private int fetchSize = AbstractSqlQueryRequest.DEFAULT_FETCH_SIZE; + private int fetchSize = Protocol.FETCH_SIZE; private String fetchSeparator = ""; private boolean debug; diff --git a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommand.java b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommand.java index 635c041da7ae6..e637386f9798f 100644 --- a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommand.java +++ b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommand.java @@ -5,8 +5,8 @@ */ package org.elasticsearch.xpack.sql.cli.command; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.xpack.sql.cli.CliTerminal; +import org.elasticsearch.xpack.sql.proto.MainResponse; import java.sql.SQLException; import java.util.Locale; @@ -30,7 +30,7 @@ public boolean doHandle(CliTerminal terminal, CliSession cliSession, String line } terminal.line() .text("Node:").em(info.getNodeName()) - .text(" Cluster:").em(info.getClusterName().value()) + .text(" Cluster:").em(info.getClusterName()) .text(" Version:").em(info.getVersion().toString()) .ln(); return true; diff --git a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java index c1fc609c50b8f..aa8bc499cd29e 100644 --- a/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java +++ b/x-pack/plugin/sql/sql-cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.shared.JreHttpUrlConnection; import org.elasticsearch.xpack.sql.plugin.CliFormatter; -import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.SqlQueryResponse; import java.sql.SQLException; @@ -23,8 +23,8 @@ protected boolean doHandle(CliTerminal terminal, CliSession cliSession, String l String data; try { response = cliClient.queryInit(line, cliSession.getFetchSize()); - cliFormatter = new CliFormatter(response); - data = cliFormatter.formatWithHeader(response); + cliFormatter = new CliFormatter(response.columns(), response.rows()); + data = cliFormatter.formatWithHeader(response.columns(), response.rows()); while (true) { handleText(terminal, data); if (response.cursor().isEmpty()) { @@ -36,7 +36,7 @@ protected boolean doHandle(CliTerminal terminal, CliSession cliSession, String l terminal.println(cliSession.getFetchSeparator()); } response = cliSession.getClient().nextPage(response.cursor()); - data = cliFormatter.formatWithoutHeader(response); + data = cliFormatter.formatWithoutHeader(response.rows()); } } catch (SQLException e) { if (JreHttpUrlConnection.SQL_STATE_BAD_SERVER.equals(e.getSQLState())) { diff --git a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java index befcddf9e7d25..e5643ad443a59 100644 --- a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java +++ b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.sql.cli; import org.elasticsearch.Build; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.UUIDs; import org.elasticsearch.test.ESTestCase; @@ -14,6 +13,7 @@ import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.shared.ClientException; import org.elasticsearch.xpack.sql.client.shared.Version; +import org.elasticsearch.xpack.sql.proto.MainResponse; import java.sql.SQLException; @@ -28,7 +28,7 @@ public class CliSessionTests extends ESTestCase { public void testProperConnection() throws Exception { HttpClient httpClient = mock(HttpClient.class); when(httpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), org.elasticsearch.Version.CURRENT, - ClusterName.DEFAULT, UUIDs.randomBase64UUID(), Build.CURRENT)); + ClusterName.DEFAULT.value(), UUIDs.randomBase64UUID(), Build.CURRENT)); CliSession cliSession = new CliSession(httpClient); cliSession.checkConnection(); verify(httpClient, times(1)).serverInfo(); @@ -58,10 +58,10 @@ public void testWrongServerVersion() throws Exception { } when(httpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), org.elasticsearch.Version.fromString(major + "." + minor + ".23"), - ClusterName.DEFAULT, UUIDs.randomBase64UUID(), Build.CURRENT)); + ClusterName.DEFAULT.value(), UUIDs.randomBase64UUID(), Build.CURRENT)); CliSession cliSession = new CliSession(httpClient); expectThrows(ClientException.class, cliSession::checkConnection); verify(httpClient, times(1)).serverInfo(); verifyNoMoreInteractions(httpClient); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java index 567cd10531d71..e99cb2fb7f7e2 100644 --- a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java +++ b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java @@ -6,12 +6,12 @@ package org.elasticsearch.xpack.sql.cli.command; import org.elasticsearch.Build; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.UUIDs; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.cli.TestTerminal; import org.elasticsearch.xpack.sql.client.HttpClient; +import org.elasticsearch.xpack.sql.proto.MainResponse; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -36,7 +36,7 @@ public void testShowInfo() throws Exception { HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); when(client.serverInfo()).thenReturn(new MainResponse("my_node", org.elasticsearch.Version.fromString("1.2.3"), - new ClusterName("my_cluster"), UUIDs.randomBase64UUID(), Build.CURRENT)); + new ClusterName("my_cluster").value(), UUIDs.randomBase64UUID(), Build.CURRENT)); ServerInfoCliCommand cliCommand = new ServerInfoCliCommand(); assertTrue(cliCommand.handle(testTerminal, cliSession, "info")); assertEquals(testTerminal.toString(), "Node:my_node Cluster:my_cluster Version:1.2.3\n"); @@ -44,4 +44,4 @@ public void testShowInfo() throws Exception { verifyNoMoreInteractions(client); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java index 4385731313aaf..86ebfa52fe49f 100644 --- a/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java +++ b/x-pack/plugin/sql/sql-cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java @@ -8,8 +8,8 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.cli.TestTerminal; import org.elasticsearch.xpack.sql.client.HttpClient; -import org.elasticsearch.xpack.sql.plugin.ColumnInfo; -import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; +import org.elasticsearch.xpack.sql.proto.SqlQueryResponse; import java.sql.JDBCType; import java.sql.SQLException; @@ -119,4 +119,4 @@ private SqlQueryResponse fakeResponse(String cursor, boolean includeColumns, Str } return new SqlQueryResponse(cursor, columns, rows); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlQueryRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlQueryRequest.java index 8969b88161935..8d34d59c1e0af 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlQueryRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlQueryRequest.java @@ -10,12 +10,17 @@ import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContentFragment; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.query.AbstractQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.type.DataType; import java.io.IOException; import java.util.Collections; @@ -28,20 +33,12 @@ * Base class for requests that contain sql queries (Query and Translate) */ public abstract class AbstractSqlQueryRequest extends AbstractSqlRequest implements CompositeIndicesRequest, ToXContentFragment { - public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getTimeZone("UTC"); - - /** - * Global choice for the default fetch size. - */ - public static final int DEFAULT_FETCH_SIZE = 1000; - public static final TimeValue DEFAULT_REQUEST_TIMEOUT = TimeValue.timeValueSeconds(90); - public static final TimeValue DEFAULT_PAGE_TIMEOUT = TimeValue.timeValueSeconds(45); private String query = ""; - private TimeZone timeZone = DEFAULT_TIME_ZONE; - private int fetchSize = DEFAULT_FETCH_SIZE; - private TimeValue requestTimeout = DEFAULT_REQUEST_TIMEOUT; - private TimeValue pageTimeout = DEFAULT_PAGE_TIMEOUT; + private TimeZone timeZone = Protocol.TIME_ZONE; + private int fetchSize = Protocol.FETCH_SIZE; + private TimeValue requestTimeout = Protocol.REQUEST_TIMEOUT; + private TimeValue pageTimeout = Protocol.PAGE_TIMEOUT; @Nullable private QueryBuilder filter = null; private List params = Collections.emptyList(); @@ -69,11 +66,10 @@ protected static ObjectParser objec parser.declareObjectArray(AbstractSqlQueryRequest::params, (p, c) -> SqlTypedParamValue.fromXContent(p), new ParseField("params")); parser.declareString((request, zoneId) -> request.timeZone(TimeZone.getTimeZone(zoneId)), new ParseField("time_zone")); parser.declareInt(AbstractSqlQueryRequest::fetchSize, new ParseField("fetch_size")); + parser.declareString((request, timeout) -> request.requestTimeout(TimeValue.parseTimeValue(timeout, Protocol.REQUEST_TIMEOUT, + "request_timeout")), new ParseField("request_timeout")); parser.declareString( - (request, timeout) -> request.requestTimeout(TimeValue.parseTimeValue(timeout, DEFAULT_REQUEST_TIMEOUT, "request_timeout")), - new ParseField("request_timeout")); - parser.declareString( - (request, timeout) -> request.pageTimeout(TimeValue.parseTimeValue(timeout, DEFAULT_PAGE_TIMEOUT, "page_timeout")), + (request, timeout) -> request.pageTimeout(TimeValue.parseTimeValue(timeout, Protocol.PAGE_TIMEOUT, "page_timeout")), new ParseField("page_timeout")); parser.declareObject(AbstractSqlQueryRequest::filter, (p, c) -> AbstractQueryBuilder.parseInnerQueryBuilder(p), new ParseField("filter")); @@ -185,7 +181,7 @@ public QueryBuilder filter() { public AbstractSqlQueryRequest(StreamInput in) throws IOException { super(in); query = in.readString(); - params = in.readList(SqlTypedParamValue::new); + params = in.readList(AbstractSqlQueryRequest::readSqlTypedParamValue); timeZone = TimeZone.getTimeZone(in.readString()); fetchSize = in.readVInt(); requestTimeout = in.readTimeValue(); @@ -193,11 +189,23 @@ public AbstractSqlQueryRequest(StreamInput in) throws IOException { filter = in.readOptionalNamedWriteable(QueryBuilder.class); } + public static void writeSqlTypedParamValue(StreamOutput out, SqlTypedParamValue value) throws IOException { + out.writeEnum(value.dataType); + out.writeGenericValue(value.value); + } + + public static SqlTypedParamValue readSqlTypedParamValue(StreamInput in) throws IOException { + return new SqlTypedParamValue(in.readEnum(DataType.class), in.readGenericValue()); + } + @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); out.writeString(query); - out.writeList(params); + out.writeVInt(params.size()); + for (SqlTypedParamValue param: params) { + writeSqlTypedParamValue(out, param); + } out.writeString(timeZone.getID()); out.writeVInt(fetchSize); out.writeTimeValue(requestTimeout); @@ -224,36 +232,4 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(super.hashCode(), query, timeZone, fetchSize, requestTimeout, pageTimeout, filter); } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - if (query != null) { - builder.field("query", query); - } - if (this.params.isEmpty() == false) { - builder.startArray("params"); - for (SqlTypedParamValue val : this.params) { - val.toXContent(builder, params); - } - builder.endArray(); - } - if (timeZone != null) { - builder.field("time_zone", timeZone.getID()); - } - if (fetchSize != DEFAULT_FETCH_SIZE) { - builder.field("fetch_size", fetchSize); - } - if (requestTimeout != DEFAULT_REQUEST_TIMEOUT) { - builder.field("request_timeout", requestTimeout.getStringRep()); - } - if (pageTimeout != DEFAULT_PAGE_TIMEOUT) { - builder.field("page_timeout", pageTimeout.getStringRep()); - } - if (filter != null) { - builder.field("filter"); - filter.toXContent(builder, params); - } - return builder; - } - } diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlRequest.java index bc4b1e81e44b3..2cb23f796d609 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/AbstractSqlRequest.java @@ -10,9 +10,9 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.xpack.sql.proto.Mode; import java.io.IOException; -import java.util.Locale; import java.util.Objects; import static org.elasticsearch.action.ValidateActions.addValidationError; @@ -24,24 +24,6 @@ */ public abstract class AbstractSqlRequest extends ActionRequest implements ToXContent { - public enum Mode { - PLAIN, - JDBC; - - public static Mode fromString(String mode) { - if (mode == null) { - return PLAIN; - } - return Mode.valueOf(mode.toUpperCase(Locale.ROOT)); - } - - - @Override - public String toString() { - return this.name().toLowerCase(Locale.ROOT); - } - } - private Mode mode = Mode.PLAIN; protected AbstractSqlRequest() { diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java index 9d9a9ea04a487..359652fa4f203 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java @@ -8,6 +8,7 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import java.io.IOException; import java.util.Arrays; @@ -28,19 +29,19 @@ public class CliFormatter implements Writeable { /** * Create a new {@linkplain CliFormatter} for formatting responses similar - * to the provided {@link SqlQueryResponse}. + * to the provided columns and rows. */ - public CliFormatter(SqlQueryResponse response) { + public CliFormatter(List columns, List> rows) { // Figure out the column widths: // 1. Start with the widths of the column names - width = new int[response.columns().size()]; + width = new int[columns.size()]; for (int i = 0; i < width.length; i++) { // TODO read the width from the data type? - width[i] = Math.max(MIN_COLUMN_WIDTH, response.columns().get(i).name().length()); + width[i] = Math.max(MIN_COLUMN_WIDTH, columns.get(i).name().length()); } // 2. Expand columns to fit the largest value - for (List row : response.rows()) { + for (List row : rows) { for (int i = 0; i < width.length; i++) { // TODO are we sure toString is correct here? What about dates that come back as longs. // Tracked by https://github.com/elastic/x-pack-elasticsearch/issues/3081 @@ -62,15 +63,15 @@ public void writeTo(StreamOutput out) throws IOException { * Format the provided {@linkplain SqlQueryResponse} for the CLI * including the header lines. */ - public String formatWithHeader(SqlQueryResponse response) { + public String formatWithHeader(List columns, List> rows) { // The header lines - StringBuilder sb = new StringBuilder(estimateSize(response.rows().size() + 2)); + StringBuilder sb = new StringBuilder(estimateSize(rows.size() + 2)); for (int i = 0; i < width.length; i++) { if (i > 0) { sb.append('|'); } - String name = response.columns().get(i).name(); + String name = columns.get(i).name(); // left padding int leftPadding = (width[i] - name.length()) / 2; for (int j = 0; j < leftPadding; j++) { @@ -98,19 +99,19 @@ public String formatWithHeader(SqlQueryResponse response) { /* Now format the results. Sadly, this means that column * widths are entirely determined by the first batch of * results. */ - return formatWithoutHeader(sb, response); + return formatWithoutHeader(sb, rows); } /** * Format the provided {@linkplain SqlQueryResponse} for the CLI * without the header lines. */ - public String formatWithoutHeader(SqlQueryResponse response) { - return formatWithoutHeader(new StringBuilder(estimateSize(response.rows().size())), response); + public String formatWithoutHeader(List> rows) { + return formatWithoutHeader(new StringBuilder(estimateSize(rows.size())), rows); } - private String formatWithoutHeader(StringBuilder sb, SqlQueryResponse response) { - for (List row : response.rows()) { + private String formatWithoutHeader(StringBuilder sb, List> rows) { + for (List row : rows) { for (int i = 0; i < width.length; i++) { if (i > 0) { sb.append('|'); @@ -138,7 +139,7 @@ private String formatWithoutHeader(StringBuilder sb, SqlQueryResponse response) } /** - * Pick a good estimate of the buffer size needed to contain the rows. + * Pick a good estimate of the buffer size needed to contain the rows. */ int estimateSize(int rows) { /* Each column has either a '|' or a '\n' after it diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/MetaColumnInfo.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/MetaColumnInfo.java deleted file mode 100644 index 72d5932f51137..0000000000000 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/MetaColumnInfo.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.sql.plugin; - -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Writeable; -import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.ToXContentObject; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; - -import java.io.IOException; -import java.sql.JDBCType; -import java.util.Objects; - -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; - -/** - * Information about a column returned by the listColumns response - */ -public class MetaColumnInfo implements Writeable, ToXContentObject { - - private static final ConstructingObjectParser PARSER = - new ConstructingObjectParser<>("column_info", true, objects -> - new MetaColumnInfo( - (String) objects[0], - (String) objects[1], - (String) objects[2], - objects[3] == null ? null : JDBCType.valueOf((int) objects[3]), - objects[4] == null ? 0 : (int) objects[4], - (int) objects[5])); - - private static final ParseField TABLE = new ParseField("table"); - private static final ParseField NAME = new ParseField("name"); - private static final ParseField ES_TYPE = new ParseField("type"); - private static final ParseField JDBC_TYPE = new ParseField("jdbc_type"); - private static final ParseField SIZE = new ParseField("size"); - private static final ParseField POSITION = new ParseField("position"); - - static { - PARSER.declareString(constructorArg(), TABLE); - PARSER.declareString(constructorArg(), NAME); - PARSER.declareString(constructorArg(), ES_TYPE); - PARSER.declareInt(optionalConstructorArg(), JDBC_TYPE); - PARSER.declareInt(optionalConstructorArg(), SIZE); - PARSER.declareInt(constructorArg(), POSITION); - } - - private final String table; - private final String name; - private final String esType; - @Nullable - private final JDBCType jdbcType; - private final int size; - private final int position; - - public MetaColumnInfo(String table, String name, String esType, JDBCType jdbcType, int size, int position) { - this.table = table; - this.name = name; - this.esType = esType; - this.jdbcType = jdbcType; - this.size = size; - this.position = position; - } - - public MetaColumnInfo(String table, String name, String esType, int position) { - this(table, name, esType, null, 0, position); - } - - MetaColumnInfo(StreamInput in) throws IOException { - table = in.readString(); - name = in.readString(); - esType = in.readString(); - if (in.readBoolean()) { - jdbcType = JDBCType.valueOf(in.readVInt()); - size = in.readVInt(); - } else { - jdbcType = null; - size = 0; - } - position = in.readVInt(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(table); - out.writeString(name); - out.writeString(esType); - if (jdbcType != null) { - out.writeBoolean(true); - out.writeVInt(jdbcType.getVendorTypeNumber()); - out.writeVInt(size); - } else { - out.writeBoolean(false); - } - out.writeVInt(position); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("table", table); - builder.field("name", name); - builder.field("type", esType); - if (jdbcType != null) { - builder.field("jdbc_type", jdbcType.getVendorTypeNumber()); - builder.field("size", size); - } - builder.field("position", position); - return builder.endObject(); - } - - - public static MetaColumnInfo fromXContent(XContentParser parser) { - return PARSER.apply(parser, null); - } - - /** - * Name of the table. - */ - public String table() { - return table; - } - - /** - * Name of the column. - */ - public String name() { - return name; - } - - /** - * The type of the column in Elasticsearch. - */ - public String esType() { - return esType; - } - - /** - * The type of the column as it would be returned by a JDBC driver. - */ - public JDBCType jdbcType() { - return jdbcType; - } - - /** - * Precision - */ - public int size() { - return size; - } - - /** - * Column position with in the tables - */ - public int position() { - return position; - } - - @Override - public String toString() { - return Strings.toString(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MetaColumnInfo that = (MetaColumnInfo) o; - return size == that.size && - position == that.position && - Objects.equals(table, that.table) && - Objects.equals(name, that.name) && - Objects.equals(esType, that.esType) && - jdbcType == that.jdbcType; - } - - @Override - public int hashCode() { - return Objects.hash(table, name, esType, jdbcType, size, position); - } - -} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorAction.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorAction.java index ed64fa2a41e57..f0b91640f981f 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorAction.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorAction.java @@ -13,7 +13,6 @@ public class SqlClearCursorAction public static final SqlClearCursorAction INSTANCE = new SqlClearCursorAction(); public static final String NAME = "indices:data/read/sql/close_cursor"; - public static final String REST_ENDPOINT = "/_xpack/sql/close"; private SqlClearCursorAction() { super(NAME); diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequest.java index 0dfb9f71e38f1..45dda28588726 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequest.java @@ -10,9 +10,9 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.xpack.sql.proto.Mode; import java.io.IOException; import java.util.Objects; @@ -23,13 +23,13 @@ /** * Request to clean all SQL resources associated with the cursor */ -public class SqlClearCursorRequest extends AbstractSqlRequest implements ToXContentObject { +public class SqlClearCursorRequest extends AbstractSqlRequest { private static final ConstructingObjectParser PARSER = - new ConstructingObjectParser<>(SqlClearCursorAction.NAME, true, (objects, mode) -> new SqlClearCursorRequest( - mode, - (String) objects[0] - )); + new ConstructingObjectParser<>(SqlClearCursorAction.NAME, true, (objects, mode) -> new SqlClearCursorRequest( + mode, + (String) objects[0] + )); static { PARSER.declareString(constructorArg(), new ParseField("cursor")); @@ -96,13 +96,11 @@ public int hashCode() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field("cursor", cursor); - builder.endObject(); - return builder; + // This is needed just to test round-trip compatibility with proto.SqlClearCursorRequest + return new org.elasticsearch.xpack.sql.proto.SqlClearCursorRequest(mode(), cursor).toXContent(builder, params); } public static SqlClearCursorRequest fromXContent(XContentParser parser, Mode mode) { return PARSER.apply(parser, mode); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponse.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponse.java index b157d65dfff84..3bb3df9a47ffd 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponse.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponse.java @@ -6,13 +6,10 @@ package org.elasticsearch.xpack.sql.plugin; import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.StatusToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.rest.RestStatus; import java.io.IOException; @@ -20,20 +17,13 @@ import static org.elasticsearch.rest.RestStatus.NOT_FOUND; import static org.elasticsearch.rest.RestStatus.OK; +import static org.elasticsearch.xpack.sql.proto.SqlClearCursorResponse.SUCCEEDED; /** * Response to the request to clean all SQL resources associated with the cursor */ public class SqlClearCursorResponse extends ActionResponse implements StatusToXContentObject { - private static final ParseField SUCCEEDED = new ParseField("succeeded"); - public static final ObjectParser PARSER = - new ObjectParser<>(SqlClearCursorAction.NAME, true, SqlClearCursorResponse::new); - static { - PARSER.declareBoolean(SqlClearCursorResponse::setSucceeded, SUCCEEDED); - } - - private boolean succeeded; public SqlClearCursorResponse(boolean succeeded) { @@ -93,9 +83,4 @@ public int hashCode() { return Objects.hash(succeeded); } - public static SqlClearCursorResponse fromXContent(XContentParser parser) { - return PARSER.apply(parser, null); - } - - } diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryAction.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryAction.java index fd46799608c73..cbcf626adad55 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryAction.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryAction.java @@ -12,7 +12,6 @@ public class SqlQueryAction extends Action PARSER = objectParser(SqlQueryRequest::new); public static final ParseField CURSOR = new ParseField("cursor"); @@ -37,7 +38,7 @@ public class SqlQueryRequest extends AbstractSqlQueryRequest implements ToXConte static { PARSER.declareString(SqlQueryRequest::cursor, CURSOR); PARSER.declareObject(SqlQueryRequest::filter, - (p, c) -> AbstractQueryBuilder.parseInnerQueryBuilder(p), FILTER); + (p, c) -> AbstractQueryBuilder.parseInnerQueryBuilder(p), FILTER); } private String cursor = ""; @@ -108,24 +109,15 @@ public String getDescription() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - super.toXContent(builder, params); - if (cursor != null) { - builder.field("cursor", cursor); - } - builder.endObject(); - return builder; - } - - @Override - public boolean isFragment() { - return false; + // This is needed just to test round-trip compatibility with proto.SqlQueryRequest + return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(mode(), query(), params(), timeZone(), fetchSize(), + requestTimeout(), pageTimeout(), filter(), cursor()).toXContent(builder, params); } public static SqlQueryRequest fromXContent(XContentParser parser, Mode mode) { - SqlQueryRequest request = PARSER.apply(parser, null); + SqlQueryRequest request = PARSER.apply(parser, null); request.mode(mode); return request; } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestBuilder.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestBuilder.java index a08af6f8ce4b0..1eddd09d89d35 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestBuilder.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestBuilder.java @@ -9,25 +9,22 @@ import org.elasticsearch.client.ElasticsearchClient; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.QueryBuilder; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest.Mode; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.util.Collections; import java.util.List; import java.util.TimeZone; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_FETCH_SIZE; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_PAGE_TIMEOUT; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_REQUEST_TIMEOUT; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_TIME_ZONE; - /** * The builder to build sql request */ public class SqlQueryRequestBuilder extends ActionRequestBuilder { public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action) { - this(client, action, "", Collections.emptyList(), null, DEFAULT_TIME_ZONE, DEFAULT_FETCH_SIZE, DEFAULT_REQUEST_TIMEOUT, - DEFAULT_PAGE_TIMEOUT, "", Mode.PLAIN); + this(client, action, "", Collections.emptyList(), null, Protocol.TIME_ZONE, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, + Protocol.PAGE_TIMEOUT, "", Mode.PLAIN); } public SqlQueryRequestBuilder(ElasticsearchClient client, SqlQueryAction action, String query, List params, diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponse.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponse.java index e0de05cd77438..118ba81f82df0 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponse.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponse.java @@ -7,49 +7,28 @@ import org.elasticsearch.action.ActionResponse; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.ObjectParser.ValueType; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; +import org.elasticsearch.xpack.sql.proto.Mode; import org.joda.time.ReadableDateTime; import java.io.IOException; +import java.sql.JDBCType; import java.util.ArrayList; import java.util.List; import java.util.Objects; import static java.util.Collections.unmodifiableList; -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; -import static org.elasticsearch.common.xcontent.XContentParserUtils.parseFieldsValue; /** * Response to perform an sql query */ public class SqlQueryResponse extends ActionResponse implements ToXContentObject { - @SuppressWarnings("unchecked") - public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("sql", true, - objects -> new SqlQueryResponse( - objects[0] == null ? "" : (String) objects[0], - (List) objects[1], - (List>) objects[2])); - - public static final ParseField CURSOR = new ParseField("cursor"); - public static final ParseField COLUMNS = new ParseField("columns"); - public static final ParseField ROWS = new ParseField("rows"); - - static { - PARSER.declareString(optionalConstructorArg(), CURSOR); - PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> ColumnInfo.fromXContent(p), COLUMNS); - PARSER.declareField(constructorArg(), (p, c) -> parseRows(p), ROWS, ValueType.OBJECT_ARRAY); - } - // TODO: Simplify cursor handling private String cursor; private List columns; @@ -109,7 +88,7 @@ public void readFrom(StreamInput in) throws IOException { int columnCount = in.readVInt(); List columns = new ArrayList<>(columnCount); for (int c = 0; c < columnCount; c++) { - columns.add(new ColumnInfo(in)); + columns.add(readColumnInfo(in)); } this.columns = unmodifiableList(columns); } else { @@ -139,7 +118,7 @@ public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(true); out.writeVInt(columns.size()); for (ColumnInfo column : columns) { - column.writeTo(out); + writeColumnInfo(out, column); } } out.writeVInt(rows.size()); @@ -155,7 +134,7 @@ public void writeTo(StreamOutput out) throws IOException { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - AbstractSqlRequest.Mode mode = AbstractSqlRequest.Mode.fromString(params.param("mode")); + Mode mode = Mode.fromString(params.param("mode")); builder.startObject(); { if (columns != null) { @@ -187,8 +166,8 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws /** * Serializes the provided value in SQL-compatible way based on the client mode */ - public static XContentBuilder value(XContentBuilder builder, AbstractSqlRequest.Mode mode, Object value) throws IOException { - if (mode == AbstractSqlRequest.Mode.JDBC && value instanceof ReadableDateTime) { + public static XContentBuilder value(XContentBuilder builder, Mode mode, Object value) throws IOException { + if (mode == Mode.JDBC && value instanceof ReadableDateTime) { // JDBC cannot parse dates in string format builder.value(((ReadableDateTime) value).getMillis()); } else { @@ -197,34 +176,33 @@ public static XContentBuilder value(XContentBuilder builder, AbstractSqlRequest. return builder; } - public static SqlQueryResponse fromXContent(XContentParser parser) { - return PARSER.apply(parser, null); + public static ColumnInfo readColumnInfo(StreamInput in) throws IOException { + String table = in.readString(); + String name = in.readString(); + String esType = in.readString(); + JDBCType jdbcType; + int displaySize; + if (in.readBoolean()) { + jdbcType = JDBCType.valueOf(in.readVInt()); + displaySize = in.readVInt(); + } else { + jdbcType = null; + displaySize = 0; + } + return new ColumnInfo(table, name, esType, jdbcType, displaySize); } - public static List> parseRows(XContentParser parser) throws IOException { - List> list = new ArrayList<>(); - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - if (parser.currentToken() == XContentParser.Token.START_ARRAY) { - list.add(parseRow(parser)); - } else { - throw new IllegalStateException("expected start array but got [" + parser.currentToken() + "]"); - } - } - return list; - } - - public static List parseRow(XContentParser parser) throws IOException { - List list = new ArrayList<>(); - while (parser.nextToken() != XContentParser.Token.END_ARRAY) { - if (parser.currentToken().isValue()) { - list.add(parseFieldsValue(parser)); - } else if (parser.currentToken() == XContentParser.Token.VALUE_NULL) { - list.add(null); - } else { - throw new IllegalStateException("expected value but got [" + parser.currentToken() + "]"); - } + public static void writeColumnInfo(StreamOutput out, ColumnInfo columnInfo) throws IOException { + out.writeString(columnInfo.table()); + out.writeString(columnInfo.name()); + out.writeString(columnInfo.esType()); + if (columnInfo.jdbcType() != null) { + out.writeBoolean(true); + out.writeVInt(columnInfo.jdbcType().getVendorTypeNumber()); + out.writeVInt(columnInfo.displaySize()); + } else { + out.writeBoolean(false); } - return list; } @Override diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequest.java index 93e0630745100..103bfe5fddd69 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequest.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequest.java @@ -10,8 +10,11 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.io.IOException; import java.util.List; @@ -56,4 +59,14 @@ public static SqlTranslateRequest fromXContent(XContentParser parser, Mode mode) request.mode(mode); return request; } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + // This is needed just to test parsing of SqlTranslateRequest, so we can reuse SqlQuerySerialization + return new org.elasticsearch.xpack.sql.proto.SqlQueryRequest(mode(), query(), params(), timeZone(), fetchSize(), + requestTimeout(), pageTimeout(), filter(), null).toXContent(builder, params); + + } + + } diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestBuilder.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestBuilder.java index 11adc975014ca..d6d97c19297de 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestBuilder.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestBuilder.java @@ -9,27 +9,25 @@ import org.elasticsearch.client.ElasticsearchClient; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.util.Collections; import java.util.List; import java.util.TimeZone; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_FETCH_SIZE; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_PAGE_TIMEOUT; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_REQUEST_TIMEOUT; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest.DEFAULT_TIME_ZONE; - /** * Builder for the request for the sql action for translating SQL queries into ES requests */ public class SqlTranslateRequestBuilder extends ActionRequestBuilder { public SqlTranslateRequestBuilder(ElasticsearchClient client, SqlTranslateAction action) { - this(client, action, AbstractSqlRequest.Mode.PLAIN, null, null, Collections.emptyList(), DEFAULT_TIME_ZONE, DEFAULT_FETCH_SIZE, - DEFAULT_REQUEST_TIMEOUT, DEFAULT_PAGE_TIMEOUT); + this(client, action, Mode.PLAIN, null, null, Collections.emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, + Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT); } - public SqlTranslateRequestBuilder(ElasticsearchClient client, SqlTranslateAction action, AbstractSqlRequest.Mode mode, String query, + public SqlTranslateRequestBuilder(ElasticsearchClient client, SqlTranslateAction action, Mode mode, String query, QueryBuilder filter, List params, TimeZone timeZone, int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout) { super(client, action, new SqlTranslateRequest(mode, query, params, filter, timeZone, fetchSize, requestTimeout, pageTimeout)); diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/AbstractSqlRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/AbstractSqlRequest.java new file mode 100644 index 0000000000000..2001aecdac5d8 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/AbstractSqlRequest.java @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.xcontent.ToXContentFragment; + +import java.util.Objects; + +/** + * Base request for all SQL-related requests for JDBC/CLI client + *

+ * Contains information about the client mode that can be used to generate different responses based on the caller type. + */ +public abstract class AbstractSqlRequest implements ToXContentFragment { + + private final Mode mode; + + protected AbstractSqlRequest(Mode mode) { + this.mode = mode; + } + + public Mode mode() { + return mode; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractSqlRequest that = (AbstractSqlRequest) o; + return mode == that.mode; + } + + @Override + public int hashCode() { + return Objects.hash(mode); + } + +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/ColumnInfo.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/ColumnInfo.java similarity index 70% rename from x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/ColumnInfo.java rename to x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/ColumnInfo.java index 5c12c776dd198..ad2f687ae0bef 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/ColumnInfo.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/ColumnInfo.java @@ -3,14 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.plugin; +package org.elasticsearch.xpack.sql.proto; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -26,16 +23,16 @@ /** * Information about a column returned with first query response */ -public final class ColumnInfo implements Writeable, ToXContentObject { +public class ColumnInfo implements ToXContentObject { private static final ConstructingObjectParser PARSER = - new ConstructingObjectParser<>("column_info", true, objects -> - new ColumnInfo( - objects[0] == null ? "" : (String) objects[0], - (String) objects[1], - (String) objects[2], - objects[3] == null ? null : JDBCType.valueOf((int) objects[3]), - objects[4] == null ? 0 : (int) objects[4])); + new ConstructingObjectParser<>("column_info", true, objects -> + new ColumnInfo( + objects[0] == null ? "" : (String) objects[0], + (String) objects[1], + (String) objects[2], + objects[3] == null ? null : JDBCType.valueOf((int) objects[3]), + objects[4] == null ? 0 : (int) objects[4])); private static final ParseField TABLE = new ParseField("table"); private static final ParseField NAME = new ParseField("name"); @@ -74,33 +71,6 @@ public ColumnInfo(String table, String name, String esType) { this.displaySize = 0; } - ColumnInfo(StreamInput in) throws IOException { - table = in.readString(); - name = in.readString(); - esType = in.readString(); - if (in.readBoolean()) { - jdbcType = JDBCType.valueOf(in.readVInt()); - displaySize = in.readVInt(); - } else { - jdbcType = null; - displaySize = 0; - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeString(table); - out.writeString(name); - out.writeString(esType); - if (jdbcType != null) { - out.writeBoolean(true); - out.writeVInt(jdbcType.getVendorTypeNumber()); - out.writeVInt(displaySize); - } else { - out.writeBoolean(false); - } - } - @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); @@ -162,10 +132,10 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; ColumnInfo that = (ColumnInfo) o; return displaySize == that.displaySize && - Objects.equals(table, that.table) && - Objects.equals(name, that.name) && - Objects.equals(esType, that.esType) && - jdbcType == that.jdbcType; + Objects.equals(table, that.table) && + Objects.equals(name, that.name) && + Objects.equals(esType, that.esType) && + jdbcType == that.jdbcType; } @Override diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/MainResponse.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/MainResponse.java new file mode 100644 index 0000000000000..73b6cbc529ec6 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/MainResponse.java @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.Build; +import org.elasticsearch.Version; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.util.Objects; + +/** + * Main (/) response for JDBC/CLI client + */ +public class MainResponse { + private String nodeName; + // TODO: Add parser for Version + private Version version; + private String clusterName; + private String clusterUuid; + // TODO: Add parser for Build + private Build build; + + private MainResponse() { + } + + public MainResponse(String nodeName, Version version, String clusterName, String clusterUuid, Build build) { + this.nodeName = nodeName; + this.version = version; + this.clusterName = clusterName; + this.clusterUuid = clusterUuid; + this.build = build; + } + + public String getNodeName() { + return nodeName; + } + + public Version getVersion() { + return version; + } + + public String getClusterName() { + return clusterName; + } + + public String getClusterUuid() { + return clusterUuid; + } + + public Build getBuild() { + return build; + } + + private static final ObjectParser PARSER = new ObjectParser<>(MainResponse.class.getName(), true, + MainResponse::new); + + static { + PARSER.declareString((response, value) -> response.nodeName = value, new ParseField("name")); + PARSER.declareString((response, value) -> response.clusterName = value, new ParseField("cluster_name")); + PARSER.declareString((response, value) -> response.clusterUuid = value, new ParseField("cluster_uuid")); + PARSER.declareString((response, value) -> { + }, new ParseField("tagline")); + PARSER.declareObject((response, value) -> { + final String buildFlavor = (String) value.get("build_flavor"); + final String buildType = (String) value.get("build_type"); + response.build = + new Build( + buildFlavor == null ? Build.Flavor.UNKNOWN : Build.Flavor.fromDisplayName(buildFlavor), + buildType == null ? Build.Type.UNKNOWN : Build.Type.fromDisplayName(buildType), + (String) value.get("build_hash"), + (String) value.get("build_date"), + (boolean) value.get("build_snapshot")); + response.version = Version.fromString((String) value.get("number")); + }, (parser, context) -> parser.map(), new ParseField("version")); + } + + public static MainResponse fromXContent(XContentParser parser) { + return PARSER.apply(parser, null); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MainResponse other = (MainResponse) o; + return Objects.equals(nodeName, other.nodeName) && + Objects.equals(version, other.version) && + Objects.equals(clusterUuid, other.clusterUuid) && + Objects.equals(build, other.build) && + Objects.equals(clusterName, other.clusterName); + } + + @Override + public int hashCode() { + return Objects.hash(nodeName, version, clusterUuid, build, clusterName); + } +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Mode.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Mode.java new file mode 100644 index 0000000000000..02f175ca80d79 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Mode.java @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.proto; + +import java.util.Locale; + +/** + * SQL protocol mode + */ +public enum Mode { + PLAIN, + JDBC; + + public static Mode fromString(String mode) { + if (mode == null) { + return PLAIN; + } + return Mode.valueOf(mode.toUpperCase(Locale.ROOT)); + } + + + @Override + public String toString() { + return this.name().toLowerCase(Locale.ROOT); + } +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java new file mode 100644 index 0000000000000..a61978828c80c --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/Protocol.java @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.unit.TimeValue; + +import java.util.TimeZone; + +/** + * Sql protocol defaults and end-points shared between JDBC and REST protocol implementations + */ +public final class Protocol { + public static final TimeZone TIME_ZONE = TimeZone.getTimeZone("UTC"); + + /** + * Global choice for the default fetch size. + */ + public static final int FETCH_SIZE = 1000; + public static final TimeValue REQUEST_TIMEOUT = TimeValue.timeValueSeconds(90); + public static final TimeValue PAGE_TIMEOUT = TimeValue.timeValueSeconds(45); + + /** + * SQL-related endpoints + */ + public static final String CLEAR_CURSOR_REST_ENDPOINT = "/_xpack/sql/close"; + public static final String SQL_QUERY_REST_ENDPOINT = "/_xpack/sql"; +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorRequest.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorRequest.java new file mode 100644 index 0000000000000..310dde4430210 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorRequest.java @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Objects; + +/** + * Request to clean all SQL resources associated with the cursor for JDBC/CLI client + */ +public class SqlClearCursorRequest extends AbstractSqlRequest { + + private final String cursor; + + public SqlClearCursorRequest(Mode mode, String cursor) { + super(mode); + this.cursor = cursor; + } + + public String getCursor() { + return cursor; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + SqlClearCursorRequest that = (SqlClearCursorRequest) o; + return Objects.equals(cursor, that.cursor); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), cursor); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("cursor", cursor); + return builder; + } +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorResponse.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorResponse.java new file mode 100644 index 0000000000000..b56a8335d20d5 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlClearCursorResponse.java @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; + +/** + * Response to the request to clean all SQL resources associated with the cursor for JDBC/CLI client + */ +public class SqlClearCursorResponse { + + public static final ParseField SUCCEEDED = new ParseField("succeeded"); + public static final ConstructingObjectParser PARSER = + new ConstructingObjectParser<>(SqlClearCursorResponse.class.getName(), true, + objects -> new SqlClearCursorResponse(objects[0] == null ? false : (boolean) objects[0])); + + static { + PARSER.declareBoolean(optionalConstructorArg(), SUCCEEDED); + } + + + private final boolean succeeded; + + public SqlClearCursorResponse(boolean succeeded) { + this.succeeded = succeeded; + } + + /** + * @return Whether the attempt to clear a cursor was successful. + */ + public boolean isSucceeded() { + return succeeded; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SqlClearCursorResponse response = (SqlClearCursorResponse) o; + return succeeded == response.succeeded; + } + + @Override + public int hashCode() { + return Objects.hash(succeeded); + } + + public static SqlClearCursorResponse fromXContent(XContentParser parser) { + return PARSER.apply(parser, null); + } + +} 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 new file mode 100644 index 0000000000000..00a1696a05f60 --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryRequest.java @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.TimeZone; + +/** + * Sql query request for JDBC/CLI client + */ +public class SqlQueryRequest extends AbstractSqlRequest { + @Nullable + private final String cursor; + private final String query; + private final TimeZone timeZone; + private final int fetchSize; + private final TimeValue requestTimeout; + private final TimeValue pageTimeout; + @Nullable + private final ToXContent filter; + private final List params; + + + public SqlQueryRequest(Mode mode, String query, List params, TimeZone timeZone, + int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout, ToXContent filter, String cursor) { + super(mode); + this.query = query; + this.params = params; + this.timeZone = timeZone; + this.fetchSize = fetchSize; + this.requestTimeout = requestTimeout; + this.pageTimeout = pageTimeout; + this.filter = filter; + this.cursor = cursor; + } + + public SqlQueryRequest(Mode mode, String query, List params, ToXContent filter, TimeZone timeZone, + int fetchSize, TimeValue requestTimeout, TimeValue pageTimeout) { + this(mode, query, params, timeZone, fetchSize, requestTimeout, pageTimeout, filter, null); + } + + public SqlQueryRequest(Mode mode, String cursor, TimeValue requestTimeout, TimeValue pageTimeout) { + this(mode, "", Collections.emptyList(), Protocol.TIME_ZONE, Protocol.FETCH_SIZE, requestTimeout, pageTimeout, null, cursor); + } + + + /** + * The key that must be sent back to SQL to access the next page of + * results. + */ + public String cursor() { + return cursor; + } + + /** + * Text of SQL query + */ + public String query() { + return query; + } + + /** + * An optional list of parameters if the SQL query is parametrized + */ + public List params() { + return params; + } + + /** + * The client's time zone + */ + public TimeZone timeZone() { + return timeZone; + } + + + /** + * Hint about how many results to fetch at once. + */ + public int fetchSize() { + return fetchSize; + } + + /** + * The timeout specified on the search request + */ + public TimeValue requestTimeout() { + return requestTimeout; + } + + /** + * The scroll timeout + */ + public TimeValue pageTimeout() { + return pageTimeout; + } + + /** + * An optional Query DSL defined query that can added as a filter on the top of the SQL query + */ + public ToXContent filter() { + return filter; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + SqlQueryRequest that = (SqlQueryRequest) o; + return fetchSize == that.fetchSize && + Objects.equals(query, that.query) && + Objects.equals(params, that.params) && + Objects.equals(timeZone, that.timeZone) && + Objects.equals(requestTimeout, that.requestTimeout) && + Objects.equals(pageTimeout, that.pageTimeout) && + Objects.equals(filter, that.filter) && + Objects.equals(cursor, that.cursor); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), query, timeZone, fetchSize, requestTimeout, pageTimeout, filter, cursor); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (query != null) { + builder.field("query", query); + } + if (this.params.isEmpty() == false) { + builder.startArray("params"); + for (SqlTypedParamValue val : this.params) { + val.toXContent(builder, params); + } + builder.endArray(); + } + if (timeZone != null) { + builder.field("time_zone", timeZone.getID()); + } + if (fetchSize != Protocol.FETCH_SIZE) { + builder.field("fetch_size", fetchSize); + } + if (requestTimeout != Protocol.REQUEST_TIMEOUT) { + builder.field("request_timeout", requestTimeout.getStringRep()); + } + if (pageTimeout != Protocol.PAGE_TIMEOUT) { + builder.field("page_timeout", pageTimeout.getStringRep()); + } + if (filter != null) { + builder.field("filter"); + filter.toXContent(builder, params); + } + if (cursor != null) { + builder.field("cursor", cursor); + } + return builder; + } + +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryResponse.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryResponse.java new file mode 100644 index 0000000000000..8937261237c7f --- /dev/null +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlQueryResponse.java @@ -0,0 +1,122 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.proto; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ObjectParser.ValueType; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; +import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg; +import static org.elasticsearch.common.xcontent.XContentParserUtils.parseFieldsValue; + +/** + * Response to perform an sql query for JDBC/CLI client + */ +public class SqlQueryResponse { + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("sql", true, + objects -> new SqlQueryResponse( + objects[0] == null ? "" : (String) objects[0], + (List) objects[1], + (List>) objects[2])); + + public static final ParseField CURSOR = new ParseField("cursor"); + public static final ParseField COLUMNS = new ParseField("columns"); + public static final ParseField ROWS = new ParseField("rows"); + + static { + PARSER.declareString(optionalConstructorArg(), CURSOR); + PARSER.declareObjectArray(optionalConstructorArg(), (p, c) -> ColumnInfo.fromXContent(p), COLUMNS); + PARSER.declareField(constructorArg(), (p, c) -> parseRows(p), ROWS, ValueType.OBJECT_ARRAY); + } + + // TODO: Simplify cursor handling + private final String cursor; + private final List columns; + // TODO investigate reusing Page here - it probably is much more efficient + private final List> rows; + + public SqlQueryResponse(String cursor, @Nullable List columns, List> rows) { + this.cursor = cursor; + this.columns = columns; + this.rows = rows; + } + + /** + * The key that must be sent back to SQL to access the next page of + * results. If equal to "" then there is no next page. + */ + public String cursor() { + return cursor; + } + + public long size() { + return rows.size(); + } + + public List columns() { + return columns; + } + + public List> rows() { + return rows; + } + + public static SqlQueryResponse fromXContent(XContentParser parser) { + return PARSER.apply(parser, null); + } + + public static List> parseRows(XContentParser parser) throws IOException { + List> list = new ArrayList<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + if (parser.currentToken() == XContentParser.Token.START_ARRAY) { + list.add(parseRow(parser)); + } else { + throw new IllegalStateException("expected start array but got [" + parser.currentToken() + "]"); + } + } + return list; + } + + public static List parseRow(XContentParser parser) throws IOException { + List list = new ArrayList<>(); + while (parser.nextToken() != XContentParser.Token.END_ARRAY) { + if (parser.currentToken().isValue()) { + list.add(parseFieldsValue(parser)); + } else if (parser.currentToken() == XContentParser.Token.VALUE_NULL) { + list.add(null); + } else { + throw new IllegalStateException("expected value but got [" + parser.currentToken() + "]"); + } + } + return list; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SqlQueryResponse that = (SqlQueryResponse) o; + return Objects.equals(cursor, that.cursor) && + Objects.equals(columns, that.columns) && + Objects.equals(rows, that.rows); + } + + @Override + public int hashCode() { + return Objects.hash(cursor, columns, rows); + } + +} diff --git a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTypedParamValue.java b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlTypedParamValue.java similarity index 76% rename from x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTypedParamValue.java rename to x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlTypedParamValue.java index ffde82fab3491..a85b66b80a34d 100644 --- a/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlTypedParamValue.java +++ b/x-pack/plugin/sql/sql-proto/src/main/java/org/elasticsearch/xpack/sql/proto/SqlTypedParamValue.java @@ -3,12 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.sql.plugin; +package org.elasticsearch.xpack.sql.proto; import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ObjectParser; import org.elasticsearch.common.xcontent.ToXContentObject; @@ -25,12 +22,12 @@ /** * Represent a strongly typed parameter value */ -public class SqlTypedParamValue implements ToXContentObject, Writeable { +public class SqlTypedParamValue implements ToXContentObject { private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("params", true, objects -> new SqlTypedParamValue( - objects[0], - DataType.fromEsType((String) objects[1]))); + DataType.fromEsType((String) objects[1]), objects[0] + )); private static final ParseField VALUE = new ParseField("value"); private static final ParseField TYPE = new ParseField("type"); @@ -43,7 +40,7 @@ public class SqlTypedParamValue implements ToXContentObject, Writeable { public final Object value; public final DataType dataType; - public SqlTypedParamValue(Object value, DataType dataType) { + public SqlTypedParamValue(DataType dataType, Object value) { this.value = value; this.dataType = dataType; } @@ -61,17 +58,6 @@ public static SqlTypedParamValue fromXContent(XContentParser parser) { return PARSER.apply(parser, null); } - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeEnum(dataType); - out.writeGenericValue(value); - } - - public SqlTypedParamValue(StreamInput in) throws IOException { - dataType = in.readEnum(DataType.class); - value = in.readGenericValue(); - } - @Override public boolean equals(Object o) { if (this == o) { @@ -94,4 +80,4 @@ public int hashCode() { public String toString() { return String.valueOf(value) + "[" + dataType + "]"; } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequestTests.java b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequestTests.java index 83546924a38f8..e479ae8b4f1ea 100644 --- a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequestTests.java +++ b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorRequestTests.java @@ -8,17 +8,18 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractSerializingTestCase; +import org.elasticsearch.xpack.sql.proto.Mode; import org.junit.Before; import java.io.IOException; import java.util.function.Consumer; public class SqlClearCursorRequestTests extends AbstractSerializingTestCase { - public AbstractSqlRequest.Mode testMode; + public Mode testMode; @Before public void setup() { - testMode = randomFrom(AbstractSqlRequest.Mode.values()); + testMode = randomFrom(Mode.values()); } @Override @@ -40,7 +41,7 @@ protected SqlClearCursorRequest doParseInstance(XContentParser parser) { protected SqlClearCursorRequest mutateInstance(SqlClearCursorRequest instance) throws IOException { @SuppressWarnings("unchecked") Consumer mutator = randomFrom( - request -> request.mode(randomValueOtherThan(request.mode(), () -> randomFrom(AbstractSqlRequest.Mode.values()))), + request -> request.mode(randomValueOtherThan(request.mode(), () -> randomFrom(Mode.values()))), request -> request.setCursor(randomValueOtherThan(request.getCursor(), SqlQueryResponseTests::randomStringCursor)) ); SqlClearCursorRequest newRequest = new SqlClearCursorRequest(instance.mode(), instance.getCursor()); diff --git a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponseTests.java b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponseTests.java index 0ef2875d8e7dd..94964428bb4f3 100644 --- a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponseTests.java +++ b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlClearCursorResponseTests.java @@ -27,6 +27,8 @@ protected SqlClearCursorResponse mutateInstance(SqlClearCursorResponse instance) @Override protected SqlClearCursorResponse doParseInstance(XContentParser parser) { - return SqlClearCursorResponse.fromXContent(parser); + org.elasticsearch.xpack.sql.proto.SqlClearCursorResponse response = + org.elasticsearch.xpack.sql.proto.SqlClearCursorResponse.fromXContent(parser); + return new SqlClearCursorResponse(response.isSucceeded()); } } diff --git a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestTests.java b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestTests.java index 5fbe4e42d48f2..0e4a183ab1626 100644 --- a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestTests.java +++ b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryRequestTests.java @@ -14,6 +14,8 @@ import org.elasticsearch.search.SearchModule; import org.elasticsearch.test.AbstractSerializingTestCase; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.type.DataType; import org.junit.Before; @@ -28,11 +30,11 @@ public class SqlQueryRequestTests extends AbstractSerializingTestCase { - public AbstractSqlRequest.Mode testMode; + public Mode testMode; @Before public void setup() { - testMode = randomFrom(AbstractSqlRequest.Mode.values()); + testMode = randomFrom(Mode.values()); } @Override @@ -63,11 +65,11 @@ public List randomParameters() { List arr = new ArrayList<>(len); for (int i = 0; i < len; i++) { @SuppressWarnings("unchecked") Supplier supplier = randomFrom( - () -> new SqlTypedParamValue(randomBoolean(), DataType.BOOLEAN), - () -> new SqlTypedParamValue(randomLong(), DataType.LONG), - () -> new SqlTypedParamValue(randomDouble(), DataType.DOUBLE), - () -> new SqlTypedParamValue(null, DataType.NULL), - () -> new SqlTypedParamValue(randomAlphaOfLength(10), DataType.KEYWORD) + () -> new SqlTypedParamValue(DataType.BOOLEAN, randomBoolean()), + () -> new SqlTypedParamValue(DataType.LONG, randomLong()), + () -> new SqlTypedParamValue(DataType.DOUBLE, randomDouble()), + () -> new SqlTypedParamValue(DataType.NULL, null), + () -> new SqlTypedParamValue(DataType.KEYWORD, randomAlphaOfLength(10)) ); arr.add(supplier.get()); } @@ -93,7 +95,7 @@ protected SqlQueryRequest doParseInstance(XContentParser parser) { protected SqlQueryRequest mutateInstance(SqlQueryRequest instance) { @SuppressWarnings("unchecked") Consumer mutator = randomFrom( - request -> request.mode(randomValueOtherThan(request.mode(), () -> randomFrom(AbstractSqlRequest.Mode.values()))), + request -> request.mode(randomValueOtherThan(request.mode(), () -> randomFrom(Mode.values()))), request -> request.query(randomValueOtherThan(request.query(), () -> randomAlphaOfLength(5))), request -> request.params(randomValueOtherThan(request.params(), this::randomParameters)), request -> request.timeZone(randomValueOtherThan(request.timeZone(), ESTestCase::randomTimeZone)), diff --git a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponseTests.java b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponseTests.java index 42c08bb09142f..bc5e5ae2a0180 100644 --- a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponseTests.java +++ b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlQueryResponseTests.java @@ -13,6 +13,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractStreamableXContentTestCase; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import java.io.IOException; import java.sql.JDBCType; @@ -114,6 +115,8 @@ public void testToXContent() throws IOException { @Override protected SqlQueryResponse doParseInstance(XContentParser parser) { - return SqlQueryResponse.fromXContent(parser); + org.elasticsearch.xpack.sql.proto.SqlQueryResponse response = + org.elasticsearch.xpack.sql.proto.SqlQueryResponse.fromXContent(parser); + return new SqlQueryResponse(response.cursor(), response.columns(), response.rows()); } } diff --git a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java index 21b002293768f..2eb3d71bbf410 100644 --- a/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java +++ b/x-pack/plugin/sql/sql-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java @@ -14,6 +14,7 @@ import org.elasticsearch.search.SearchModule; import org.elasticsearch.test.AbstractSerializingTestCase; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.sql.proto.Mode; import org.junit.Before; import java.io.IOException; @@ -25,11 +26,11 @@ public class SqlTranslateRequestTests extends AbstractSerializingTestCase { - public AbstractSqlRequest.Mode testMode; + public Mode testMode; @Before public void setup() { - testMode = randomFrom(AbstractSqlRequest.Mode.values()); + testMode = randomFrom(Mode.values()); } @Override @@ -71,7 +72,7 @@ protected SqlTranslateRequest mutateInstance(SqlTranslateRequest instance) throw request -> request.query(randomValueOtherThan(request.query(), () -> randomAlphaOfLength(5))), request -> request.timeZone(randomValueOtherThan(request.timeZone(), ESTestCase::randomTimeZone)), request -> request.fetchSize(randomValueOtherThan(request.fetchSize(), () -> between(1, Integer.MAX_VALUE))), - request -> request.requestTimeout(randomValueOtherThan(request.requestTimeout(), () -> randomTV())), + request -> request.requestTimeout(randomValueOtherThan(request.requestTimeout(), this::randomTV)), request -> request.filter(randomValueOtherThan(request.filter(), () -> request.filter() == null ? randomFilter(random()) : randomFilterOrNull(random()))) ); diff --git a/x-pack/plugin/sql/sql-shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java b/x-pack/plugin/sql/sql-shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java index bf7c245b24cbe..8f77d5397e948 100644 --- a/x-pack/plugin/sql/sql-shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java +++ b/x-pack/plugin/sql/sql-shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.xpack.sql.client; -import org.elasticsearch.action.main.MainResponse; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.stream.BytesStreamOutput; @@ -22,13 +21,14 @@ import org.elasticsearch.xpack.sql.client.shared.ConnectionConfiguration; import org.elasticsearch.xpack.sql.client.shared.JreHttpUrlConnection; import org.elasticsearch.xpack.sql.client.shared.JreHttpUrlConnection.ResponseOrException; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest; -import org.elasticsearch.xpack.sql.plugin.SqlClearCursorAction; -import org.elasticsearch.xpack.sql.plugin.SqlClearCursorRequest; -import org.elasticsearch.xpack.sql.plugin.SqlClearCursorResponse; -import org.elasticsearch.xpack.sql.plugin.SqlQueryAction; -import org.elasticsearch.xpack.sql.plugin.SqlQueryRequest; -import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.AbstractSqlRequest; +import org.elasticsearch.xpack.sql.proto.MainResponse; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; +import org.elasticsearch.xpack.sql.proto.SqlClearCursorRequest; +import org.elasticsearch.xpack.sql.proto.SqlClearCursorResponse; +import org.elasticsearch.xpack.sql.proto.SqlQueryRequest; +import org.elasticsearch.xpack.sql.proto.SqlQueryResponse; import java.io.IOException; import java.io.InputStream; @@ -50,7 +50,7 @@ public class HttpClient { private final ConnectionConfiguration cfg; - public HttpClient(ConnectionConfiguration cfg) throws SQLException { + public HttpClient(ConnectionConfiguration cfg) { this.cfg = cfg; } @@ -66,26 +66,25 @@ public MainResponse serverInfo() throws SQLException { public SqlQueryResponse queryInit(String query, int fetchSize) throws SQLException { // TODO allow customizing the time zone - this is what session set/reset/get should be about - SqlQueryRequest sqlRequest = new SqlQueryRequest(AbstractSqlRequest.Mode.PLAIN, query, Collections.emptyList(), null, + SqlQueryRequest sqlRequest = new SqlQueryRequest(Mode.PLAIN, query, Collections.emptyList(), null, TimeZone.getTimeZone("UTC"), fetchSize, TimeValue.timeValueMillis(cfg.queryTimeout()), - TimeValue.timeValueMillis(cfg.pageTimeout()), "" - ); + TimeValue.timeValueMillis(cfg.pageTimeout())); return query(sqlRequest); } public SqlQueryResponse query(SqlQueryRequest sqlRequest) throws SQLException { - return post(SqlQueryAction.REST_ENDPOINT, sqlRequest, SqlQueryResponse::fromXContent); + return post(Protocol.SQL_QUERY_REST_ENDPOINT, sqlRequest, SqlQueryResponse::fromXContent); } public SqlQueryResponse nextPage(String cursor) throws SQLException { - SqlQueryRequest sqlRequest = new SqlQueryRequest(); - sqlRequest.cursor(cursor); - return post(SqlQueryAction.REST_ENDPOINT, sqlRequest, SqlQueryResponse::fromXContent); + SqlQueryRequest sqlRequest = new SqlQueryRequest(Mode.PLAIN, cursor, TimeValue.timeValueMillis(cfg.queryTimeout()), + TimeValue.timeValueMillis(cfg.pageTimeout())); + return post(Protocol.SQL_QUERY_REST_ENDPOINT, sqlRequest, SqlQueryResponse::fromXContent); } public boolean queryClose(String cursor) throws SQLException { - SqlClearCursorResponse response = post(SqlClearCursorAction.REST_ENDPOINT, - new SqlClearCursorRequest(AbstractSqlRequest.Mode.PLAIN, cursor), + SqlClearCursorResponse response = post(Protocol.CLEAR_CURSOR_REST_ENDPOINT, + new SqlClearCursorRequest(Mode.PLAIN, cursor), SqlClearCursorResponse::fromXContent); return response.isSucceeded(); } @@ -167,4 +166,4 @@ private Response fromXContent(XContentType xContentType, BytesReferen throw new ClientException("Cannot parse response", ex); } } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/PlanExecutor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/PlanExecutor.java index 8c58769b75962..23f1a6049dc2c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/PlanExecutor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/PlanExecutor.java @@ -17,7 +17,7 @@ import org.elasticsearch.xpack.sql.plan.physical.EsQueryExec; import org.elasticsearch.xpack.sql.planner.Planner; import org.elasticsearch.xpack.sql.planner.PlanningException; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.session.Configuration; import org.elasticsearch.xpack.sql.session.Cursor; import org.elasticsearch.xpack.sql.session.RowSet; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/AstBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/AstBuilder.java index de28f33187260..48aa2cf1fa79b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/AstBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/AstBuilder.java @@ -8,7 +8,7 @@ import org.antlr.v4.runtime.Token; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SingleStatementContext; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.util.Map; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java index bf432a7236357..7ce65aa4cfec1 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/CommandBuilder.java @@ -33,7 +33,7 @@ import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTableTypes; import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTables; import org.elasticsearch.xpack.sql.plan.logical.command.sys.SysTypes; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.util.StringUtils; @@ -190,4 +190,4 @@ public SysTypes visitSysTypes(SysTypesContext ctx) { public Object visitSysTableTypes(SysTableTypesContext ctx) { return new SysTableTypes(source(ctx)); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index b14611f9f599f..a6185def278a1 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -76,7 +76,7 @@ import org.elasticsearch.xpack.sql.parser.SqlBaseParser.StringLiteralContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.StringQueryContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.SubqueryExpressionContext; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; @@ -516,4 +516,4 @@ private SqlTypedParamValue param(TerminalNode node) { return params.get(token); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java index f41fce1602783..3435994a0fc42 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java @@ -41,7 +41,7 @@ import org.elasticsearch.xpack.sql.plan.logical.SubQueryAlias; import org.elasticsearch.xpack.sql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.sql.plan.logical.With; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.session.EmptyExecutable; import org.elasticsearch.xpack.sql.type.DataType; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlParser.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlParser.java index 7aa3748e31eae..b7fe9178f911f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlParser.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/SqlParser.java @@ -26,7 +26,7 @@ import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import java.util.Arrays; import java.util.BitSet; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlClearCursorAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlClearCursorAction.java index 4d47ca8c373e1..534d0459180e0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlClearCursorAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlClearCursorAction.java @@ -12,23 +12,25 @@ import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestToXContentListener; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; import java.io.IOException; import static org.elasticsearch.rest.RestRequest.Method.POST; -import static org.elasticsearch.xpack.sql.plugin.SqlClearCursorAction.REST_ENDPOINT; + public class RestSqlClearCursorAction extends BaseRestHandler { public RestSqlClearCursorAction(Settings settings, RestController controller) { super(settings); - controller.registerHandler(POST, REST_ENDPOINT, this); + controller.registerHandler(POST, Protocol.CLEAR_CURSOR_REST_ENDPOINT, this); } @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { SqlClearCursorRequest sqlRequest; try (XContentParser parser = request.contentOrSourceParamParser()) { - sqlRequest = SqlClearCursorRequest.fromXContent(parser, AbstractSqlRequest.Mode.fromString(request.param("mode"))); + sqlRequest = SqlClearCursorRequest.fromXContent(parser, Mode.fromString(request.param("mode"))); } return channel -> client.executeLocally(SqlClearCursorAction.INSTANCE, sqlRequest, new RestToXContentListener<>(channel)); } @@ -37,4 +39,4 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli public String getName() { return "sql_translate_action"; } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlQueryAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlQueryAction.java index 9d043f855fd44..9e34a3fb2e097 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlQueryAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlQueryAction.java @@ -18,6 +18,8 @@ import org.elasticsearch.rest.RestResponse; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.action.RestResponseListener; +import org.elasticsearch.xpack.sql.proto.Mode; +import org.elasticsearch.xpack.sql.proto.Protocol; import org.elasticsearch.xpack.sql.session.Cursor; import org.elasticsearch.xpack.sql.session.Cursors; @@ -31,15 +33,15 @@ public class RestSqlQueryAction extends BaseRestHandler { public RestSqlQueryAction(Settings settings, RestController controller) { super(settings); - controller.registerHandler(GET, SqlQueryAction.REST_ENDPOINT, this); - controller.registerHandler(POST, SqlQueryAction.REST_ENDPOINT, this); + controller.registerHandler(GET, Protocol.SQL_QUERY_REST_ENDPOINT, this); + controller.registerHandler(POST, Protocol.SQL_QUERY_REST_ENDPOINT, this); } @Override protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { SqlQueryRequest sqlRequest; try (XContentParser parser = request.contentOrSourceParamParser()) { - sqlRequest = SqlQueryRequest.fromXContent(parser, AbstractSqlRequest.Mode.fromString(request.param("mode"))); + sqlRequest = SqlQueryRequest.fromXContent(parser,Mode.fromString(request.param("mode"))); } /* diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlTranslateAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlTranslateAction.java index 6167e4e571dff..503ee84314820 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlTranslateAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlTranslateAction.java @@ -12,6 +12,7 @@ import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.action.RestToXContentListener; +import org.elasticsearch.xpack.sql.proto.Mode; import java.io.IOException; @@ -32,7 +33,7 @@ public RestSqlTranslateAction(Settings settings, RestController controller) { protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException { SqlTranslateRequest sqlRequest; try (XContentParser parser = request.contentOrSourceParamParser()) { - sqlRequest = SqlTranslateRequest.fromXContent(parser, AbstractSqlRequest.Mode.fromString(request.param("mode"))); + sqlRequest = SqlTranslateRequest.fromXContent(parser, Mode.fromString(request.param("mode"))); } return channel -> client.executeLocally(SqlTranslateAction.INSTANCE, sqlRequest, new RestToXContentListener<>(channel)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java index 8a3ef973d6bf1..b15ff6a1ae4aa 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java @@ -5,6 +5,8 @@ */ package org.elasticsearch.xpack.sql.plugin; +import org.elasticsearch.xpack.sql.proto.Mode; + import java.util.function.Consumer; /** @@ -12,16 +14,16 @@ */ public class SqlLicenseChecker { - private final Consumer checkIfSqlAllowed; + private final Consumer checkIfSqlAllowed; - public SqlLicenseChecker(Consumer checkIfSqlAllowed) { + public SqlLicenseChecker(Consumer checkIfSqlAllowed) { this.checkIfSqlAllowed = checkIfSqlAllowed; } /** * Throws an ElasticsearchSecurityException if the specified mode is not allowed */ - public void checkIfSqlAllowed(AbstractSqlRequest.Mode mode) { + public void checkIfSqlAllowed(Mode mode) { checkIfSqlAllowed.accept(mode); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TextFormat.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TextFormat.java index 349a481cf660f..9d0cd60c23e32 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TextFormat.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TextFormat.java @@ -7,6 +7,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.rest.RestRequest; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import org.elasticsearch.xpack.sql.session.Cursor; import org.elasticsearch.xpack.sql.session.Cursors; import org.elasticsearch.xpack.sql.util.StringUtils; @@ -38,17 +39,17 @@ String format(Cursor cursor, RestRequest request, SqlQueryResponse response) { final CliFormatter formatter; if (cursor instanceof CliFormatterCursor) { formatter = ((CliFormatterCursor) cursor).getCliFormatter(); - return formatter.formatWithoutHeader(response); + return formatter.formatWithoutHeader(response.rows()); } else { - formatter = new CliFormatter(response); - return formatter.formatWithHeader(response); + formatter = new CliFormatter(response.columns(), response.rows()); + return formatter.formatWithHeader(response.columns(), response.rows()); } } @Override Cursor wrapCursor(Cursor oldCursor, SqlQueryResponse response) { CliFormatter formatter = (oldCursor instanceof CliFormatterCursor) ? - ((CliFormatterCursor) oldCursor).getCliFormatter() : new CliFormatter(response); + ((CliFormatterCursor) oldCursor).getCliFormatter() : new CliFormatter(response.columns(), response.rows()); return CliFormatterCursor.wrap(super.wrapCursor(oldCursor, response), formatter); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java index 5b59ced7a494d..46429e2d50829 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java @@ -16,6 +16,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.sql.execution.PlanExecutor; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import org.elasticsearch.xpack.sql.session.Configuration; import org.elasticsearch.xpack.sql.session.Cursors; import org.elasticsearch.xpack.sql.session.RowSet; @@ -26,7 +27,7 @@ import java.util.List; import static java.util.Collections.unmodifiableList; -import static org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest.Mode.JDBC; +import static org.elasticsearch.xpack.sql.proto.Mode.JDBC; public class TransportSqlQueryAction extends HandledTransportAction { private final PlanExecutor planExecutor; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Configuration.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Configuration.java index 681a5eb1fbd24..ae43d4a988922 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Configuration.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Configuration.java @@ -9,16 +9,14 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.xpack.sql.plugin.AbstractSqlQueryRequest; +import org.elasticsearch.xpack.sql.proto.Protocol; import java.util.TimeZone; -// Typed object holding properties for a given action +// Typed object holding properties for a given action public class Configuration { public static final Configuration DEFAULT = new Configuration(TimeZone.getTimeZone("UTC"), - AbstractSqlQueryRequest.DEFAULT_FETCH_SIZE, - AbstractSqlQueryRequest.DEFAULT_REQUEST_TIMEOUT, - AbstractSqlQueryRequest.DEFAULT_PAGE_TIMEOUT, - null); + Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null); private TimeZone timeZone; private int pageSize; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java index 880e98c606408..65da32c3122ab 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/SqlSession.java @@ -21,7 +21,7 @@ import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.sql.planner.Planner; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.rule.RuleExecutor; import java.util.List; @@ -162,4 +162,4 @@ public void sqlExecutable(String sql, List params, ActionLis public Configuration settings() { return settings; } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/action/SqlActionIT.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/action/SqlActionIT.java index b36fa811d3b25..22a7889f6247e 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/action/SqlActionIT.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/action/SqlActionIT.java @@ -7,10 +7,10 @@ import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.WriteRequest; -import org.elasticsearch.xpack.sql.plugin.AbstractSqlRequest.Mode; -import org.elasticsearch.xpack.sql.plugin.ColumnInfo; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import org.elasticsearch.xpack.sql.plugin.SqlQueryAction; import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; +import org.elasticsearch.xpack.sql.proto.Mode; import java.sql.JDBCType; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/CursorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/CursorTests.java index 0cd8c33b11688..bac221df2e92d 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/CursorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/CursorTests.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.sql.SqlException; import org.elasticsearch.xpack.sql.plugin.CliFormatter; import org.elasticsearch.xpack.sql.plugin.CliFormatterCursor; -import org.elasticsearch.xpack.sql.plugin.ColumnInfo; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import org.elasticsearch.xpack.sql.plugin.SqlQueryResponse; import org.elasticsearch.xpack.sql.session.Configuration; import org.elasticsearch.xpack.sql.session.Cursor; @@ -80,7 +80,8 @@ static Cursor randomNonEmptyCursor() { () -> { SqlQueryResponse response = createRandomSqlResponse(); if (response.columns() != null && response.rows() != null) { - return CliFormatterCursor.wrap(ScrollCursorTests.randomScrollCursor(), new CliFormatter(response)); + return CliFormatterCursor.wrap(ScrollCursorTests.randomScrollCursor(), + new CliFormatter(response.columns(), response.rows())); } else { return ScrollCursorTests.randomScrollCursor(); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ParameterTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ParameterTests.java index 5e35965985987..37ab5fb2b6ce3 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ParameterTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ParameterTests.java @@ -12,7 +12,7 @@ import org.elasticsearch.xpack.sql.expression.predicate.Equals; import org.elasticsearch.xpack.sql.parser.ParsingException; import org.elasticsearch.xpack.sql.parser.SqlParser; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.type.DataType; import java.util.Arrays; @@ -28,7 +28,7 @@ public class ParameterTests extends ESTestCase { public void testSingleParameter() { Expression expression = new SqlParser().createExpression("a = \n?", Collections.singletonList( - new SqlTypedParamValue("foo", DataType.KEYWORD) + new SqlTypedParamValue(DataType.KEYWORD, "foo") )); logger.info(expression); assertThat(expression, instanceOf(Equals.class)); @@ -42,10 +42,10 @@ public void testSingleParameter() { public void testMultipleParameters() { Expression expression = new SqlParser().createExpression("(? + ? * ?) - ?", Arrays.asList( - new SqlTypedParamValue(1L, DataType.LONG), - new SqlTypedParamValue(2L, DataType.LONG), - new SqlTypedParamValue(3L, DataType.LONG), - new SqlTypedParamValue(4L, DataType.LONG) + new SqlTypedParamValue(DataType.LONG, 1L), + new SqlTypedParamValue(DataType.LONG, 2L), + new SqlTypedParamValue(DataType.LONG, 3L), + new SqlTypedParamValue(DataType.LONG, 4L) )); assertThat(expression, instanceOf(Sub.class)); Sub sub = (Sub) expression; @@ -62,9 +62,9 @@ public void testMultipleParameters() { public void testNotEnoughParameters() { ParsingException ex = expectThrows(ParsingException.class, () -> new SqlParser().createExpression("(? + ? * ?) - ?", Arrays.asList( - new SqlTypedParamValue(1L, DataType.LONG), - new SqlTypedParamValue(2L, DataType.LONG), - new SqlTypedParamValue(3L, DataType.LONG) + new SqlTypedParamValue(DataType.LONG, 1L), + new SqlTypedParamValue(DataType.LONG, 2L), + new SqlTypedParamValue(DataType.LONG, 3L) ))); assertThat(ex.getMessage(), containsString("Not enough actual parameters")); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java index c94bcf0e664c4..b2abf0b680054 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.expression.regex.Like; import org.elasticsearch.xpack.sql.expression.regex.LikePattern; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.type.DataType; import java.util.Locale; @@ -33,7 +33,7 @@ private LikePattern like(String pattern) { Expression exp = null; boolean parameterized = randomBoolean(); if (parameterized) { - exp = parser.createExpression("exp LIKE ?", singletonList(new SqlTypedParamValue(pattern, DataType.KEYWORD))); + exp = parser.createExpression("exp LIKE ?", singletonList(new SqlTypedParamValue(DataType.KEYWORD, pattern))); } else { exp = parser.createExpression(String.format(Locale.ROOT, "exp LIKE '%s'", pattern)); } @@ -63,9 +63,9 @@ public void testInvalidChar() { assertThat(error("'%string' ESCAPE '%'"), is("line 1:28: Char [%] cannot be used for escaping")); } - + public void testCannotUseStar() { assertThat(error("'|*string' ESCAPE '|'"), is("line 1:11: Invalid char [*] found in pattern [|*string] at position 1; use [%] or [_] instead")); } -} \ No newline at end of file +} diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java index c08c423be34eb..e42ec51b425d2 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java @@ -17,7 +17,7 @@ import org.elasticsearch.xpack.sql.expression.function.FunctionRegistry; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.plan.logical.command.Command; -import org.elasticsearch.xpack.sql.plugin.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.type.DataTypes; @@ -228,7 +228,7 @@ public void testSysTablesTypesEnumerationWoString() throws Exception { } private SqlTypedParamValue param(Object value) { - return new SqlTypedParamValue(value, DataTypes.fromJava(value)); + return new SqlTypedParamValue(DataTypes.fromJava(value), value); } private Tuple sql(String sql, List params) { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java index 1fe3c9fc89e99..d87dba3306889 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.sql.plugin; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import java.sql.JDBCType; import java.util.Arrays; @@ -23,17 +24,17 @@ public class CliFormatterTests extends ESTestCase { Arrays.asList( Arrays.asList("15charwidedata!", 1, 6.888, 12, "rabbit"), Arrays.asList("dog", 1.7976931348623157E308, 123124.888, 9912, "goat"))); - private final CliFormatter formatter = new CliFormatter(firstResponse); + private final CliFormatter formatter = new CliFormatter(firstResponse.columns(), firstResponse.rows()); /** - * Tests for {@link CliFormatter#formatWithHeader(SqlQueryResponse)}, values + * Tests for {@link CliFormatter#formatWithHeader}, values * of exactly the minimum column size, column names of exactly * the minimum column size, column headers longer than the * minimum column size, and values longer than the minimum * column size. */ public void testFormatWithHeader() { - String[] result = formatter.formatWithHeader(firstResponse).split("\n"); + String[] result = formatter.formatWithHeader(firstResponse.columns(), firstResponse.rows()).split("\n"); assertThat(result, arrayWithSize(4)); assertEquals(" foo | bar |15charwidename!|superduperwidename!!!| baz ", result[0]); assertEquals("---------------+----------------------+---------------+---------------------+---------------", result[1]); @@ -42,14 +43,14 @@ public void testFormatWithHeader() { } /** - * Tests for {@link CliFormatter#formatWithoutHeader(SqlQueryResponse)} and + * Tests for {@link CliFormatter#formatWithoutHeader} and * truncation of long columns. */ public void testFormatWithoutHeader() { - String[] result = formatter.formatWithoutHeader(new SqlQueryResponse("", null, + String[] result = formatter.formatWithoutHeader( Arrays.asList( Arrays.asList("ohnotruncateddata", 4, 1, 77, "wombat"), - Arrays.asList("dog", 2, 123124.888, 9912, "goat")))).split("\n"); + Arrays.asList("dog", 2, 123124.888, 9912, "goat"))).split("\n"); assertThat(result, arrayWithSize(2)); assertEquals("ohnotruncatedd~|4 |1 |77 |wombat ", result[0]); assertEquals("dog |2 |123124.888 |9912 |goat ", result[1]); @@ -59,9 +60,9 @@ public void testFormatWithoutHeader() { * Ensure that our estimates are perfect in at least some cases. */ public void testEstimateSize() { - assertEquals(formatter.formatWithHeader(firstResponse).length(), + assertEquals(formatter.formatWithHeader(firstResponse.columns(), firstResponse.rows()).length(), formatter.estimateSize(firstResponse.rows().size() + 2)); - assertEquals(formatter.formatWithoutHeader(firstResponse).length(), + assertEquals(formatter.formatWithoutHeader(firstResponse.rows()).length(), formatter.estimateSize(firstResponse.rows().size())); } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/TextFormatTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/TextFormatTests.java index 1c6bbfa69e816..bf6ccbb225a54 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/TextFormatTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/TextFormatTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.rest.RestRequest; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.xpack.sql.proto.ColumnInfo; import java.util.ArrayList; import java.util.List;