From 178d6ca6b3856e4513ec67122702da053551deeb Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Thu, 28 Dec 2017 11:10:18 -0500 Subject: [PATCH] SQL: Move shared REST client methods to shared-client (elastic/x-pack-elasticsearch#3428) * SQL: Move shared REST client methods to shared-client This commit is a preliminary step for moving JDBC to the REST client. It extracts the common REST clients from CLI and moves it to shared-client. This will allow us to move to the 5 project setup: rest-proto, shared-client, server, jdbc, cli with the following dependencies: server <-- rest-proto shared-client <-- rest-proto jdbc <-- shared-client cli <-- shared-client Relates to elastic/x-pack-elasticsearch#3419 Original commit: elastic/x-pack-elasticsearch@2e6a134de04ad9540cbfe40ec82338a95783af18 --- docs/en/sql/endpoints/sql-rest.asciidoc | 10 +- .../org/elasticsearch/xpack/XPackPlugin.java | 3 +- .../qa/sql/multinode/RestSqlMultinodeIT.java | 4 +- .../qa/sql/security/RestSqlSecurityIT.java | 16 +- .../xpack/qa/sql/embed/JdbcProtoHandler.java | 2 +- .../xpack/qa/sql/rest/RestSqlTestCase.java | 29 +- .../org/elasticsearch/xpack/sql/cli/Cli.java | 3 +- .../xpack/sql/cli/PlainResponse.java | 29 -- .../xpack/sql/cli/command/CliSession.java | 14 +- .../cli/command/ServerQueryCliCommand.java | 45 +- .../xpack/sql/cli/CliSessionTests.java | 31 +- .../sql/cli/command/BuiltinCommandTests.java | 32 +- .../sql/cli/command/CliCommandsTests.java | 8 +- .../command/ServerInfoCliCommandTests.java | 6 +- .../command/ServerQueryCliCommandTests.java | 57 ++- sql/jdbc/build.gradle | 9 +- .../xpack/sql/plugin/CliFormatter.java | 0 .../xpack/sql/plugin/SqlResponse.java | 159 ++++-- .../xpack/sql/plugin}/SqlRequestTests.java | 18 +- .../xpack/sql/plugin}/SqlResponseTests.java | 95 ++-- sql/server/build.gradle | 1 + .../search/extractor/FieldHitExtractor.java | 55 +- .../xpack/sql/plugin/RestSqlAction.java | 20 +- .../xpack/sql/plugin/SqlLicenseChecker.java | 10 +- .../xpack/sql/plugin/SqlPlugin.java | 2 +- .../xpack/sql/plugin/TransportSqlAction.java | 2 - .../sql/execution/search/CursorTests.java | 59 +++ .../extractor/FieldHitExtractorTests.java | 74 ++- .../xpack/sql/plugin/CliFormatterTests.java | 4 +- .../xpack/sql/plugin/SqlPluginTests.java | 2 +- .../sql/plugin/SqlTranslateRequestTests.java | 4 +- sql/shared-client/build.gradle | 8 + .../licenses/elasticsearch-LICENSE.txt | 202 ++++++++ .../licenses/elasticsearch-NOTICE.txt | 5 + .../licenses/joda-time-2.9.5.jar.sha1 | 1 + .../licenses/joda-time-LICENSE.txt | 202 ++++++++ .../licenses/joda-time-NOTICE.txt | 5 + .../licenses/log4j-api-2.9.1.jar.sha1 | 1 + .../licenses/log4j-api-LICENSE.txt | 202 ++++++++ .../licenses/log4j-api-NOTICE.txt | 5 + .../licenses/log4j-core-2.9.1.jar.sha1 | 1 + .../licenses/log4j-core-LICENSE.txt | 202 ++++++++ .../licenses/log4j-core-NOTICE.txt | 5 + sql/shared-client/licenses/lucene-LICENSE.txt | 475 ++++++++++++++++++ sql/shared-client/licenses/lucene-NOTICE.txt | 192 +++++++ .../licenses/lucene-core-7.2.0.jar.sha1 | 1 + .../xpack/sql/client/HttpClient.java} | 115 +++-- .../client/shared/JreHttpUrlConnection.java | 1 + .../xpack/sql/test}/SqlTestUtils.java | 2 +- 49 files changed, 2055 insertions(+), 373 deletions(-) delete mode 100644 sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/PlainResponse.java rename sql/{server => rest-proto}/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java (100%) rename sql/{server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action => rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin}/SqlRequestTests.java (77%) rename sql/{server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action => rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin}/SqlResponseTests.java (53%) create mode 100644 sql/shared-client/licenses/elasticsearch-LICENSE.txt create mode 100644 sql/shared-client/licenses/elasticsearch-NOTICE.txt create mode 100644 sql/shared-client/licenses/joda-time-2.9.5.jar.sha1 create mode 100644 sql/shared-client/licenses/joda-time-LICENSE.txt create mode 100644 sql/shared-client/licenses/joda-time-NOTICE.txt create mode 100644 sql/shared-client/licenses/log4j-api-2.9.1.jar.sha1 create mode 100644 sql/shared-client/licenses/log4j-api-LICENSE.txt create mode 100644 sql/shared-client/licenses/log4j-api-NOTICE.txt create mode 100644 sql/shared-client/licenses/log4j-core-2.9.1.jar.sha1 create mode 100644 sql/shared-client/licenses/log4j-core-LICENSE.txt create mode 100644 sql/shared-client/licenses/log4j-core-NOTICE.txt create mode 100644 sql/shared-client/licenses/lucene-LICENSE.txt create mode 100644 sql/shared-client/licenses/lucene-NOTICE.txt create mode 100644 sql/shared-client/licenses/lucene-core-7.2.0.jar.sha1 rename sql/{cli/src/main/java/org/elasticsearch/xpack/sql/cli/CliHttpClient.java => shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java} (53%) rename sql/{server/src/test/java/org/elasticsearch/xpack/sql => test-utils/src/main/java/org/elasticsearch/xpack/sql/test}/SqlTestUtils.java (96%) diff --git a/docs/en/sql/endpoints/sql-rest.asciidoc b/docs/en/sql/endpoints/sql-rest.asciidoc index ffde8934203..643a1daf941 100644 --- a/docs/en/sql/endpoints/sql-rest.asciidoc +++ b/docs/en/sql/endpoints/sql-rest.asciidoc @@ -59,12 +59,11 @@ Which returns: -------------------------------------------------- { "columns": [ - {"name": "author", "type": "text"}, - {"name": "name", "type": "text"}, - {"name": "page_count", "type": "short"}, - {"name": "release_date", "type": "date"} + {"name": "author", "type": "text", "jdbc_type": 12, "display_size": 0}, + {"name": "name", "type": "text", "jdbc_type": 12, "display_size": 0}, + {"name": "page_count", "type": "short", "jdbc_type": 5, "display_size": 6}, + {"name": "release_date", "type": "date", "jdbc_type": 93, "display_size": 20} ], - "size": 5, "rows": [ ["Peter F. Hamilton", "Pandora's Star", 768, 1078185600000], ["Vernor Vinge", "A Fire Upon the Deep", 613, 707356800000], @@ -96,7 +95,6 @@ Which looks like: [source,js] -------------------------------------------------- { - "size" : 5, "rows" : [ ["Dan Simmons", "Hyperion", 482, 612144000000], ["Iain M. Banks", "Consider Phlebas", 471, 546134400000], diff --git a/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index e9b08c2ed59..fc3ca729904 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -196,7 +196,8 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I if (!licenseState.isJdbcAllowed()) { throw LicenseUtils.newComplianceException("jdbc"); } - }) + }, + () -> licenseState.isJdbcAllowed()) ); // Check if the node is a transport client. if (transportClientMode == false) { diff --git a/qa/sql/multinode/src/test/java/org/elasticsearch/xpack/qa/sql/multinode/RestSqlMultinodeIT.java b/qa/sql/multinode/src/test/java/org/elasticsearch/xpack/qa/sql/multinode/RestSqlMultinodeIT.java index 1c743c95a94..9a363baa9a3 100644 --- a/qa/sql/multinode/src/test/java/org/elasticsearch/xpack/qa/sql/multinode/RestSqlMultinodeIT.java +++ b/qa/sql/multinode/src/test/java/org/elasticsearch/xpack/qa/sql/multinode/RestSqlMultinodeIT.java @@ -19,6 +19,7 @@ import org.elasticsearch.test.rest.ESRestTestCase; import java.io.IOException; import java.io.InputStream; import java.nio.charset.UnsupportedCharsetException; +import java.sql.JDBCType; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -100,9 +101,8 @@ public class RestSqlMultinodeIT extends ESRestTestCase { private void assertCount(RestClient client, int count) throws IOException { Map expected = new HashMap<>(); - expected.put("columns", singletonList(columnInfo("COUNT(1)", "long"))); + expected.put("columns", singletonList(columnInfo("COUNT(1)", "long", JDBCType.BIGINT, 20))); expected.put("rows", singletonList(singletonList(count))); - expected.put("size", 1); Map actual = responseToMap(client.performRequest("POST", "/_xpack/sql", singletonMap("format", "json"), new StringEntity("{\"query\": \"SELECT COUNT(*) FROM test\"}", ContentType.APPLICATION_JSON))); diff --git a/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java b/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java index 57283b892e2..fc2833f26e5 100644 --- a/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java +++ b/qa/sql/security/src/test/java/org/elasticsearch/xpack/qa/sql/security/RestSqlSecurityIT.java @@ -18,6 +18,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.NotEqualMessageBuilder; import java.io.IOException; import java.io.InputStream; +import java.sql.JDBCType; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -37,13 +38,12 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase { public void queryWorksAsAdmin() throws Exception { Map expected = new HashMap<>(); expected.put("columns", Arrays.asList( - columnInfo("a", "long"), - columnInfo("b", "long"), - columnInfo("c", "long"))); + columnInfo("a", "long", JDBCType.BIGINT, 20), + columnInfo("b", "long", JDBCType.BIGINT, 20), + columnInfo("c", "long", JDBCType.BIGINT, 20))); expected.put("rows", Arrays.asList( Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6))); - expected.put("size", 2); assertResponse(expected, runSql(null, "SELECT * FROM test ORDER BY a")); } @@ -83,14 +83,13 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase { public void expectDescribe(Map columns, String user) throws Exception { Map expected = new HashMap<>(3); expected.put("columns", Arrays.asList( - columnInfo("column", "keyword"), - columnInfo("type", "keyword"))); + columnInfo("column", "keyword", JDBCType.VARCHAR, 0), + columnInfo("type", "keyword", JDBCType.VARCHAR, 0))); List> rows = new ArrayList<>(columns.size()); for (Map.Entry column : columns.entrySet()) { rows.add(Arrays.asList(column.getKey(), column.getValue())); } expected.put("rows", rows); - expected.put("size", columns.size()); assertResponse(expected, runSql(user, "DESCRIBE test")); } @@ -98,13 +97,12 @@ public class RestSqlSecurityIT extends SqlSecurityTestCase { @Override public void expectShowTables(List tables, String user) throws Exception { Map expected = new HashMap<>(); - expected.put("columns", singletonList(columnInfo("table", "keyword"))); + expected.put("columns", singletonList(columnInfo("table", "keyword", JDBCType.VARCHAR, 0))); List> rows = new ArrayList<>(); for (String table : tables) { rows.add(singletonList(table)); } expected.put("rows", rows); - expected.put("size", tables.size()); assertResponse(expected, runSql(user, "SHOW TABLES")); } diff --git a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/embed/JdbcProtoHandler.java b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/embed/JdbcProtoHandler.java index 9818c53c848..5b28bac7c73 100644 --- a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/embed/JdbcProtoHandler.java +++ b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/embed/JdbcProtoHandler.java @@ -24,7 +24,7 @@ class JdbcProtoHandler extends ProtoHandler { JdbcProtoHandler(Client client) { super(client); - action = new RestSqlJdbcAction(Settings.EMPTY, mock(RestController.class), new SqlLicenseChecker(() -> {}, () -> {}), + action = new RestSqlJdbcAction(Settings.EMPTY, mock(RestController.class), new SqlLicenseChecker(() -> {}, () -> {}, () -> true), new IndexResolver(client)); } diff --git a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java index 8cb560bb970..8e5bed55b27 100644 --- a/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java +++ b/qa/sql/src/main/java/org/elasticsearch/xpack/qa/sql/rest/RestSqlTestCase.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; +import java.sql.JDBCType; import java.util.Arrays; import java.util.HashMap; import java.util.Locale; @@ -45,10 +46,12 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe /** * Builds that map that is returned in the header for each column. */ - public static Map columnInfo(String name, String type) { + public static Map columnInfo(String name, String type, JDBCType jdbcType, int size) { Map column = new HashMap<>(); column.put("name", name); column.put("type", type); + column.put("jdbc_type", jdbcType.getVendorTypeNumber()); + column.put("display_size", size); return unmodifiableMap(column); } @@ -57,9 +60,8 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe "{\"test\":\"test\"}"); Map expected = new HashMap<>(); - expected.put("columns", singletonList(columnInfo("test", "text"))); + expected.put("columns", singletonList(columnInfo("test", "text", JDBCType.VARCHAR, 0))); expected.put("rows", Arrays.asList(singletonList("test"), singletonList("test"))); - expected.put("size", 2); assertResponse(expected, runSql("SELECT * FROM test")); } @@ -90,21 +92,19 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe Map expected = new HashMap<>(); if (i == 0) { expected.put("columns", Arrays.asList( - columnInfo("text", "text"), - columnInfo("number", "long"), - columnInfo("s", "double"), - columnInfo("SCORE()", "float"))); + columnInfo("text", "text", JDBCType.VARCHAR, 0), + columnInfo("number", "long", JDBCType.BIGINT, 20), + columnInfo("s", "double", JDBCType.DOUBLE, 25), + columnInfo("SCORE()", "float", JDBCType.REAL, 15))); } expected.put("rows", Arrays.asList( Arrays.asList("text" + i, i, Math.sin(i), 1.0), Arrays.asList("text" + (i + 1), i + 1, Math.sin(i + 1), 1.0))); - expected.put("size", 2); cursor = (String) response.remove("cursor"); assertResponse(expected, response); assertNotNull(cursor); } Map expected = new HashMap<>(); - expected.put("size", 0); expected.put("rows", emptyList()); assertResponse(expected, runSql(new StringEntity("{\"cursor\":\"" + cursor + "\"}", ContentType.APPLICATION_JSON))); } @@ -133,12 +133,11 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe Map expected = new HashMap<>(); expected.put("columns", Arrays.asList( - columnInfo("name", "text"), - columnInfo("score", "long"), - columnInfo("SCORE()", "float"))); + columnInfo("name", "text", JDBCType.VARCHAR, 0), + columnInfo("score", "long", JDBCType.BIGINT, 20), + columnInfo("SCORE()", "float", JDBCType.REAL, 15))); expected.put("rows", singletonList(Arrays.asList( "test", 10, 1.0))); - expected.put("size", 1); assertResponse(expected, runSql("SELECT *, SCORE() FROM test ORDER BY SCORE()")); assertResponse(expected, runSql("SELECT name, \\\"score\\\", SCORE() FROM test ORDER BY SCORE()")); @@ -356,9 +355,8 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe "{\"test\":\"bar\"}"); Map expected = new HashMap<>(); - expected.put("columns", singletonList(columnInfo("test", "text"))); + expected.put("columns", singletonList(columnInfo("test", "text", JDBCType.VARCHAR, 0))); expected.put("rows", singletonList(singletonList("foo"))); - expected.put("size", 1); assertResponse(expected, runSql(new StringEntity("{\"query\":\"SELECT * FROM test\", \"filter\":{\"match\": {\"test\": \"foo\"}}}", ContentType.APPLICATION_JSON))); } @@ -445,7 +443,6 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe assertNotNull(cursor); } Map expected = new HashMap<>(); - expected.put("size", 0); expected.put("rows", emptyList()); assertResponse(expected, runSql(new StringEntity("{\"cursor\":\"" + cursor + "\"}", ContentType.APPLICATION_JSON))); diff --git a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/Cli.java b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/Cli.java index 20854fecb51..298a3ecd7bc 100644 --- a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/Cli.java +++ b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/Cli.java @@ -20,6 +20,7 @@ import org.elasticsearch.xpack.sql.cli.command.FetchSizeCliCommand; import org.elasticsearch.xpack.sql.cli.command.PrintLogoCommand; import org.elasticsearch.xpack.sql.cli.command.ServerInfoCliCommand; import org.elasticsearch.xpack.sql.cli.command.ServerQueryCliCommand; +import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.shared.ClientException; import org.elasticsearch.xpack.sql.client.shared.ConnectionConfiguration; import org.elasticsearch.xpack.sql.client.shared.Version; @@ -111,7 +112,7 @@ public class Cli extends LoggingAwareCommand { try (CliTerminal cliTerminal = new JLineTerminal()) { ConnectionBuilder connectionBuilder = new ConnectionBuilder(cliTerminal); ConnectionConfiguration con = connectionBuilder.buildConnection(uri, keystoreLocation); - CliSession cliSession = new CliSession(new CliHttpClient(con)); + CliSession cliSession = new CliSession(new HttpClient(con)); cliSession.setDebug(debug); if (checkConnection) { checkConnection(cliSession, cliTerminal, con); diff --git a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/PlainResponse.java b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/PlainResponse.java deleted file mode 100644 index 18185692a19..00000000000 --- a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/PlainResponse.java +++ /dev/null @@ -1,29 +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.cli; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; - -/** - * Plain text tabular SQL response - */ -public class PlainResponse { - public final long tookNanos; - public final String data; - public final String cursor; - - public PlainResponse(long tookNanos, String cursor, String data) { - this.data = data; - this.tookNanos = tookNanos; - this.cursor = cursor; - } -} - diff --git a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java index b5dc4e75c19..fd0727c1554 100644 --- a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java +++ b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/CliSession.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.sql.cli.command; import org.elasticsearch.action.main.MainResponse; -import org.elasticsearch.xpack.sql.cli.CliHttpClient; +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.protocol.shared.AbstractQueryInitRequest; @@ -17,17 +17,17 @@ import java.sql.SQLException; * Stores information about the current session */ public class CliSession { - private final CliHttpClient cliHttpClient; + private final HttpClient httpClient; private int fetchSize = AbstractQueryInitRequest.DEFAULT_FETCH_SIZE; private String fetchSeparator = ""; private boolean debug; - public CliSession(CliHttpClient cliHttpClient) { - this.cliHttpClient = cliHttpClient; + public CliSession(HttpClient httpClient) { + this.httpClient = httpClient; } - public CliHttpClient getClient() { - return cliHttpClient; + public HttpClient getClient() { + return httpClient; } public void setFetchSize(int fetchSize) { @@ -60,7 +60,7 @@ public class CliSession { public void checkConnection() throws ClientException { MainResponse response; try { - response = cliHttpClient.serverInfo(); + response = httpClient.serverInfo(); } catch (SQLException ex) { throw new ClientException(ex); } diff --git a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java index 633ce18de1a..1ec5a4ffc9b 100644 --- a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java +++ b/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommand.java @@ -5,34 +5,29 @@ */ package org.elasticsearch.xpack.sql.cli.command; -import org.elasticsearch.common.SuppressForbidden; -import org.elasticsearch.xpack.sql.cli.CliHttpClient; import org.elasticsearch.xpack.sql.cli.CliTerminal; -import org.elasticsearch.xpack.sql.cli.PlainResponse; +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.SqlResponse; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.sql.SQLException; public class ServerQueryCliCommand extends AbstractServerCliCommand { @Override protected boolean doHandle(CliTerminal terminal, CliSession cliSession, String line) { - PlainResponse response = null; - CliHttpClient cliClient = cliSession.getClient(); + SqlResponse response = null; + HttpClient cliClient = cliSession.getClient(); + CliFormatter cliFormatter; + String data; try { response = cliClient.queryInit(line, cliSession.getFetchSize()); - if (response.data.startsWith("digraph ")) { - handleGraphviz(terminal, response.data); - return true; - } + cliFormatter = new CliFormatter(response); + data = cliFormatter.formatWithHeader(response); while (true) { - handleText(terminal, response.data); - if (response.cursor.isEmpty()) { + handleText(terminal, data); + if (response.cursor().isEmpty()) { // Successfully finished the entire query! terminal.flush(); return true; @@ -40,7 +35,8 @@ public class ServerQueryCliCommand extends AbstractServerCliCommand { if (false == cliSession.getFetchSeparator().equals("")) { terminal.println(cliSession.getFetchSeparator()); } - response = cliSession.getClient().nextPage(response.cursor); + response = cliSession.getClient().nextPage(response.cursor()); + data = cliFormatter.formatWithoutHeader(response); } } catch (SQLException e) { if (JreHttpUrlConnection.SQL_STATE_BAD_SERVER.equals(e.getSQLState())) { @@ -50,7 +46,7 @@ public class ServerQueryCliCommand extends AbstractServerCliCommand { } if (response != null) { try { - cliClient.queryClose(response.cursor); + cliClient.queryClose(response.cursor()); } catch (SQLException ex) { terminal.error("Could not close cursor", ex.getMessage()); } @@ -62,17 +58,4 @@ public class ServerQueryCliCommand extends AbstractServerCliCommand { private void handleText(CliTerminal terminal, String str) { terminal.print(str); } - - @SuppressForbidden(reason = "cli application") - private void handleGraphviz(CliTerminal terminal, String str) { - try { - // save the content to a temp file - Path dotTempFile = Files.createTempFile(Paths.get("."), "sql-gv", ".dot"); - Files.write(dotTempFile, str.getBytes(StandardCharsets.UTF_8)); - terminal.println("Saved graph file at " + dotTempFile); - } catch (IOException ex) { - terminal.error("Cannot save graph file ", ex.getMessage()); - } - } - } diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java index 9fbee63c2d9..e332ccc7044 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/CliSessionTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.UUIDs; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.cli.command.CliSession; +import org.elasticsearch.xpack.sql.client.HttpClient; import org.elasticsearch.xpack.sql.client.shared.ClientException; import org.elasticsearch.xpack.sql.client.shared.Version; @@ -25,26 +26,26 @@ import static org.mockito.Mockito.when; public class CliSessionTests extends ESTestCase { public void testProperConnection() throws Exception { - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - when(cliHttpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), org.elasticsearch.Version.CURRENT, + HttpClient httpClient = mock(HttpClient.class); + when(httpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), org.elasticsearch.Version.CURRENT, ClusterName.DEFAULT, UUIDs.randomBase64UUID(), Build.CURRENT, randomBoolean())); - CliSession cliSession = new CliSession(cliHttpClient); + CliSession cliSession = new CliSession(httpClient); cliSession.checkConnection(); - verify(cliHttpClient, times(1)).serverInfo(); - verifyNoMoreInteractions(cliHttpClient); + verify(httpClient, times(1)).serverInfo(); + verifyNoMoreInteractions(httpClient); } public void testConnection() throws Exception { - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - when(cliHttpClient.serverInfo()).thenThrow(new SQLException("Cannot connect")); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + when(httpClient.serverInfo()).thenThrow(new SQLException("Cannot connect")); + CliSession cliSession = new CliSession(httpClient); expectThrows(ClientException.class, cliSession::checkConnection); - verify(cliHttpClient, times(1)).serverInfo(); - verifyNoMoreInteractions(cliHttpClient); + verify(httpClient, times(1)).serverInfo(); + verifyNoMoreInteractions(httpClient); } public void testWrongServerVersion() throws Exception { - CliHttpClient cliHttpClient = mock(CliHttpClient.class); + HttpClient httpClient = mock(HttpClient.class); byte minor; byte major; if (randomBoolean()) { @@ -55,12 +56,12 @@ public class CliSessionTests extends ESTestCase { major = Version.CURRENT.major; } - when(cliHttpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), + when(httpClient.serverInfo()).thenReturn(new MainResponse(randomAlphaOfLength(5), org.elasticsearch.Version.fromString(major + "." + minor + ".23"), ClusterName.DEFAULT, UUIDs.randomBase64UUID(), Build.CURRENT, randomBoolean())); - CliSession cliSession = new CliSession(cliHttpClient); + CliSession cliSession = new CliSession(httpClient); expectThrows(ClientException.class, cliSession::checkConnection); - verify(cliHttpClient, times(1)).serverInfo(); - verifyNoMoreInteractions(cliHttpClient); + verify(httpClient, times(1)).serverInfo(); + verifyNoMoreInteractions(httpClient); } } \ No newline at end of file diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/BuiltinCommandTests.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/BuiltinCommandTests.java index 99696b24888..b6a54a3a8cf 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/BuiltinCommandTests.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/BuiltinCommandTests.java @@ -6,8 +6,8 @@ package org.elasticsearch.xpack.sql.cli.command; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.sql.cli.CliHttpClient; import org.elasticsearch.xpack.sql.cli.TestTerminal; +import org.elasticsearch.xpack.sql.client.HttpClient; import static org.hamcrest.Matchers.containsString; import static org.mockito.Mockito.mock; @@ -18,29 +18,29 @@ public class BuiltinCommandTests extends ESTestCase { public void testInvalidCommand() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); assertFalse(new ClearScreenCliCommand().handle(testTerminal, cliSession, "something")); assertFalse(new FetchSeparatorCliCommand().handle(testTerminal, cliSession, "something")); assertFalse(new FetchSizeCliCommand().handle(testTerminal, cliSession, "something")); assertFalse(new PrintLogoCommand().handle(testTerminal, cliSession, "something")); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } public void testClearScreen() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); testTerminal.print("not clean"); assertTrue(new ClearScreenCliCommand().handle(testTerminal, cliSession, "cls")); assertEquals("", testTerminal.toString()); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } public void testFetchSeparator() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); FetchSeparatorCliCommand cliCommand = new FetchSeparatorCliCommand(); assertFalse(cliCommand.handle(testTerminal, cliSession, "fetch")); assertEquals("", cliSession.getFetchSeparator()); @@ -58,13 +58,13 @@ public class BuiltinCommandTests extends ESTestCase { assertTrue(cliCommand.handle(testTerminal, cliSession, "fetch separator=\"baz\"")); assertEquals("baz", cliSession.getFetchSeparator()); assertEquals("fetch separator set to \"baz\"", testTerminal.toString()); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } public void testFetchSize() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); FetchSizeCliCommand cliCommand = new FetchSizeCliCommand(); assertFalse(cliCommand.handle(testTerminal, cliSession, "fetch")); assertEquals(1000L, cliSession.getFetchSize()); @@ -83,17 +83,17 @@ public class BuiltinCommandTests extends ESTestCase { assertTrue(cliCommand.handle(testTerminal, cliSession, "fetch_size = -10")); assertEquals(10L, cliSession.getFetchSize()); assertEquals("Invalid fetch size [-10]. Must be > 0.", testTerminal.toString()); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } public void testPrintLogo() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); testTerminal.print("not clean"); assertTrue(new PrintLogoCommand().handle(testTerminal, cliSession, "logo")); assertThat(testTerminal.toString(), containsString("SQL")); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } } diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/CliCommandsTests.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/CliCommandsTests.java index 13aee4a4291..5d1988d5c8d 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/CliCommandsTests.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/CliCommandsTests.java @@ -6,8 +6,8 @@ package org.elasticsearch.xpack.sql.cli.command; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.sql.cli.CliHttpClient; import org.elasticsearch.xpack.sql.cli.TestTerminal; +import org.elasticsearch.xpack.sql.client.HttpClient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -16,8 +16,8 @@ public class CliCommandsTests extends ESTestCase { public void testCliCommands() { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient cliHttpClient = mock(CliHttpClient.class); - CliSession cliSession = new CliSession(cliHttpClient); + HttpClient httpClient = mock(HttpClient.class); + CliSession cliSession = new CliSession(httpClient); CliCommands cliCommands = new CliCommands( (terminal, session, line) -> line.equals("foo"), (terminal, session, line) -> line.equals("bar"), @@ -29,6 +29,6 @@ public class CliCommandsTests extends ESTestCase { assertTrue(cliCommands.handle(testTerminal, cliSession, "baz")); assertFalse(cliCommands.handle(testTerminal, cliSession, "")); assertFalse(cliCommands.handle(testTerminal, cliSession, "something")); - verifyNoMoreInteractions(cliHttpClient); + verifyNoMoreInteractions(httpClient); } } diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java index bc3f61e5109..b2a0b9f7276 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerInfoCliCommandTests.java @@ -10,8 +10,8 @@ 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.CliHttpClient; import org.elasticsearch.xpack.sql.cli.TestTerminal; +import org.elasticsearch.xpack.sql.client.HttpClient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -23,7 +23,7 @@ public class ServerInfoCliCommandTests extends ESTestCase { public void testInvalidCommand() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); ServerInfoCliCommand cliCommand = new ServerInfoCliCommand(); assertFalse(cliCommand.handle(testTerminal, cliSession, "blah")); @@ -33,7 +33,7 @@ public class ServerInfoCliCommandTests extends ESTestCase { public void testShowInfo() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + 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, randomBoolean())); diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java index ed06d22e89a..40b99b71713 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/command/ServerQueryCliCommandTests.java @@ -6,11 +6,14 @@ package org.elasticsearch.xpack.sql.cli.command; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.sql.cli.CliHttpClient; import org.elasticsearch.xpack.sql.cli.TestTerminal; -import org.elasticsearch.xpack.sql.cli.PlainResponse; +import org.elasticsearch.xpack.sql.client.HttpClient; +import org.elasticsearch.xpack.sql.plugin.SqlResponse; +import java.sql.JDBCType; import java.sql.SQLException; +import java.util.Collections; +import java.util.List; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; @@ -24,7 +27,7 @@ public class ServerQueryCliCommandTests extends ESTestCase { public void testExceptionHandling() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); when(client.queryInit("blah", 1000)).thenThrow(new SQLException("test exception")); ServerQueryCliCommand cliCommand = new ServerQueryCliCommand(); @@ -36,28 +39,29 @@ public class ServerQueryCliCommandTests extends ESTestCase { public void testOnePageQuery() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); cliSession.setFetchSize(10); - when(client.queryInit("test query", 10)).thenReturn(new PlainResponse(123, "", "some command response")); + when(client.queryInit("test query", 10)).thenReturn(fakeResponse("", true, "foo")); ServerQueryCliCommand cliCommand = new ServerQueryCliCommand(); assertTrue(cliCommand.handle(testTerminal, cliSession, "test query")); - assertEquals("some command response", testTerminal.toString()); + assertEquals(" field \n---------------\nfoo \n", testTerminal.toString()); verify(client, times(1)).queryInit(eq("test query"), eq(10)); verifyNoMoreInteractions(client); } public void testThreePageQuery() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); cliSession.setFetchSize(10); - when(client.queryInit("test query", 10)).thenReturn(new PlainResponse(123, "my_cursor1", "first")); - when(client.nextPage("my_cursor1")).thenReturn(new PlainResponse(345, "my_cursor2", "second")); - when(client.nextPage("my_cursor2")).thenReturn(new PlainResponse(678, "", "third")); + when(client.queryInit("test query", 10)).thenReturn(fakeResponse("my_cursor1", true, "first")); + when(client.nextPage("my_cursor1")).thenReturn(fakeResponse("my_cursor2", false, "second")); + when(client.nextPage("my_cursor2")).thenReturn(fakeResponse("", false, "third")); ServerQueryCliCommand cliCommand = new ServerQueryCliCommand(); assertTrue(cliCommand.handle(testTerminal, cliSession, "test query")); - assertEquals("firstsecondthird", testTerminal.toString()); + assertEquals(" field \n---------------\nfirst \nsecond \nthird \n", + testTerminal.toString()); verify(client, times(1)).queryInit(eq("test query"), eq(10)); verify(client, times(2)).nextPage(any()); verifyNoMoreInteractions(client); @@ -65,16 +69,17 @@ public class ServerQueryCliCommandTests extends ESTestCase { public void testTwoPageQueryWithSeparator() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); cliSession.setFetchSize(15); // Set a separator cliSession.setFetchSeparator("-----"); - when(client.queryInit("test query", 15)).thenReturn(new PlainResponse(123, "my_cursor1", "first")); - when(client.nextPage("my_cursor1")).thenReturn(new PlainResponse(345, "", "second")); + when(client.queryInit("test query", 15)).thenReturn(fakeResponse("my_cursor1", true, "first")); + when(client.nextPage("my_cursor1")).thenReturn(fakeResponse("", false, "second")); ServerQueryCliCommand cliCommand = new ServerQueryCliCommand(); assertTrue(cliCommand.handle(testTerminal, cliSession, "test query")); - assertEquals("first-----\nsecond", testTerminal.toString()); + assertEquals(" field \n---------------\nfirst \n-----\nsecond \n", + testTerminal.toString()); verify(client, times(1)).queryInit(eq("test query"), eq(15)); verify(client, times(1)).nextPage(any()); verifyNoMoreInteractions(client); @@ -82,19 +87,35 @@ public class ServerQueryCliCommandTests extends ESTestCase { public void testCursorCleanupOnError() throws Exception { TestTerminal testTerminal = new TestTerminal(); - CliHttpClient client = mock(CliHttpClient.class); + HttpClient client = mock(HttpClient.class); CliSession cliSession = new CliSession(client); cliSession.setFetchSize(15); - when(client.queryInit("test query", 15)).thenReturn(new PlainResponse(123, "my_cursor1", "first")); + when(client.queryInit("test query", 15)).thenReturn(fakeResponse("my_cursor1", true, "first")); when(client.nextPage("my_cursor1")).thenThrow(new SQLException("test exception")); when(client.queryClose("my_cursor1")).thenReturn(true); ServerQueryCliCommand cliCommand = new ServerQueryCliCommand(); assertTrue(cliCommand.handle(testTerminal, cliSession, "test query")); - assertEquals("firstBad request [test exception]\n", testTerminal.toString()); + assertEquals(" field \n---------------\nfirst \n" + + "Bad request [test exception]\n", testTerminal.toString()); verify(client, times(1)).queryInit(eq("test query"), eq(15)); verify(client, times(1)).nextPage(any()); verify(client, times(1)).queryClose(eq("my_cursor1")); verifyNoMoreInteractions(client); } + private SqlResponse fakeResponse(String cursor, boolean includeColumns, String val) { + List> rows; + List columns; + if (includeColumns) { + columns = Collections.singletonList(new SqlResponse.ColumnInfo("field", "string", JDBCType.VARCHAR, 0)); + } else { + columns = null; + } + if (val != null) { + rows = Collections.singletonList(Collections.singletonList(val)); + } else { + rows = Collections.singletonList(Collections.emptyList()); + } + return new SqlResponse(cursor, columns, rows); + } } \ No newline at end of file diff --git a/sql/jdbc/build.gradle b/sql/jdbc/build.gradle index 551a9f8d1e5..ee671d084a0 100644 --- a/sql/jdbc/build.gradle +++ b/sql/jdbc/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.github.johnrengelman.shadow' version '2.0.1' + id 'com.github.johnrengelman.shadow' version '2.0.2' } import org.elasticsearch.gradle.test.RunTask @@ -12,7 +12,10 @@ forbiddenApisMain { } dependencies { - compile project(':x-pack-elasticsearch:sql:shared-client') + compile (project(':x-pack-elasticsearch:sql:shared-client')) { + // TODO: For now remove extra dependencies, we will add them back when we migrate JDBC to REST + transitive = false + } compile project(':x-pack-elasticsearch:sql:jdbc-proto') compile project(':x-pack-elasticsearch:sql:shared-proto') runtime "com.fasterxml.jackson.core:jackson-core:${versions.jackson}" @@ -27,6 +30,8 @@ dependencyLicenses { mapping from: /shared-client.*/, to: 'elasticsearch' mapping from: /shared-proto.*/, to: 'elasticsearch' mapping from: /jackson-.*/, to: 'jackson' + mapping from: /rest-proto.*/, to: 'elasticsearch' + ignoreSha 'rest-proto' ignoreSha 'jdbc-proto' ignoreSha 'shared-client' ignoreSha 'shared-proto' diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java b/sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java similarity index 100% rename from sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java rename to sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/CliFormatter.java diff --git a/sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlResponse.java b/sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlResponse.java index 18654a2c3f4..ee28bd9fd78 100644 --- a/sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlResponse.java +++ b/sql/rest-proto/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlResponse.java @@ -7,12 +7,16 @@ package org.elasticsearch.xpack.sql.plugin; 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.io.stream.Writeable; +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 java.io.IOException; import java.sql.JDBCType; @@ -21,15 +25,36 @@ 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.parseStoredFieldsValue; /** * Response to perform an sql query */ public class SqlResponse extends ActionResponse implements ToXContentObject { + public static final String JDBC_ENABLED_PARAM = "jdbc_enabled"; + public static final int UNKNOWN_DISPLAY_SIZE = -1; + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("sql", true, + objects -> new SqlResponse( + 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 long size; - private int columnCount; private List columns; // TODO investigate reusing Page here - it probably is much more efficient private List> rows; @@ -37,12 +62,8 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { public SqlResponse() { } - public SqlResponse(String cursor, long size, int columnCount, @Nullable List columns, List> rows) { + public SqlResponse(String cursor, @Nullable List columns, List> rows) { this.cursor = cursor; - this.size = size; - // Size isn't the total number of results like ES uses, it is the size of the current rows list. - // While not necessary internally, it is useful for REST responses - this.columnCount = columnCount; this.columns = columns; this.rows = rows; } @@ -56,7 +77,7 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { } public long size() { - return size; + return rows.size(); } public List columns() { @@ -67,12 +88,28 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { return rows; } + public SqlResponse cursor(String cursor) { + this.cursor = cursor; + return this; + } + + public SqlResponse columns(List columns) { + this.columns = columns; + return this; + } + + public SqlResponse rows(List> rows) { + this.rows = rows; + return this; + } + @Override public void readFrom(StreamInput in) throws IOException { cursor = in.readString(); - size = in.readVLong(); - columnCount = in.readVInt(); if (in.readBoolean()) { + // We might have rows without columns and we might have columns without rows + // So we send the column size twice, just to keep the protocol simple + int columnCount = in.readVInt(); List columns = new ArrayList<>(columnCount); for (int c = 0; c < columnCount; c++) { columns.add(new ColumnInfo(in)); @@ -83,12 +120,15 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { } int rowCount = in.readVInt(); List> rows = new ArrayList<>(rowCount); - for (int r = 0; r < rowCount; r++) { - List row = new ArrayList<>(columnCount); - for (int c = 0; c < columnCount; c++) { - row.add(in.readGenericValue()); + if (rowCount > 0) { + int columnCount = in.readVInt(); + for (int r = 0; r < rowCount; r++) { + List row = new ArrayList<>(columnCount); + for (int c = 0; c < columnCount; c++) { + row.add(in.readGenericValue()); + } + rows.add(unmodifiableList(row)); } - rows.add(unmodifiableList(row)); } this.rows = unmodifiableList(rows); } @@ -96,41 +136,40 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { @Override public void writeTo(StreamOutput out) throws IOException { out.writeString(cursor); - out.writeVLong(size); - out.writeVInt(columnCount); if (columns == null) { out.writeBoolean(false); } else { out.writeBoolean(true); - assert columns.size() == columnCount; + out.writeVInt(columns.size()); for (ColumnInfo column : columns) { column.writeTo(out); } } out.writeVInt(rows.size()); - for (List row : rows) { - assert row.size() == columnCount; - for (Object value : row) { - out.writeGenericValue(value); + if (rows.size() > 0) { + out.writeVInt(rows.get(0).size()); + for (List row : rows) { + for (Object value : row) { + out.writeGenericValue(value); + } } } } @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + boolean isJdbcAllowed = params.paramAsBoolean(JDBC_ENABLED_PARAM, true); builder.startObject(); { - builder.field("size", size()); if (columns != null) { builder.startArray("columns"); { for (ColumnInfo column : columns) { - column.toXContent(builder, params); + column.toXContent(builder, isJdbcAllowed); } } builder.endArray(); } - builder.startArray("rows"); for (List row : rows()) { builder.startArray(); @@ -148,20 +187,49 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { return builder.endObject(); } + public static SqlResponse 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(parseStoredFieldsValue(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; SqlResponse that = (SqlResponse) o; - return size == that.size && - Objects.equals(cursor, that.cursor) && + return Objects.equals(cursor, that.cursor) && Objects.equals(columns, that.columns) && Objects.equals(rows, that.rows); } @Override public int hashCode() { - return Objects.hash(cursor, size, columns, rows); + return Objects.hash(cursor, columns, rows); } @Override @@ -169,6 +237,27 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { return Strings.toString(this); } + + private static final ConstructingObjectParser COLUMN_INFO_PARSER = + new ConstructingObjectParser<>("sql", true, objects -> + new ColumnInfo( + (String) objects[0], + (String) objects[1], + objects[2] == null ? null : JDBCType.valueOf((int) objects[2]), + objects[3] == null ? UNKNOWN_DISPLAY_SIZE : (int) objects[3])); + + 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 DISPLAY_SIZE = new ParseField("display_size"); + + static { + COLUMN_INFO_PARSER.declareString(constructorArg(), NAME); + COLUMN_INFO_PARSER.declareString(constructorArg(), ES_TYPE); + COLUMN_INFO_PARSER.declareInt(optionalConstructorArg(), JDBC_TYPE); + COLUMN_INFO_PARSER.declareInt(optionalConstructorArg(), DISPLAY_SIZE); + } + /** * Information about a column. */ @@ -202,13 +291,25 @@ public class SqlResponse extends ActionResponse implements ToXContentObject { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + return toXContent(builder, params.paramAsBoolean(JDBC_ENABLED_PARAM, true)); + } + + public XContentBuilder toXContent(XContentBuilder builder, boolean isJdbcAllowed) throws IOException { builder.startObject(); builder.field("name", name); builder.field("type", esType); - // TODO include jdbc_type? + if (isJdbcAllowed && jdbcType != null) { + builder.field("jdbc_type", jdbcType.getVendorTypeNumber()); + builder.field("display_size", displaySize); + } return builder.endObject(); } + + public static ColumnInfo fromXContent(XContentParser parser) { + return COLUMN_INFO_PARSER.apply(parser, null); + } + /** * Name of the column. */ diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlRequestTests.java b/sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlRequestTests.java similarity index 77% rename from sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlRequestTests.java rename to sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlRequestTests.java index 8717afcb480..b84b29c0e3a 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlRequestTests.java +++ b/sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlRequestTests.java @@ -3,9 +3,8 @@ * 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.sql.action; +package org.elasticsearch.xpack.sql.plugin; -import org.elasticsearch.Version; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; @@ -13,32 +12,25 @@ import org.elasticsearch.search.SearchModule; import org.elasticsearch.test.AbstractStreamableTestCase; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.EqualsHashCodeTestUtils.MutateFunction; -import org.elasticsearch.xpack.sql.plugin.SqlPlugin; -import org.elasticsearch.xpack.sql.plugin.SqlRequest; -import org.elasticsearch.xpack.sql.session.Cursor; +import org.elasticsearch.xpack.sql.test.SqlTestUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static org.elasticsearch.xpack.sql.SqlTestUtils.randomFilter; -import static org.elasticsearch.xpack.sql.SqlTestUtils.randomFilterOrNull; -import static org.elasticsearch.xpack.sql.plugin.sql.action.SqlResponseTests.randomCursor; - public class SqlRequestTests extends AbstractStreamableTestCase { @Override protected NamedWriteableRegistry getNamedWriteableRegistry() { SearchModule searchModule = new SearchModule(Settings.EMPTY, false, Collections.emptyList()); List namedWriteables = new ArrayList<>(); namedWriteables.addAll(searchModule.getNamedWriteables()); - namedWriteables.addAll(SqlPlugin.getNamedWriteables()); return new NamedWriteableRegistry(namedWriteables); } @Override protected SqlRequest createTestInstance() { - return new SqlRequest(randomAlphaOfLength(10), randomFilterOrNull(random()), randomDateTimeZone(), - between(1, Integer.MAX_VALUE), randomTV(), randomTV(), Cursor.encodeToString(Version.CURRENT, randomCursor())); + return new SqlRequest(randomAlphaOfLength(10), SqlTestUtils.randomFilterOrNull(random()), randomDateTimeZone(), + between(1, Integer.MAX_VALUE), randomTV(), randomTV(), randomAlphaOfLength(10)); } private TimeValue randomTV() { @@ -67,6 +59,6 @@ public class SqlRequestTests extends AbstractStreamableTestCase { request -> (SqlRequest) getCopyFunction().copy(request) .pageTimeout(randomValueOtherThan(request.pageTimeout(), () -> randomTV())), request -> (SqlRequest) getCopyFunction().copy(request).filter(randomValueOtherThan(request.filter(), - () -> request.filter() == null ? randomFilter(random()) : randomFilterOrNull(random())))); + () -> request.filter() == null ? SqlTestUtils.randomFilter(random()) : SqlTestUtils.randomFilterOrNull(random())))); } } diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlResponseTests.java b/sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlResponseTests.java similarity index 53% rename from sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlResponseTests.java rename to sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlResponseTests.java index 5e91866c225..03d7ab0484d 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/sql/action/SqlResponseTests.java +++ b/sql/rest-proto/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlResponseTests.java @@ -3,69 +3,32 @@ * 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.sql.action; +package org.elasticsearch.xpack.sql.plugin; -import org.elasticsearch.Version; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.test.AbstractStreamableTestCase; -import org.elasticsearch.xpack.sql.execution.search.ScrollCursorTests; -import org.elasticsearch.xpack.sql.plugin.CliFormatter; -import org.elasticsearch.xpack.sql.plugin.CliFormatterCursor; -import org.elasticsearch.xpack.sql.plugin.JdbcCursor; -import org.elasticsearch.xpack.sql.plugin.SqlPlugin; -import org.elasticsearch.xpack.sql.plugin.SqlRequest; -import org.elasticsearch.xpack.sql.plugin.SqlResponse; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractStreamableXContentTestCase; +import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.plugin.SqlResponse.ColumnInfo; -import org.elasticsearch.xpack.sql.session.Cursor; import java.io.IOException; import java.sql.JDBCType; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import static org.hamcrest.Matchers.hasSize; -public class SqlResponseTests extends AbstractStreamableTestCase { +public class SqlResponseTests extends AbstractStreamableXContentTestCase { + static String randomStringCursor() { - return Cursor.encodeToString(Version.CURRENT, randomCursor()); - } - - static Cursor randomCursor() { - return randomBoolean() ? Cursor.EMPTY : randomNonEmptyCursor(); - } - - static Cursor randomNonEmptyCursor() { - switch (randomIntBetween(0, 2)) { - case 0: - return ScrollCursorTests.randomScrollCursor(); - case 1: - int typeNum = randomIntBetween(0, 10); - List types = new ArrayList<>(); - for (int i = 0; i < typeNum; i++) { - types.add(randomFrom(JDBCType.values())); - } - return JdbcCursor.wrap(ScrollCursorTests.randomScrollCursor(), types); - case 2: - SqlResponse response = createRandomInstance(""); - if (response.columns() != null && response.rows() != null) { - return CliFormatterCursor.wrap(ScrollCursorTests.randomScrollCursor(), new CliFormatter(response)); - } else { - return ScrollCursorTests.randomScrollCursor(); - } - default: - throw new IllegalArgumentException("Unexpected random value "); - } - } - - @Override - protected NamedWriteableRegistry getNamedWriteableRegistry() { - return new NamedWriteableRegistry(SqlPlugin.getNamedWriteables()); + return randomBoolean() ? "" : randomAlphaOfLength(10); } @Override @@ -93,13 +56,18 @@ public class SqlResponseTests extends AbstractStreamableTestCase { for (int r = 0; r < rowCount; r++) { List row = new ArrayList<>(rowCount); for (int c = 0; c < columnCount; c++) { - row.add(randomBoolean() ? randomAlphaOfLength(10) : randomInt()); + Supplier value = randomFrom(Arrays.asList( + () -> randomAlphaOfLength(10), + ESTestCase::randomLong, + ESTestCase::randomDouble, + () -> null)); + row.add(value.get()); + } rows.add(row); } } - - return new SqlResponse(cursor, randomNonNegativeLong(), columnCount, columns, rows); + return new SqlResponse(cursor, columns, rows); } @Override @@ -110,12 +78,15 @@ public class SqlResponseTests extends AbstractStreamableTestCase { public void testToXContent() throws IOException { SqlResponse testInstance = createTestInstance(); - XContentBuilder builder = testInstance.toXContent(XContentFactory.jsonBuilder(), ToXContent.EMPTY_PARAMS); + boolean jdbcEnabled = randomBoolean(); + ToXContent.Params params = + new ToXContent.MapParams(Collections.singletonMap(SqlResponse.JDBC_ENABLED_PARAM, Boolean.toString(jdbcEnabled))); + + XContentBuilder builder = testInstance.toXContent(XContentFactory.jsonBuilder(), params); Map rootMap = XContentHelper.convertToMap(builder.bytes(), false, builder.contentType()).v2(); logger.info(builder.string()); - assertEquals(testInstance.size(), rootMap.get("size")); if (testInstance.columns() != null) { List columns = (List) rootMap.get("columns"); assertThat(columns, hasSize(testInstance.columns().size())); @@ -124,6 +95,13 @@ public class SqlResponseTests extends AbstractStreamableTestCase { ColumnInfo columnInfo = testInstance.columns().get(i); assertEquals(columnInfo.name(), columnMap.get("name")); assertEquals(columnInfo.esType(), columnMap.get("type")); + if (jdbcEnabled) { + assertEquals(columnInfo.displaySize(), columnMap.get("display_size")); + assertEquals(columnInfo.jdbcType().getVendorTypeNumber(), columnMap.get("jdbc_type")); + } else { + assertNull(columnMap.get("display_size")); + assertNull(columnMap.get("jdbc_type")); + } } } else { assertNull(rootMap.get("columns")); @@ -141,17 +119,8 @@ public class SqlResponseTests extends AbstractStreamableTestCase { } } - public void testVersionHandling() { - Cursor cursor = randomNonEmptyCursor(); - assertEquals(cursor, Cursor.decodeFromString(Cursor.encodeToString(Version.CURRENT, cursor))); - - Version nextMinorVersion = Version.fromId(Version.CURRENT.id + 10000); - - String encodedWithWrongVersion = Cursor.encodeToString(nextMinorVersion, cursor); - RuntimeException exception = expectThrows(RuntimeException.class, () -> { - Cursor.decodeFromString(encodedWithWrongVersion); - }); - - assertEquals(exception.getMessage(), "Unsupported scroll version " + nextMinorVersion); + @Override + protected SqlResponse doParseInstance(XContentParser parser) { + return SqlResponse.fromXContent(parser); } } diff --git a/sql/server/build.gradle b/sql/server/build.gradle index 9ac44dc815f..6ccbf3d9e2f 100644 --- a/sql/server/build.gradle +++ b/sql/server/build.gradle @@ -7,6 +7,7 @@ dependencies { compile 'org.antlr:antlr4-runtime:4.5.3' provided "org.elasticsearch:elasticsearch:${project.versions.elasticsearch}" + testCompile project(':x-pack-elasticsearch:sql:test-utils') } dependencyLicenses { diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java index 1044eb2d90c..65467aad7d6 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java @@ -72,11 +72,7 @@ public class FieldHitExtractor implements HitExtractor { if (useDocValue) { DocumentField field = hit.field(fieldName); if (field != null) { - checkMultiValue(field.getValues()); - value = field.getValue(); - if (value instanceof ReadableInstant) { - value = ((ReadableInstant) value).getMillis(); - } + value = unwrapMultiValue(field.getValues()); } } else { Map source = hit.getSourceAsMap(); @@ -87,29 +83,50 @@ public class FieldHitExtractor implements HitExtractor { return value; } - private void checkMultiValue(Object values) { - if (!ARRAYS_LENIENCY && values != null && values instanceof List && ((List) values).size() > 1) { - throw new ExecutionException("Arrays (returned by [%s]) are not supported", fieldName); + private Object unwrapMultiValue(Object values) { + if (values == null) { + return null; } + if (values instanceof List) { + List list = (List) values; + if (list.isEmpty()) { + return null; + } else { + if (ARRAYS_LENIENCY || list.size() == 1) { + return unwrapMultiValue(list.get(0)); + } else { + throw new ExecutionException("Arrays (returned by [%s]) are not supported", fieldName); + } + } + } + if (values instanceof Map) { + throw new ExecutionException("Objects (returned by [%s]) are not supported", fieldName); + } + if (values instanceof Long || values instanceof Double || values instanceof String || values instanceof Boolean) { + return values; + } + if (values instanceof ReadableInstant) { + return ((ReadableInstant) values).getMillis(); + } + throw new ExecutionException("Type %s (returned by [%s]) is not supported", values.getClass().getSimpleName(), fieldName); } @SuppressWarnings("unchecked") Object extractFromSource(Map map) { - Object value = null; + Object value = map; + boolean first = true; // each node is a key inside the map for (String node : path) { - // if it's not the first step, start unpacking - if (value != null) { - if (value instanceof Map) { - map = (Map) value; - } else { - throw new ExecutionException("Cannot extract value [%s] from source", fieldName); - } + if (value == null) { + return null; + } else if (first || value instanceof Map) { + first = false; + value = ((Map) value).get(node); + } else { + throw new ExecutionException("Cannot extract value [%s] from source", fieldName); } - value = map.get(node); } - checkMultiValue(value); - return value; + return unwrapMultiValue(value); } @Override diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlAction.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlAction.java index cf51b106a91..e4e0f4894e6 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlAction.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/RestSqlAction.java @@ -8,6 +8,8 @@ package org.elasticsearch.xpack.sql.plugin; import org.elasticsearch.Version; import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.BaseRestHandler; @@ -22,15 +24,19 @@ import org.elasticsearch.xpack.sql.session.Cursor; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Collections; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; public class RestSqlAction extends BaseRestHandler { - public RestSqlAction(Settings settings, RestController controller) { + private final SqlLicenseChecker sqlLicenseChecker; + + public RestSqlAction(Settings settings, RestController controller, SqlLicenseChecker sqlLicenseChecker) { super(settings); controller.registerHandler(GET, SqlAction.REST_ENDPOINT, this); controller.registerHandler(POST, SqlAction.REST_ENDPOINT, this); + this.sqlLicenseChecker = sqlLicenseChecker; } @Override @@ -43,7 +49,17 @@ public class RestSqlAction extends BaseRestHandler { XContentType xContentType = XContentType.fromMediaTypeOrFormat(request.param("format", request.header("Accept"))); if (xContentType != null) { // The client expects us to send back results in a XContent format - return channel -> client.executeLocally(SqlAction.INSTANCE, sqlRequest, new RestToXContentListener<>(channel)); + return channel -> client.executeLocally(SqlAction.INSTANCE, sqlRequest, new RestToXContentListener(channel) { + @Override + public RestResponse buildResponse(SqlResponse response, XContentBuilder builder) throws Exception { + // Make sure we only display JDBC-related data if JDBC is enabled + ToXContent.Params params = new ToXContent.DelegatingMapParams( + Collections.singletonMap(SqlResponse.JDBC_ENABLED_PARAM, Boolean.toString(sqlLicenseChecker.isJdbcAllowed())), + channel.request()); + response.toXContent(builder, params); + return new BytesRestResponse(getStatus(response), builder); + } + }); } // The client accepts plain text long startNanos = System.nanoTime(); diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java index 0b61960d7e2..bb244cdf0b6 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlLicenseChecker.java @@ -5,6 +5,8 @@ */ package org.elasticsearch.xpack.sql.plugin; +import java.util.function.Supplier; + /** * Determines if different features of SQL should be enabled */ @@ -12,10 +14,12 @@ public class SqlLicenseChecker { private final Runnable checkIfSqlAllowed; private final Runnable checkIfJdbcAllowed; + private final Supplier isJdbcAllowed; - public SqlLicenseChecker(Runnable checkIfSqlAllowed, Runnable checkIfJdbcAllowed) { + public SqlLicenseChecker(Runnable checkIfSqlAllowed, Runnable checkIfJdbcAllowed, Supplier isJdbcAllowed) { this.checkIfSqlAllowed = checkIfSqlAllowed; this.checkIfJdbcAllowed = checkIfJdbcAllowed; + this.isJdbcAllowed = isJdbcAllowed; } /** @@ -31,4 +35,8 @@ public class SqlLicenseChecker { public void checkIfJdbcAllowed() { checkIfJdbcAllowed.run(); } + + public boolean isJdbcAllowed() { + return isJdbcAllowed.get(); + } } diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java index 9e0c29df768..aa364c85e54 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java @@ -64,7 +64,7 @@ public class SqlPlugin implements ActionPlugin { return emptyList(); } - return Arrays.asList(new RestSqlAction(settings, restController), + return Arrays.asList(new RestSqlAction(settings, restController, sqlLicenseChecker), new SqlTranslateAction.RestAction(settings, restController), new RestSqlJdbcAction(settings, restController, sqlLicenseChecker, indexResolver), new RestSqlClearCursorAction(settings, restController)); diff --git a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlAction.java b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlAction.java index 5b79f69008f..14e9306e5ab 100644 --- a/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlAction.java +++ b/sql/server/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlAction.java @@ -87,8 +87,6 @@ public class TransportSqlAction extends HandledTransportAction columns = null; + if (randomBoolean()) { + columns = new ArrayList<>(columnCount); + for (int i = 0; i < columnCount; i++) { + columns.add(new SqlResponse.ColumnInfo(randomAlphaOfLength(10), randomAlphaOfLength(10), randomFrom(JDBCType.values()), randomInt(25))); + } + } + return new SqlResponse("", columns, Collections.emptyList()); + } + + static Cursor randomNonEmptyCursor() { + switch (randomIntBetween(0, 2)) { + case 0: + return ScrollCursorTests.randomScrollCursor(); + case 1: + int typeNum = randomIntBetween(0, 10); + List types = new ArrayList<>(); + for (int i = 0; i < typeNum; i++) { + types.add(randomFrom(JDBCType.values())); + } + return JdbcCursor.wrap(ScrollCursorTests.randomScrollCursor(), types); + case 2: + SqlResponse response = createRandomSqlResponse(); + if (response.columns() != null && response.rows() != null) { + return CliFormatterCursor.wrap(ScrollCursorTests.randomScrollCursor(), new CliFormatter(response)); + } else { + return ScrollCursorTests.randomScrollCursor(); + } + default: + throw new IllegalArgumentException("Unexpected random value "); + } + } + + public void testVersionHandling() { + Cursor cursor = randomNonEmptyCursor(); + assertEquals(cursor, Cursor.decodeFromString(Cursor.encodeToString(Version.CURRENT, cursor))); + + Version nextMinorVersion = Version.fromId(Version.CURRENT.id + 10000); + + String encodedWithWrongVersion = Cursor.encodeToString(nextMinorVersion, cursor); + RuntimeException exception = expectThrows(RuntimeException.class, () -> { + Cursor.decodeFromString(encodedWithWrongVersion); + }); + + assertEquals(exception.getMessage(), "Unsupported scroll version " + nextMinorVersion); + } + + } diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java b/sql/server/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java index cf6834bcd91..4aaf02bc052 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java +++ b/sql/server/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java @@ -12,10 +12,13 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.search.SearchHit; import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.execution.ExecutionException; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.Supplier; @@ -62,7 +65,7 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase documentFieldValues = new ArrayList<>(); if (randomBoolean()) { - documentFieldValues.add(new Object()); + documentFieldValues.add(randomValue()); } SearchHit hit = new SearchHit(1); @@ -85,12 +88,7 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase valueSupplier = randomFrom( - () -> randomAlphaOfLength(5), - () -> randomInt(), - () -> randomDouble()); - Object value = valueSupplier.get(); + Object value = randomValue(); SearchHit hit = new SearchHit(1); XContentBuilder source = JsonXContent.contentBuilder(); boolean hasGrandparent = randomBoolean(); @@ -129,7 +127,7 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase documentFieldValues = new ArrayList<>(); if (randomBoolean()) { - documentFieldValues.add(new Object()); + documentFieldValues.add(randomValue()); } SearchHit hit = new SearchHit(1); DocumentField field = new DocumentField(fieldName, documentFieldValues); @@ -147,12 +145,7 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase valueSupplier = randomFrom( - () -> randomAlphaOfLength(5), - () -> randomInt(), - () -> randomDouble()); - Object value = valueSupplier.get(); + Object value = randomValue(); SearchHit hit = new SearchHit(1); XContentBuilder source = JsonXContent.contentBuilder(); source.startObject(); { @@ -182,16 +175,46 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase fe.get(hit)); + assertThat(ex.getMessage(), is("Arrays (returned by [" + fieldName + "]) are not supported")); + } + + public void testSingleValueArrayInSource() throws IOException { + String fieldName = randomAlphaOfLength(5); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, false); + SearchHit hit = new SearchHit(1); + XContentBuilder source = JsonXContent.contentBuilder(); + Object value = randomValue(); + source.startObject(); { + source.field(fieldName, Collections.singletonList(value)); + } + source.endObject(); + BytesReference sourceRef = source.bytes(); + hit.sourceRef(sourceRef); + assertEquals(value, fe.get(hit)); + } + public void testExtractSourcePath() { FieldHitExtractor fe = new FieldHitExtractor("a.b.c", false); - Object value = new Object(); + Object value = randomValue(); Map map = singletonMap("a", singletonMap("b", singletonMap("c", value))); assertThat(fe.extractFromSource(map), is(value)); } public void testExtractSourceIncorrectPath() { FieldHitExtractor fe = new FieldHitExtractor("a.b.c.d", false); - Object value = new Object(); + Object value = randomNonNullValue(); Map map = singletonMap("a", singletonMap("b", singletonMap("c", value))); ExecutionException ex = expectThrows(ExecutionException.class, () -> fe.extractFromSource(map)); assertThat(ex.getMessage(), is("Cannot extract value [a.b.c.d] from source")); @@ -199,9 +222,26 @@ public class FieldHitExtractorTests extends AbstractWireSerializingTestCase map = singletonMap("a", asList(value, value)); ExecutionException ex = expectThrows(ExecutionException.class, () -> fe.extractFromSource(map)); assertThat(ex.getMessage(), is("Arrays (returned by [a]) are not supported")); } + + public Object randomValue() { + Supplier value = randomFrom(Arrays.asList( + () -> randomAlphaOfLength(10), + ESTestCase::randomLong, + ESTestCase::randomDouble, + () -> null)); + return value.get(); + } + + public Object randomNonNullValue() { + Supplier value = randomFrom(Arrays.asList( + () -> randomAlphaOfLength(10), + ESTestCase::randomLong, + ESTestCase::randomDouble)); + return value.get(); + } } \ No newline at end of file diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java index 52440394bb2..64007b833ad 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java +++ b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/CliFormatterTests.java @@ -14,7 +14,7 @@ import java.util.Arrays; import static org.hamcrest.Matchers.arrayWithSize; public class CliFormatterTests extends ESTestCase { - private final SqlResponse firstResponse = new SqlResponse("", 10, 5, + private final SqlResponse firstResponse = new SqlResponse("", Arrays.asList( new ColumnInfo("foo", "string", JDBCType.VARCHAR, 0), new ColumnInfo("bar", "long", JDBCType.BIGINT, 15), @@ -47,7 +47,7 @@ public class CliFormatterTests extends ESTestCase { * truncation of long columns. */ public void testFormatWithoutHeader() { - String[] result = formatter.formatWithoutHeader(new SqlResponse("", 10, 5, null, + String[] result = formatter.formatWithoutHeader(new SqlResponse("", null, Arrays.asList( Arrays.asList("ohnotruncateddata", 4, 1, 77, "wombat"), Arrays.asList("dog", 2, 123124.888, 9912, "goat")))).split("\n"); diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java index 801ad86ea46..134ae078dda 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java +++ b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlPluginTests.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.mock; public class SqlPluginTests extends ESTestCase { public void testSqlDisabled() { - SqlPlugin plugin = new SqlPlugin(false, new SqlLicenseChecker(() -> {}, () -> {})); + SqlPlugin plugin = new SqlPlugin(false, new SqlLicenseChecker(() -> {}, () -> {}, () -> true)); assertThat(plugin.createComponents(mock(Client.class)), empty()); assertThat(plugin.getActions(), empty()); assertThat(plugin.getRestHandlers(Settings.EMPTY, mock(RestController.class), diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java index ed90022da58..0f89035cea4 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java +++ b/sql/server/src/test/java/org/elasticsearch/xpack/sql/plugin/SqlTranslateRequestTests.java @@ -15,8 +15,8 @@ import org.elasticsearch.test.EqualsHashCodeTestUtils.MutateFunction; import java.util.Collections; -import static org.elasticsearch.xpack.sql.SqlTestUtils.randomFilter; -import static org.elasticsearch.xpack.sql.SqlTestUtils.randomFilterOrNull; +import static org.elasticsearch.xpack.sql.test.SqlTestUtils.randomFilter; +import static org.elasticsearch.xpack.sql.test.SqlTestUtils.randomFilterOrNull; public class SqlTranslateRequestTests extends AbstractStreamableTestCase { diff --git a/sql/shared-client/build.gradle b/sql/shared-client/build.gradle index 5984238c887..98266d30f56 100644 --- a/sql/shared-client/build.gradle +++ b/sql/shared-client/build.gradle @@ -1,11 +1,19 @@ description = 'Code shared between jdbc and cli' dependencies { + compile project(':x-pack-elasticsearch:sql:rest-proto') compile "com.fasterxml.jackson.core:jackson-core:${versions.jackson}" } dependencyLicenses { mapping from: /jackson-.*/, to: 'jackson' + mapping from: /rest-proto.*/, to: 'elasticsearch' + mapping from: /shared-proto.*/, to: 'elasticsearch' + mapping from: /elasticsearch-cli.*/, to: 'elasticsearch' + mapping from: /lucene-.*/, to: 'lucene' + ignoreSha 'rest-proto' + ignoreSha 'shared-proto' + ignoreSha 'elasticsearch' } forbiddenApisMain { diff --git a/sql/shared-client/licenses/elasticsearch-LICENSE.txt b/sql/shared-client/licenses/elasticsearch-LICENSE.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/sql/shared-client/licenses/elasticsearch-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sql/shared-client/licenses/elasticsearch-NOTICE.txt b/sql/shared-client/licenses/elasticsearch-NOTICE.txt new file mode 100644 index 00000000000..643a060cd05 --- /dev/null +++ b/sql/shared-client/licenses/elasticsearch-NOTICE.txt @@ -0,0 +1,5 @@ +Elasticsearch +Copyright 2009-2017 Elasticsearch + +This product includes software developed by The Apache Software +Foundation (http://www.apache.org/). diff --git a/sql/shared-client/licenses/joda-time-2.9.5.jar.sha1 b/sql/shared-client/licenses/joda-time-2.9.5.jar.sha1 new file mode 100644 index 00000000000..ecf1c781556 --- /dev/null +++ b/sql/shared-client/licenses/joda-time-2.9.5.jar.sha1 @@ -0,0 +1 @@ +5f01da7306363fad2028b916f3eab926262de928 \ No newline at end of file diff --git a/sql/shared-client/licenses/joda-time-LICENSE.txt b/sql/shared-client/licenses/joda-time-LICENSE.txt new file mode 100644 index 00000000000..75b52484ea4 --- /dev/null +++ b/sql/shared-client/licenses/joda-time-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sql/shared-client/licenses/joda-time-NOTICE.txt b/sql/shared-client/licenses/joda-time-NOTICE.txt new file mode 100644 index 00000000000..dffbcf31cac --- /dev/null +++ b/sql/shared-client/licenses/joda-time-NOTICE.txt @@ -0,0 +1,5 @@ +============================================================================= += NOTICE file corresponding to section 4d of the Apache License Version 2.0 = +============================================================================= +This product includes software developed by +Joda.org (http://www.joda.org/). diff --git a/sql/shared-client/licenses/log4j-api-2.9.1.jar.sha1 b/sql/shared-client/licenses/log4j-api-2.9.1.jar.sha1 new file mode 100644 index 00000000000..e1a89fadfed --- /dev/null +++ b/sql/shared-client/licenses/log4j-api-2.9.1.jar.sha1 @@ -0,0 +1 @@ +7a2999229464e7a324aa503c0a52ec0f05efe7bd \ No newline at end of file diff --git a/sql/shared-client/licenses/log4j-api-LICENSE.txt b/sql/shared-client/licenses/log4j-api-LICENSE.txt new file mode 100644 index 00000000000..6279e5206de --- /dev/null +++ b/sql/shared-client/licenses/log4j-api-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 1999-2005 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sql/shared-client/licenses/log4j-api-NOTICE.txt b/sql/shared-client/licenses/log4j-api-NOTICE.txt new file mode 100644 index 00000000000..03757323600 --- /dev/null +++ b/sql/shared-client/licenses/log4j-api-NOTICE.txt @@ -0,0 +1,5 @@ +Apache log4j +Copyright 2007 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/sql/shared-client/licenses/log4j-core-2.9.1.jar.sha1 b/sql/shared-client/licenses/log4j-core-2.9.1.jar.sha1 new file mode 100644 index 00000000000..990ea322a76 --- /dev/null +++ b/sql/shared-client/licenses/log4j-core-2.9.1.jar.sha1 @@ -0,0 +1 @@ +c041978c686866ee8534f538c6220238db3bb6be \ No newline at end of file diff --git a/sql/shared-client/licenses/log4j-core-LICENSE.txt b/sql/shared-client/licenses/log4j-core-LICENSE.txt new file mode 100644 index 00000000000..6279e5206de --- /dev/null +++ b/sql/shared-client/licenses/log4j-core-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 1999-2005 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sql/shared-client/licenses/log4j-core-NOTICE.txt b/sql/shared-client/licenses/log4j-core-NOTICE.txt new file mode 100644 index 00000000000..03757323600 --- /dev/null +++ b/sql/shared-client/licenses/log4j-core-NOTICE.txt @@ -0,0 +1,5 @@ +Apache log4j +Copyright 2007 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/sql/shared-client/licenses/lucene-LICENSE.txt b/sql/shared-client/licenses/lucene-LICENSE.txt new file mode 100644 index 00000000000..28b134f5f8e --- /dev/null +++ b/sql/shared-client/licenses/lucene-LICENSE.txt @@ -0,0 +1,475 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from unicode conversion examples available at +http://www.unicode.org/Public/PROGRAMS/CVTUTF. Here is the copyright +from those sources: + +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +Some code in core/src/java/org/apache/lucene/util/ArrayUtil.java was +derived from Python 2.4.2 sources available at +http://www.python.org. Full license is here: + + http://www.python.org/download/releases/2.4.2/license/ + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from Python 3.1.2 sources available at +http://www.python.org. Full license is here: + + http://www.python.org/download/releases/3.1.2/license/ + +Some code in core/src/java/org/apache/lucene/util/automaton was +derived from Brics automaton sources available at +www.brics.dk/automaton/. Here is the copyright from those sources: + +/* + * Copyright (c) 2001-2009 Anders Moeller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +The levenshtein automata tables in core/src/java/org/apache/lucene/util/automaton +were automatically generated with the moman/finenight FSA package. +Here is the copyright for those sources: + +# Copyright (c) 2010, Jean-Philippe Barrette-LaPierre, +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +Some code in core/src/java/org/apache/lucene/util/UnicodeUtil.java was +derived from ICU (http://www.icu-project.org) +The full license is available here: + http://source.icu-project.org/repos/icu/icu/trunk/license.html + +/* + * Copyright (C) 1999-2010, International Business Machines + * Corporation and others. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * provided that the above copyright notice(s) and this permission notice appear + * in all copies of the Software and that both the above copyright notice(s) and + * this permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE + * LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR + * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall not + * be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization of the + * copyright holder. + */ + +The following license applies to the Snowball stemmers: + +Copyright (c) 2001, Dr Martin Porter +Copyright (c) 2002, Richard Boulton +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holders nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The following license applies to the KStemmer: + +Copyright © 2003, +Center for Intelligent Information Retrieval, +University of Massachusetts, Amherst. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. The names "Center for Intelligent Information Retrieval" and +"University of Massachusetts" must not be used to endorse or promote products +derived from this software without prior written permission. To obtain +permission, contact info@ciir.cs.umass.edu. + +THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF MASSACHUSETTS AND OTHER CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +The following license applies to the Morfologik project: + +Copyright (c) 2006 Dawid Weiss +Copyright (c) 2007-2011 Dawid Weiss, Marcin Miłkowski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Morfologik nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- + +The dictionary comes from Morfologik project. Morfologik uses data from +Polish ispell/myspell dictionary hosted at http://www.sjp.pl/slownik/en/ and +is licenced on the terms of (inter alia) LGPL and Creative Commons +ShareAlike. The part-of-speech tags were added in Morfologik project and +are not found in the data from sjp.pl. The tagset is similar to IPI PAN +tagset. + +--- + +The following license applies to the Morfeusz project, +used by org.apache.lucene.analysis.morfologik. + +BSD-licensed dictionary of Polish (SGJP) +http://sgjp.pl/morfeusz/ + +Copyright © 2011 Zygmunt Saloni, Włodzimierz Gruszczyński, + Marcin Woliński, Robert Wołosz + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS “AS IS” AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sql/shared-client/licenses/lucene-NOTICE.txt b/sql/shared-client/licenses/lucene-NOTICE.txt new file mode 100644 index 00000000000..1a1d5157243 --- /dev/null +++ b/sql/shared-client/licenses/lucene-NOTICE.txt @@ -0,0 +1,192 @@ +Apache Lucene +Copyright 2014 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Includes software from other Apache Software Foundation projects, +including, but not limited to: + - Apache Ant + - Apache Jakarta Regexp + - Apache Commons + - Apache Xerces + +ICU4J, (under analysis/icu) is licensed under an MIT styles license +and Copyright (c) 1995-2008 International Business Machines Corporation and others + +Some data files (under analysis/icu/src/data) are derived from Unicode data such +as the Unicode Character Database. See http://unicode.org/copyright.html for more +details. + +Brics Automaton (under core/src/java/org/apache/lucene/util/automaton) is +BSD-licensed, created by Anders Møller. See http://www.brics.dk/automaton/ + +The levenshtein automata tables (under core/src/java/org/apache/lucene/util/automaton) were +automatically generated with the moman/finenight FSA library, created by +Jean-Philippe Barrette-LaPierre. This library is available under an MIT license, +see http://sites.google.com/site/rrettesite/moman and +http://bitbucket.org/jpbarrette/moman/overview/ + +The class org.apache.lucene.util.WeakIdentityMap was derived from +the Apache CXF project and is Apache License 2.0. + +The Google Code Prettify is Apache License 2.0. +See http://code.google.com/p/google-code-prettify/ + +JUnit (junit-4.10) is licensed under the Common Public License v. 1.0 +See http://junit.sourceforge.net/cpl-v10.html + +This product includes code (JaspellTernarySearchTrie) from Java Spelling Checkin +g Package (jaspell): http://jaspell.sourceforge.net/ +License: The BSD License (http://www.opensource.org/licenses/bsd-license.php) + +The snowball stemmers in + analysis/common/src/java/net/sf/snowball +were developed by Martin Porter and Richard Boulton. +The snowball stopword lists in + analysis/common/src/resources/org/apache/lucene/analysis/snowball +were developed by Martin Porter and Richard Boulton. +The full snowball package is available from + http://snowball.tartarus.org/ + +The KStem stemmer in + analysis/common/src/org/apache/lucene/analysis/en +was developed by Bob Krovetz and Sergio Guzman-Lara (CIIR-UMass Amherst) +under the BSD-license. + +The Arabic,Persian,Romanian,Bulgarian, Hindi and Bengali analyzers (common) come with a default +stopword list that is BSD-licensed created by Jacques Savoy. These files reside in: +analysis/common/src/resources/org/apache/lucene/analysis/ar/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/fa/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/ro/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/bg/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/hi/stopwords.txt, +analysis/common/src/resources/org/apache/lucene/analysis/bn/stopwords.txt +See http://members.unine.ch/jacques.savoy/clef/index.html. + +The German,Spanish,Finnish,French,Hungarian,Italian,Portuguese,Russian and Swedish light stemmers +(common) are based on BSD-licensed reference implementations created by Jacques Savoy and +Ljiljana Dolamic. These files reside in: +analysis/common/src/java/org/apache/lucene/analysis/de/GermanLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/de/GermanMinimalStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/es/SpanishLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fi/FinnishLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fr/FrenchLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/fr/FrenchMinimalStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/hu/HungarianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/it/ItalianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/pt/PortugueseLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/ru/RussianLightStemmer.java +analysis/common/src/java/org/apache/lucene/analysis/sv/SwedishLightStemmer.java + +The Stempel analyzer (stempel) includes BSD-licensed software developed +by the Egothor project http://egothor.sf.net/, created by Leo Galambos, Martin Kvapil, +and Edmond Nolan. + +The Polish analyzer (stempel) comes with a default +stopword list that is BSD-licensed created by the Carrot2 project. The file resides +in stempel/src/resources/org/apache/lucene/analysis/pl/stopwords.txt. +See http://project.carrot2.org/license.html. + +The SmartChineseAnalyzer source code (smartcn) was +provided by Xiaoping Gao and copyright 2009 by www.imdict.net. + +WordBreakTestUnicode_*.java (under modules/analysis/common/src/test/) +is derived from Unicode data such as the Unicode Character Database. +See http://unicode.org/copyright.html for more details. + +The Morfologik analyzer (morfologik) includes BSD-licensed software +developed by Dawid Weiss and Marcin Miłkowski (http://morfologik.blogspot.com/). + +Morfologik uses data from Polish ispell/myspell dictionary +(http://www.sjp.pl/slownik/en/) licenced on the terms of (inter alia) +LGPL and Creative Commons ShareAlike. + +Morfologic includes data from BSD-licensed dictionary of Polish (SGJP) +(http://sgjp.pl/morfeusz/) + +Servlet-api.jar and javax.servlet-*.jar are under the CDDL license, the original +source code for this can be found at http://www.eclipse.org/jetty/downloads.php + +=========================================================================== +Kuromoji Japanese Morphological Analyzer - Apache Lucene Integration +=========================================================================== + +This software includes a binary and/or source version of data from + + mecab-ipadic-2.7.0-20070801 + +which can be obtained from + + http://atilika.com/releases/mecab-ipadic/mecab-ipadic-2.7.0-20070801.tar.gz + +or + + http://jaist.dl.sourceforge.net/project/mecab/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz + +=========================================================================== +mecab-ipadic-2.7.0-20070801 Notice +=========================================================================== + +Nara Institute of Science and Technology (NAIST), +the copyright holders, disclaims all warranties with regard to this +software, including all implied warranties of merchantability and +fitness, in no event shall NAIST be liable for +any special, indirect or consequential damages or any damages +whatsoever resulting from loss of use, data or profits, whether in an +action of contract, negligence or other tortuous action, arising out +of or in connection with the use or performance of this software. + +A large portion of the dictionary entries +originate from ICOT Free Software. The following conditions for ICOT +Free Software applies to the current dictionary as well. + +Each User may also freely distribute the Program, whether in its +original form or modified, to any third party or parties, PROVIDED +that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear +on, or be attached to, the Program, which is distributed substantially +in the same form as set out herein and that such intended +distribution, if actually made, will neither violate or otherwise +contravene any of the laws and regulations of the countries having +jurisdiction over the User or the intended distribution itself. + +NO WARRANTY + +The program was produced on an experimental basis in the course of the +research and development conducted during the project and is provided +to users as so produced on an experimental basis. Accordingly, the +program is provided without any warranty whatsoever, whether express, +implied, statutory or otherwise. The term "warranty" used herein +includes, but is not limited to, any warranty of the quality, +performance, merchantability and fitness for a particular purpose of +the program and the nonexistence of any infringement or violation of +any right of any third party. + +Each user of the program will agree and understand, and be deemed to +have agreed and understood, that there is no warranty whatsoever for +the program and, accordingly, the entire risk arising from or +otherwise connected with the program is assumed by the user. + +Therefore, neither ICOT, the copyright holder, or any other +organization that participated in or was otherwise related to the +development of the program and their respective officials, directors, +officers and other employees shall be held liable for any and all +damages, including, without limitation, general, special, incidental +and consequential damages, arising out of or otherwise in connection +with the use or inability to use the program or any product, material +or result produced or otherwise obtained by using the program, +regardless of whether they have been advised of, or otherwise had +knowledge of, the possibility of such damages at any time during the +project or thereafter. Each user will be deemed to have agreed to the +foregoing by his or her commencement of use of the program. The term +"use" as used herein includes, but is not limited to, the use, +modification, copying and distribution of the program and the +production of secondary products from the program. + +In the case where the program, whether in its original form or +modified, was distributed or delivered to or received by a user from +any person, organization or entity other than ICOT, unless it makes or +grants independently of ICOT any specific warranty to the user in +writing, such person, organization or entity, will also be exempted +from and not be held liable to the user for any such damages as noted +above as far as the program is concerned. diff --git a/sql/shared-client/licenses/lucene-core-7.2.0.jar.sha1 b/sql/shared-client/licenses/lucene-core-7.2.0.jar.sha1 new file mode 100644 index 00000000000..41e1103ca25 --- /dev/null +++ b/sql/shared-client/licenses/lucene-core-7.2.0.jar.sha1 @@ -0,0 +1 @@ +f88107aa577ce8edc0a5cee036b485943107a552 \ No newline at end of file diff --git a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/CliHttpClient.java b/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java similarity index 53% rename from sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/CliHttpClient.java rename to sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java index c040b03ab5b..c9acc2952a2 100644 --- a/sql/cli/src/main/java/org/elasticsearch/xpack/sql/cli/CliHttpClient.java +++ b/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/HttpClient.java @@ -3,43 +3,49 @@ * 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.cli; +package org.elasticsearch.xpack.sql.client; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.action.main.MainResponse; -import org.elasticsearch.common.CheckedFunction; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.Streams; +import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.xpack.sql.client.shared.CheckedFunction; import org.elasticsearch.xpack.sql.client.shared.ClientException; 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.SqlAction; 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.SqlRequest; +import org.elasticsearch.xpack.sql.plugin.SqlResponse; import org.joda.time.DateTimeZone; -import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.sql.SQLException; import java.util.function.Function; -public class CliHttpClient { +/** + * A specialized high-level REST client with support for SQL-related functions + */ +public class HttpClient { + private static final XContentType REQUEST_BODY_CONTENT_TYPE = XContentType.JSON; private final ConnectionConfiguration cfg; - public CliHttpClient(ConnectionConfiguration cfg) { + public HttpClient(ConnectionConfiguration cfg) throws SQLException { this.cfg = cfg; } @@ -49,17 +55,17 @@ public class CliHttpClient { return get("/", MainResponse::fromXContent); } - public PlainResponse queryInit(String query, int fetchSize) throws SQLException { + public SqlResponse queryInit(String query, int fetchSize) throws SQLException { // TODO allow customizing the time zone - this is what session set/reset/get should be about SqlRequest sqlRequest = new SqlRequest(query, null, DateTimeZone.UTC, fetchSize, TimeValue.timeValueMillis(cfg.queryTimeout()), TimeValue.timeValueMillis(cfg.pageTimeout()), ""); - return postPlain(SqlAction.REST_ENDPOINT, sqlRequest); + return post(SqlAction.REST_ENDPOINT, sqlRequest, SqlResponse::fromXContent); } - public PlainResponse nextPage(String cursor) throws SQLException { + public SqlResponse nextPage(String cursor) throws SQLException { SqlRequest sqlRequest = new SqlRequest(); sqlRequest.cursor(cursor); - return postPlain(SqlAction.REST_ENDPOINT, sqlRequest); + return post(SqlAction.REST_ENDPOINT, sqlRequest, SqlResponse::fromXContent); } public boolean queryClose(String cursor) throws SQLException { @@ -72,73 +78,64 @@ public class CliHttpClient { private Response post(String path, Request request, CheckedFunction responseParser) throws SQLException { - return JreHttpUrlConnection.http(path, "error_trace", cfg, con -> - con.request( - outputStream -> writeTo(request, outputStream), - (in, headers) -> readFrom(in, headers, responseParser), - "POST" - ) - ).getResponseOrThrowException(); + BytesReference requestBytes = toXContent(request); + Tuple response = + AccessController.doPrivileged((PrivilegedAction>>) () -> + JreHttpUrlConnection.http(path, "error_trace", cfg, con -> + con.request( + requestBytes::writeTo, + this::readFrom, + "POST" + ) + )).getResponseOrThrowException(); + return fromXContent(response.v1(), response.v2(), responseParser); } private Response get(String path, CheckedFunction responseParser) throws SQLException { - return JreHttpUrlConnection.http(path, "error_trace", cfg, con -> - con.request( - null, - (in, headers) -> readFrom(in, headers, responseParser), - "GET" - ) - ).getResponseOrThrowException(); + Tuple response = + AccessController.doPrivileged((PrivilegedAction>>) () -> + JreHttpUrlConnection.http(path, "error_trace", cfg, con -> + con.request( + null, + this::readFrom, + "GET" + ) + )).getResponseOrThrowException(); + return fromXContent(response.v1(), response.v2(), responseParser); } - private PlainResponse postPlain(String path, Request request) throws SQLException { - return JreHttpUrlConnection.http(path, "error_trace", cfg, con -> - con.request( - outputStream -> { - writeTo(request, outputStream); - }, - (in, headers) -> { - String cursor = headers.apply("Cursor"); - long tookNanos; - try { - tookNanos = Long.parseLong(headers.apply("Took-nanos")); - } catch (NumberFormatException ex) { - throw new ClientException("Cannot parse Took-nanos header [" + headers.apply("Took-nanos") + "]"); - } - return new PlainResponse(tookNanos, cursor == null ? "" : cursor, readData(in)); - }, - "POST" - ) - ).getResponseOrThrowException(); - } - - private static void writeTo(Request xContent, OutputStream outputStream) { + private static BytesReference toXContent(Request xContent) { try { - BytesRef source = XContentHelper.toXContent(xContent, REQUEST_BODY_CONTENT_TYPE, false).toBytesRef(); - outputStream.write(source.bytes, source.offset, source.length); + return XContentHelper.toXContent(xContent, REQUEST_BODY_CONTENT_TYPE, false); } catch (IOException ex) { throw new ClientException("Cannot serialize request", ex); } - } - private Response readFrom(InputStream inputStream, Function headers, - CheckedFunction responseParser) { + private Tuple readFrom(InputStream inputStream, Function headers) { String contentType = headers.apply("Content-Type"); XContentType xContentType = XContentType.fromMediaTypeOrFormat(contentType); if (xContentType == null) { throw new IllegalStateException("Unsupported Content-Type: " + contentType); } - try (XContentParser parser = xContentType.xContent().createParser(registry, inputStream)) { + BytesStreamOutput out = new BytesStreamOutput(); + try { + Streams.copy(inputStream, out); + } catch (IOException ex) { + throw new ClientException("Cannot deserialize response", ex); + } + return new Tuple<>(xContentType, out.bytes()); + + } + + private Response fromXContent(XContentType xContentType, BytesReference bytesReference, + CheckedFunction responseParser) { + try (XContentParser parser = xContentType.xContent().createParser(registry, bytesReference)) { return responseParser.apply(parser); } catch (IOException ex) { throw new ClientException("Cannot parse response", ex); } } - private static String readData(InputStream in) throws IOException { - return Streams.copyToString(new InputStreamReader(new BufferedInputStream(in), StandardCharsets.UTF_8)); - } - } diff --git a/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/shared/JreHttpUrlConnection.java b/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/shared/JreHttpUrlConnection.java index 491e489cbe9..8bc420954c5 100644 --- a/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/shared/JreHttpUrlConnection.java +++ b/sql/shared-client/src/main/java/org/elasticsearch/xpack/sql/client/shared/JreHttpUrlConnection.java @@ -162,6 +162,7 @@ public class JreHttpUrlConnection implements Closeable { con.setRequestMethod(requestMethod); con.setDoOutput(true); con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Accept", "application/json"); if (doc != null) { try (OutputStream out = con.getOutputStream()) { doc.accept(new DataOutputStream(out)); diff --git a/sql/server/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java b/sql/test-utils/src/main/java/org/elasticsearch/xpack/sql/test/SqlTestUtils.java similarity index 96% rename from sql/server/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java rename to sql/test-utils/src/main/java/org/elasticsearch/xpack/sql/test/SqlTestUtils.java index ff6f0db3f6e..e6026b34625 100644 --- a/sql/server/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java +++ b/sql/test-utils/src/main/java/org/elasticsearch/xpack/sql/test/SqlTestUtils.java @@ -3,7 +3,7 @@ * 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; +package org.elasticsearch.xpack.sql.test; import com.carrotsearch.randomizedtesting.generators.RandomStrings; import org.elasticsearch.index.query.QueryBuilder;