From 3eb1258b0d6ff28240292d97e295cc12b6891b4c Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Mon, 3 Jul 2017 21:01:29 +0300 Subject: [PATCH] Add to CSV infra plus some refactoring of the JDBC one Original commit: elastic/x-pack-elasticsearch@3e002c91c2c5e77e10e1ec1b8aa85f3a9428e7f4 --- sql/cli/build.gradle | 2 +- .../integration/server/CliProtoHandler.java | 3 +- sql/jdbc/build.gradle | 2 +- .../xpack/sql/jdbc/BasicsIT.java | 5 +- .../xpack/sql/jdbc/DatabaseMetaDataIT.java | 4 +- .../sql/jdbc/csv/CsvSpecIntegrationTest.java | 155 ++++++++++++++++++ .../sql/jdbc/framework/CsvInfraSuite.java | 49 ------ .../sql/jdbc/framework/CsvSpecBaseTest.java | 115 ------------- .../jdbc/framework/CsvSpecTableReader.java | 9 +- .../xpack/sql/jdbc/framework/EsInfra.java | 50 ------ .../sql/jdbc/framework/EsJdbcServer.java | 66 ++++++++ .../xpack/sql/jdbc/framework/JdbcAssert.java | 7 +- .../sql/jdbc/framework/JdbcHttpServer.java | 22 +++ ...ationTestCase.java => LocalEsCluster.java} | 101 ++++++------ .../xpack/sql/jdbc/framework/LocalH2.java | 59 +++++++ ....java => SpecBaseIntegrationTestCase.java} | 91 ++++++---- .../sql/jdbc/framework/SqlInfraSuite.java | 49 ------ .../sql/jdbc/framework/SqlProtoHandler.java | 38 +++++ .../sql/jdbc/framework/SqlSpecBaseTest.java | 58 ------- .../TestUtils.java} | 152 +++++++---------- .../xpack/sql/jdbc/h2/AggIT.java | 24 --- .../xpack/sql/jdbc/h2/DateTimeIT.java | 24 --- .../xpack/sql/jdbc/h2/FilterIT.java | 24 --- .../xpack/sql/jdbc/h2/MathIT.java | 21 --- .../xpack/sql/jdbc/h2/SelectIT.java | 24 --- .../sql/jdbc/h2/SqlSpecIntegrationTest.java | 83 ++++++++++ .../test/resources/{agg.spec => agg.sql-spec} | 0 sql/jdbc/src/test/resources/command.csv-spec | 107 ++++++++++++ .../{datetime.spec => datetime.sql-spec} | 0 sql/jdbc/src/test/resources/debug.csv-spec | 53 ++++++ sql/jdbc/src/test/resources/debug.sql-spec | 6 + .../framework => resources}/example.csv-spec | 0 .../framework => resources}/example.sql-spec | 0 .../{filter.spec => filter.sql-spec} | 0 sql/jdbc/src/test/resources/fulltext.csv-spec | 31 ++++ sql/jdbc/src/test/resources/h2-setup.sql | 14 +- .../resources/{math.spec => math.sql-spec} | 0 .../{select.spec => select.sql-spec} | 0 38 files changed, 805 insertions(+), 643 deletions(-) create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/csv/CsvSpecIntegrationTest.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvInfraSuite.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecBaseTest.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsInfra.java create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsJdbcServer.java create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcHttpServer.java rename sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/{JdbcIntegrationTestCase.java => LocalEsCluster.java} (58%) create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalH2.java rename sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/{SpecBaseTest.java => SpecBaseIntegrationTestCase.java} (56%) delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlInfraSuite.java create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlProtoHandler.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlSpecBaseTest.java rename sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/{h2/CompareToH2BaseTestCase.java => framework/TestUtils.java} (52%) delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/AggIT.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/DateTimeIT.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/FilterIT.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/MathIT.java delete mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SelectIT.java create mode 100644 sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SqlSpecIntegrationTest.java rename sql/jdbc/src/test/resources/{agg.spec => agg.sql-spec} (100%) create mode 100644 sql/jdbc/src/test/resources/command.csv-spec rename sql/jdbc/src/test/resources/{datetime.spec => datetime.sql-spec} (100%) create mode 100644 sql/jdbc/src/test/resources/debug.csv-spec create mode 100644 sql/jdbc/src/test/resources/debug.sql-spec rename sql/jdbc/src/test/{java/org/elasticsearch/xpack/sql/jdbc/framework => resources}/example.csv-spec (100%) rename sql/jdbc/src/test/{java/org/elasticsearch/xpack/sql/jdbc/framework => resources}/example.sql-spec (100%) rename sql/jdbc/src/test/resources/{filter.spec => filter.sql-spec} (100%) create mode 100644 sql/jdbc/src/test/resources/fulltext.csv-spec rename sql/jdbc/src/test/resources/{math.spec => math.sql-spec} (100%) rename sql/jdbc/src/test/resources/{select.spec => select.sql-spec} (100%) diff --git a/sql/cli/build.gradle b/sql/cli/build.gradle index 911ad8750c2..da60caac0ff 100644 --- a/sql/cli/build.gradle +++ b/sql/cli/build.gradle @@ -14,7 +14,7 @@ dependencies { testCompile project(':x-pack-elasticsearch:sql:server') runtime "org.fusesource.jansi:jansi:1.16" - runtime "org.elasticsearch:jna:4.4.0" + runtime "org.elasticsearch:jna:4.4.0-1" } dependencyLicenses { diff --git a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/integration/server/CliProtoHandler.java b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/integration/server/CliProtoHandler.java index bd01465757b..4399e92d53e 100644 --- a/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/integration/server/CliProtoHandler.java +++ b/sql/cli/src/test/java/org/elasticsearch/xpack/sql/cli/integration/server/CliProtoHandler.java @@ -27,8 +27,7 @@ class CliProtoHandler extends ProtoHandler { CliProtoHandler(Client client) { super(client, ProtoUtils::readHeader, CliServerProtoUtils::write); - this.server = new CliServer(TestUtils.planExecutor(client), clusterName, () -> info.getNode().getName(), info.getVersion(), - info.getBuild()); + this.server = new CliServer(TestUtils.planExecutor(client), clusterName, () -> info.getNode().getName(), info.getVersion(), info.getBuild()); } @Override diff --git a/sql/jdbc/build.gradle b/sql/jdbc/build.gradle index 3e72e3170e7..67cf37cae55 100644 --- a/sql/jdbc/build.gradle +++ b/sql/jdbc/build.gradle @@ -51,7 +51,7 @@ dependencies { // Used by the hack to run InternalTestCluster if not running against a gradle-started cluster. testCompile project(path: ':modules:lang-painless', configuration: 'runtime') - testRuntime "com.h2database:org.elasticsearch.xpack.sql.jdbc.h2:1.4.194" + testRuntime "com.h2database:h2:1.4.194" testRuntime "net.sourceforge.csvjdbc:csvjdbc:1.0.31" } diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/BasicsIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/BasicsIT.java index 463cfa98429..38a5f081b4d 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/BasicsIT.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/BasicsIT.java @@ -5,7 +5,7 @@ */ package org.elasticsearch.xpack.sql.jdbc; -import org.elasticsearch.xpack.sql.jdbc.framework.JdbcIntegrationTestCase; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase; import java.sql.Connection; import java.sql.SQLException; @@ -18,11 +18,12 @@ import java.util.Map; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +import static org.elasticsearch.xpack.sql.jdbc.framework.TestUtils.index; /** * Test the jdbc driver behavior and the connection to Elasticsearch. */ -public class BasicsIT extends JdbcIntegrationTestCase { +public class BasicsIT extends SpecBaseIntegrationTestCase { // NOCOMMIT these might should move into their own test or be deleted entirely // public void test01Ping() throws Exception { diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/DatabaseMetaDataIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/DatabaseMetaDataIT.java index d3591a6aa6d..ba397a5f2f8 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/DatabaseMetaDataIT.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/DatabaseMetaDataIT.java @@ -5,7 +5,7 @@ */ package org.elasticsearch.xpack.sql.jdbc; -import org.elasticsearch.xpack.sql.jdbc.framework.JdbcIntegrationTestCase; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -18,7 +18,7 @@ import static org.hamcrest.Matchers.startsWith; /** * Tests for our implementation of {@link DatabaseMetaData}. */ -public class DatabaseMetaDataIT extends JdbcIntegrationTestCase { +public class DatabaseMetaDataIT extends SpecBaseIntegrationTestCase { /** * We do not support procedures so we return an empty set for {@link DatabaseMetaData#getProcedures(String, String, String)}. */ diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/csv/CsvSpecIntegrationTest.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/csv/CsvSpecIntegrationTest.java new file mode 100644 index 00000000000..2cca5734d55 --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/csv/CsvSpecIntegrationTest.java @@ -0,0 +1,155 @@ +/* + * 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.jdbc.csv; + +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.xpack.sql.jdbc.framework.CsvSpecTableReader; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase.Parser; +import org.elasticsearch.xpack.sql.util.CollectionUtils; +import org.junit.AfterClass; +import org.junit.Test; +import org.relique.jdbc.csv.CsvDriver; + +import java.io.Reader; +import java.io.StringReader; +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +import static java.lang.String.format; +import static org.elasticsearch.xpack.sql.jdbc.framework.JdbcAssert.assertResultSets; + +public class CsvSpecIntegrationTest extends SpecBaseIntegrationTestCase { + + private static CsvDriver DRIVER = new CsvDriver(); + public static final Map CSV_READERS = new LinkedHashMap<>(); + + private final CsvFragment fragment; + + @AfterClass + public static void cleanup() throws Exception { + CSV_READERS.clear(); + } + + public static CheckedSupplier csvCon(Properties props, Reader reader) { + return new CheckedSupplier() { + @Override + public Connection get() throws SQLException { + Connection con = DRIVER.connect("jdbc:relique:csv:class:" + CsvSpecTableReader.class.getName(), props); + CSV_READERS.put(con, reader); + return con; + } + }; + } + + @ParametersFactory(shuffle = false, argumentFormatting = "name=%1s") + public static List readScriptSpec() throws Exception { + CsvSpecParser parser = new CsvSpecParser(); + return CollectionUtils.combine( + readScriptSpec("/command.csv-spec", parser), + readScriptSpec("/fulltext.csv-spec", parser)); + } + + + public CsvSpecIntegrationTest(String groupName, String testName, Integer lineNumber, Path source, CsvFragment fragment) { + super(groupName, testName, lineNumber, source); + this.fragment = fragment; + } + + @Test + public void testQuery() throws Throwable { + // hook CSV reader, which picks the current test context + try (Connection csv = csvCon(fragment.asProps(), fragment.reader).get(); + Connection es = esCon()) { + ResultSet expected, actual; + try { + // pass the testName as table for debugging purposes (in case the underlying reader is missing) + expected = csv.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY).executeQuery("SELECT * FROM " + testName); + // trigger data loading for type inference + expected.beforeFirst(); + actual = es.createStatement().executeQuery(fragment.query); + assertResultSets(expected, actual); + } catch (AssertionError ae) { + throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); + } + } catch (Throwable th) { + throw new RuntimeException(errorMessage(th), th); + } + } + + String errorMessage(Throwable th) { + return format(Locale.ROOT, "test%s@%s:%d failed\n\"%s\"\n%s", testName, source.getFileName().toString(), lineNumber, fragment.query, th.getMessage()); + } + + private static class CsvSpecParser implements Parser { + + private final StringBuilder data = new StringBuilder(); + private CsvFragment fragment; + + @Override + public Object parse(String line) { + // beginning of the section + if (fragment == null) { + // pick up the query + fragment = new CsvFragment(); + fragment.query = line.endsWith(";") ? line.substring(0, line.length() - 1) : line; + } + else { + // read CSV header + // if (fragment.columnNames == null) { + // fragment.columnNames = line; + // } + // read data + if (line.startsWith(";")) { + CsvFragment f = fragment; + f.reader = new StringReader(data.toString()); + // clean-up + fragment = null; + data.setLength(0); + return f; + } + else { + data.append(line); + data.append("\r\n"); + } + } + + return null; + } + } + + private static class CsvFragment { + String query; + String columnNames; + List columnTypes; + Reader reader; + + private static final Properties DEFAULT = new Properties(); + + static { + DEFAULT.setProperty("charset", "UTF-8"); + // trigger auto-detection + DEFAULT.setProperty("columnTypes", ""); + DEFAULT.setProperty("separator", "|"); + DEFAULT.setProperty("trimValues", "true"); + } + + Properties asProps() { + // p.setProperty("suppressHeaders", "true"); + // p.setProperty("headerline", columnNames); + return DEFAULT; + } + } +} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvInfraSuite.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvInfraSuite.java deleted file mode 100644 index e6715714cb8..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvInfraSuite.java +++ /dev/null @@ -1,49 +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.jdbc.integration.util.framework; - -import java.io.Reader; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Properties; -import java.util.function.Supplier; - -import org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcTemplate.JdbcSupplier; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.relique.jdbc.csv.CsvDriver; - -@RunWith(Suite.class) -public abstract class CsvInfraSuite extends EsInfra { - - private static CsvDriver DRIVER = new CsvDriver(); - public static final Map CSV_READERS = new LinkedHashMap<>(); - - @BeforeClass - public static void setupDB() throws Exception { - EsInfra.setupDB(); - } - - @AfterClass - public static void cleanup() throws Exception { - CSV_READERS.clear(); - } - - public static Supplier csvCon(Properties props, Reader reader) { - return new JdbcSupplier() { - @Override - public Connection jdbc() throws SQLException { - Connection con = DRIVER.connect("jdbc:relique:csv:class:" + CsvSpecTableReader.class.getName(), props); - CSV_READERS.put(con, reader); - return con; - } - }; - } -} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecBaseTest.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecBaseTest.java deleted file mode 100644 index f23f3a8a61b..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecBaseTest.java +++ /dev/null @@ -1,115 +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.jdbc.integration.util.framework; - -import java.io.Reader; -import java.io.StringReader; -import java.sql.Connection; -import java.sql.ResultSet; -import java.util.List; -import java.util.Locale; -import java.util.Properties; - -import org.junit.Test; -import org.junit.runners.Parameterized.Parameter; - -import static java.lang.String.format; - -import static org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcAssert.assertResultSets; - -public abstract class CsvSpecBaseTest extends SpecBaseTest { - - @Parameter(3) - public CsvFragment fragment; - - protected static List readScriptSpec(String url) throws Exception { - return SpecBaseTest.readScriptSpec(url, new CsvSpecParser()); - } - - @Test - public void testQuery() throws Throwable { - try (Connection csv = CsvInfraSuite.csvCon(fragment.asProps(), fragment.reader).get(); - Connection es = CsvInfraSuite.esCon().get()) { - ResultSet expected, actual; - try { - // pass the testName as table for debugging purposes (in case the underlying reader is missing) - expected = csv.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY).executeQuery("SELECT * FROM " + testName); - // trigger data loading for type inference - expected.beforeFirst(); - actual = es.createStatement().executeQuery(fragment.query); - assertResultSets(expected, actual); - } catch (AssertionError ae) { - throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); - } - } catch (Throwable th) { - throw new RuntimeException(errorMessage(th), th); - } - } - - String errorMessage(Throwable th) { - return format(Locale.ROOT, "test%s@%s:%d failed\n\"%s\"\n%s", testName, source.getFileName().toString(), lineNumber, fragment.query, th.getMessage()); - } -} - -class CsvSpecParser implements SpecBaseTest.Parser { - - private final StringBuilder data = new StringBuilder(); - private CsvFragment fragment; - - @Override - public Object parse(String line) { - // beginning of the section - if (fragment == null) { - // pick up the query - fragment = new CsvFragment(); - fragment.query = line.endsWith(";") ? line.substring(0, line.length() - 1) : line; - } - else { - // read CSV header - // if (fragment.columnNames == null) { - // fragment.columnNames = line; - // } - // read data - if (line.startsWith(";")) { - CsvFragment f = fragment; - f.reader = new StringReader(data.toString()); - // clean-up - fragment = null; - data.setLength(0); - return f; - } - else { - data.append(line); - data.append("\r\n"); - } - } - - return null; - } -} - -class CsvFragment { - String query; - String columnNames; - List columnTypes; - Reader reader; - - private static final Properties DEFAULT = new Properties(); - - static { - DEFAULT.setProperty("charset", "UTF-8"); - // trigger auto-detection - DEFAULT.setProperty("columnTypes", ""); - DEFAULT.setProperty("separator", "|"); - DEFAULT.setProperty("trimValues", "true"); - } - - Properties asProps() { - // p.setProperty("suppressHeaders", "true"); - // p.setProperty("headerline", columnNames); - return DEFAULT; - } -} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecTableReader.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecTableReader.java index 7e90d78159f..b8366d20859 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecTableReader.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/CsvSpecTableReader.java @@ -3,7 +3,10 @@ * 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.jdbc.integration.util.framework; +package org.elasticsearch.xpack.sql.jdbc.framework; + +import org.elasticsearch.xpack.sql.jdbc.csv.CsvSpecIntegrationTest; +import org.relique.io.TableReader; import java.io.Reader; import java.sql.Connection; @@ -11,13 +14,11 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; -import org.relique.io.TableReader; - public class CsvSpecTableReader implements TableReader { @Override public Reader getReader(Statement statement, String tableName) throws SQLException { - Reader reader = CsvInfraSuite.CSV_READERS.remove(statement.getConnection()); + Reader reader = CsvSpecIntegrationTest.CSV_READERS.remove(statement.getConnection()); if (reader == null) { throw new RuntimeException("Cannot find reader for test " + tableName); } diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsInfra.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsInfra.java deleted file mode 100644 index cd4f45013db..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsInfra.java +++ /dev/null @@ -1,50 +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.jdbc.integration.util.framework; - -import java.sql.Connection; -import java.util.function.Supplier; - -import org.elasticsearch.xpack.sql.jdbc.integration.util.EsDataLoader; -import org.elasticsearch.xpack.sql.jdbc.integration.util.EsJdbcServer; -import org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcTemplate; -import org.junit.ClassRule; - -import static org.junit.Assert.assertNotNull; - -public class EsInfra { - - // - // REMOTE ACCESS - // - private static boolean REMOTE = true; - - @ClassRule - public static EsJdbcServer ES_JDBC_SERVER = new EsJdbcServer(REMOTE, false); - - private static JdbcTemplate ES_JDBC; - - public static void setupDB() throws Exception { - //ES_CON = new JdbcTemplate(ES_JDBC_SERVER); - - if (!REMOTE) { - setupES(); - } - } - - private static void setupES() throws Exception { - EsDataLoader.loadData(); - } - - public static Supplier esCon() { - return ES_JDBC_SERVER; - } - - public static JdbcTemplate es() { - assertNotNull("ES connection null - make sure the suite is ran", ES_JDBC); - return ES_JDBC; - } -} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsJdbcServer.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsJdbcServer.java new file mode 100644 index 00000000000..db217eb8bf6 --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/EsJdbcServer.java @@ -0,0 +1,66 @@ +/* + * 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.jdbc.framework; + +import org.elasticsearch.client.Client; +import org.elasticsearch.common.CheckedSupplier; +import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver; +import org.junit.rules.ExternalResource; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Properties; + +import static org.junit.Assert.assertNotNull; + +public class EsJdbcServer extends ExternalResource implements CheckedSupplier { + + private JdbcHttpServer server; + private String jdbcUrl; + private JdbcDriver driver; + private final Properties properties; + + public EsJdbcServer() { + this(false); + } + + public EsJdbcServer(boolean debug) { + properties = new Properties(); + if (debug) { + properties.setProperty("debug", "true"); + } + } + + @Override + protected void before() throws Throwable { + server = new JdbcHttpServer(TestUtils.client()); + driver = new JdbcDriver(); + + server.start(0); + jdbcUrl = server.url(); + + System.out.println("Started JDBC Server at " + jdbcUrl); + } + + @Override + protected void after() { + server.stop(); + server = null; + + System.out.println("Stopped JDBC Server at " + jdbcUrl); + } + + public Client client() { + assertNotNull("ES JDBC Server is null - make sure ES is properly run as a @ClassRule", driver); + return server.client(); + } + + @Override + public Connection get() throws SQLException { + assertNotNull("ES JDBC Server is null - make sure ES is properly run as a @ClassRule", driver); + return driver.connect(jdbcUrl, properties); + } +} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcAssert.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcAssert.java index 571ead849f9..ad8a8b478cb 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcAssert.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcAssert.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.jdbc.compare; +package org.elasticsearch.xpack.sql.jdbc.framework; import java.sql.ResultSet; import java.sql.ResultSetMetaData; @@ -14,7 +14,6 @@ import java.time.Instant; import java.util.Locale; import java.util.TimeZone; -import static org.elasticsearch.xpack.sql.jdbc.compare.CompareToH2BaseTestCase.UTC_FORMATTER; import static org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcUtils.nameOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -85,8 +84,8 @@ public class JdbcAssert { * locale and time zone for date functions. */ msg += " locale is [" + Locale.getDefault() + "] and time zone is [" + TimeZone.getDefault() + "]"; - expectedObject = UTC_FORMATTER.format(Instant.ofEpochMilli(((Timestamp) expectedObject).getTime())); - actualObject = UTC_FORMATTER.format(Instant.ofEpochMilli(((Timestamp) actualObject).getTime())); + expectedObject = TestUtils.UTC_FORMATTER.format(Instant.ofEpochMilli(((Timestamp) expectedObject).getTime())); + actualObject = TestUtils.UTC_FORMATTER.format(Instant.ofEpochMilli(((Timestamp) actualObject).getTime())); // NOCOMMIT look at ResultSet.getTimestamp(int, Calendar) } diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcHttpServer.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcHttpServer.java new file mode 100644 index 00000000000..0a5c89f9dd0 --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcHttpServer.java @@ -0,0 +1,22 @@ +/* + * 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.jdbc.framework; + +import org.elasticsearch.client.Client; +import org.elasticsearch.xpack.sql.jdbc.net.protocol.Response; +import org.elasticsearch.xpack.sql.test.server.ProtoHttpServer; + +public class JdbcHttpServer extends ProtoHttpServer { + + public JdbcHttpServer(Client client) { + super(client, new SqlProtoHandler(client), "/jdbc/", "sql/"); + } + + @Override + public String url() { + return "jdbc:es://" + super.url(); + } +} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcIntegrationTestCase.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalEsCluster.java similarity index 58% rename from sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcIntegrationTestCase.java rename to sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalEsCluster.java index fbfdf6c2ebe..0f7f352a76a 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/JdbcIntegrationTestCase.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalEsCluster.java @@ -5,61 +5,53 @@ */ package org.elasticsearch.xpack.sql.jdbc.framework; -import org.apache.http.HttpEntity; -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; +import org.elasticsearch.client.RestClient; import org.elasticsearch.cluster.routing.allocation.DiskThresholdSettings; -import org.elasticsearch.common.CheckedConsumer; +import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.painless.PainlessPlugin; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.InternalTestCluster; import org.elasticsearch.test.NodeConfigurationSource; -import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.transport.Netty4Plugin; import org.elasticsearch.xpack.XPackPlugin; -import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver; +import org.elasticsearch.xpack.sql.jdbc.util.IOUtils; import org.elasticsearch.xpack.sql.net.client.SuppressForbidden; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; +import org.elasticsearch.xpack.sql.util.StringUtils; +import org.junit.rules.ExternalResource; -import java.io.IOException; import java.net.InetSocketAddress; import java.nio.file.Path; +import java.sql.Connection; import java.sql.DriverManager; +import java.sql.SQLException; import java.util.Arrays; import java.util.Collection; -import java.util.TimeZone; import java.util.function.Function; import static java.util.Collections.emptySet; -import static java.util.Collections.singletonMap; +import static org.apache.lucene.util.LuceneTestCase.createTempDir; +import static org.apache.lucene.util.LuceneTestCase.random; +import static org.elasticsearch.test.ESTestCase.randomBoolean; +import static org.elasticsearch.test.ESTestCase.randomLong; -public abstract class JdbcIntegrationTestCase extends ESRestTestCase { - static { - // Initialize the jdbc driver - JdbcDriver.jdbcMajorVersion(); - } - private static InternalTestCluster internalTestCluster; +/** + * Hack to run an {@link InternalTestCluster} if this is being run + * in an environment without {@code tests.rest.cluster} set for easier + * debugging. Note that this doesn't work in the security manager is + * enabled. + */ +public class LocalEsCluster extends ExternalResource implements CheckedSupplier { - /** - * Hack to run an {@link InternalTestCluster} if this is being run - * in an environment without {@code tests.rest.cluster} set for easier - * debugging. Note that this doesn't work in the security manager is - * enabled. - */ - @BeforeClass - @SuppressForbidden(reason="it is a hack anyway") - public static void startInternalTestClusterIfNeeded() throws IOException, InterruptedException { - if (System.getProperty("tests.rest.cluster") != null) { - // Nothing to do, using an external Elasticsearch node. - return; - } + private InternalTestCluster internalTestCluster; + private RestClient client; + private String serverAddress = StringUtils.EMPTY; + + @Override + @SuppressForbidden(reason = "it is a hack anyway") + protected void before() throws Throwable { long seed = randomLong(); String name = InternalTestCluster.clusterName("", seed); NodeConfigurationSource config = new NodeConfigurationSource() { @@ -92,8 +84,7 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase { return Arrays.asList(Netty4Plugin.class, XPackPlugin.class, PainlessPlugin.class); } }; - internalTestCluster = new InternalTestCluster(seed, createTempDir(), false, true, 1, 1, name, config, 0, randomBoolean(), "", - emptySet(), Function.identity()); + internalTestCluster = new InternalTestCluster(seed, createTempDir(), false, true, 1, 1, name, config, 0, randomBoolean(), "", emptySet(), Function.identity()); internalTestCluster.beforeTest(random(), 0); internalTestCluster.ensureAtLeastNumDataNodes(1); InetSocketAddress httpBound = internalTestCluster.httpAddresses()[0]; @@ -101,32 +92,36 @@ public abstract class JdbcIntegrationTestCase extends ESRestTestCase { try { System.setProperty("tests.rest.cluster", http); } catch (SecurityException e) { - throw new RuntimeException( - "Failed to set system property required for tests. Security manager must be disabled to use this hack.", e); + throw new RuntimeException("Failed to set system property required for tests. Security manager must be disabled to use this hack.", e); } + + client = TestUtils.restClient(httpBound.getAddress()); + // load data + TestUtils.loadDatasetInEs(client); + + serverAddress = httpBound.getAddress().getHostAddress(); } - @AfterClass - public static void shutDownInternalTestClusterIfNeeded() { + @Override + protected void after() { + serverAddress = StringUtils.EMPTY; if (internalTestCluster == null) { return; } - internalTestCluster.close(); + IOUtils.close(client); + IOUtils.close(internalTestCluster); } - protected JdbcTemplate j; - - @Before - public void setupJdbcTemplate() throws Exception { - j = new JdbcTemplate(() -> DriverManager.getConnection( - "jdbc:es://" + System.getProperty("tests.rest.cluster") + "/?time_zone=" + TimeZone.getDefault().getID())); + public RestClient client() { + return client; } - protected void index(String index, CheckedConsumer body) throws IOException { - XContentBuilder builder = JsonXContent.contentBuilder().startObject(); - body.accept(builder); - builder.endObject(); - HttpEntity doc = new StringEntity(builder.string(), ContentType.APPLICATION_JSON); - client().performRequest("PUT", "/" + index + "/doc/1", singletonMap("refresh", "true"), doc); + public String address() { + return serverAddress; } -} + + @Override + public Connection get() throws SQLException { + return DriverManager.getConnection("jdbc:es://" + serverAddress); + } +} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalH2.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalH2.java new file mode 100644 index 00000000000..a59b0ce0004 --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/LocalH2.java @@ -0,0 +1,59 @@ +/* + * 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.jdbc.framework; + +import org.elasticsearch.common.CheckedSupplier; +import org.h2.Driver; +import org.junit.rules.ExternalResource; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Properties; + +public class LocalH2 extends ExternalResource implements CheckedSupplier { + + private final Driver driver = Driver.load(); + // add any defaults in here + private final Properties DEFAULTS = new Properties(); + private final String url; + // H2 in-memory will keep the db alive as long as the connection is opened + private Connection keepAlive; + + /* + * The syntax on the connection string is fairly particular: + * mem:; creates an anonymous database in memory. The `;` is + * technically the separator that comes after the name. + * DATABASE_TO_UPPER=false turns *off* H2's Oracle-like habit + * of upper-casing everything that isn't quoted. + * ALIAS_COLUMN_NAME=true turn *on* returning alias names in + * result set metadata which is what most DBs do except + * for MySQL and, by default, H2. Our jdbc driver does it. + */ + public LocalH2() { + this.url = "jdbc:H2:mem:essql;DATABASE_TO_UPPER=false;ALIAS_COLUMN_NAME=true"; + } + + @Override + protected void before() throws Throwable { + keepAlive = get(); + //NOCOMMIT: check timezone issue + keepAlive.createStatement().executeQuery("RUNSCRIPT FROM 'classpath:h2-setup.sql'"); + } + + @Override + protected void after() { + try { + keepAlive.close(); + } catch (SQLException ex) { + // close + } + } + + @Override + public Connection get() throws SQLException { + return driver.connect(url, DEFAULTS); + } +} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseTest.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseIntegrationTestCase.java similarity index 56% rename from sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseTest.java rename to sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseIntegrationTestCase.java index ed409d50ec4..5e5a30b182a 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseTest.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SpecBaseIntegrationTestCase.java @@ -3,81 +3,106 @@ * 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.jdbc.integration.util.framework; +package org.elasticsearch.xpack.sql.jdbc.framework; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.sql.jdbc.jdbc.JdbcDriver; +import org.junit.Assert; +import org.junit.ClassRule; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.sql.Connection; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; -import org.elasticsearch.common.Strings; -import org.junit.Assert; -import org.junit.runners.Parameterized.Parameter; - import static java.lang.String.format; -public abstract class SpecBaseTest { - - @Parameter(0) - public String testName; - @Parameter(1) - public Integer lineNumber; - @Parameter(2) - public Path source; - - interface Parser { - Object parse(String line); +public abstract class SpecBaseIntegrationTestCase extends ESTestCase { + static { + // Initialize the jdbc driver + JdbcDriver.jdbcMajorVersion(); } + protected final String groupName; + protected final String testName; + protected final Integer lineNumber; + protected final Path source; + + @ClassRule + public static EsJdbcServer ES = new EsJdbcServer(); + + public SpecBaseIntegrationTestCase(String groupName, String testName, Integer lineNumber, Path source) { + this.groupName = groupName; + this.testName = testName; + this.lineNumber = lineNumber; + this.source = source; + } + + public Connection esCon() throws Exception { + return ES.get(); + } + + protected Throwable reworkException(Throwable th) { + StackTraceElement[] stackTrace = th.getStackTrace(); + StackTraceElement[] redone = new StackTraceElement[stackTrace.length + 1]; + System.arraycopy(stackTrace, 0, redone, 1, stackTrace.length); + redone[0] = new StackTraceElement(getClass().getName(), groupName + "." + testName, source.getFileName().toString(), lineNumber); + + th.setStackTrace(redone); + return th; + } + + // + // spec reader + // + // returns testName, its line location, its source and the custom object (based on each test parser) protected static List readScriptSpec(String url, Parser parser) throws Exception { - Path source = Paths.get(SpecBaseTest.class.getResource(url).toURI()); + Path source = Paths.get(TestUtils.class.getResource(url).toURI()); + String groupName = source.getFileName().toString(); + List lines = Files.readAllLines(source); Map testNames = new LinkedHashMap<>(); List pairs = new ArrayList<>(); - String name = null; + String testName = null; for (int i = 0; i < lines.size(); i++) { String line = lines.get(i).trim(); // ignore comments if (!line.isEmpty() && !line.startsWith("//")) { // parse test name - if (name == null) { + if (testName == null) { if (testNames.keySet().contains(line)) { throw new IllegalStateException(format(Locale.ROOT, "Duplicate test name '%s' at line %d (previously seen at line %d)", line, i, testNames.get(line))); } else { - name = Strings.capitalize(line); - testNames.put(name, Integer.valueOf(i)); + testName = Strings.capitalize(line); + testNames.put(testName, Integer.valueOf(i)); } } else { Object result = parser.parse(line); // only if the parser is ready, add the object - otherwise keep on serving it lines if (result != null) { - pairs.add(new Object[] { name, Integer.valueOf(i), source, result }); - name = null; + pairs.add(new Object[] { groupName, testName, Integer.valueOf(i), source, result }); + testName = null; } } } } - Assert.assertNull("Cannot find spec for test " + name, name); + Assert.assertNull("Cannot find spec for test " + testName, testName); return pairs; } - Throwable reworkException(Throwable th) { - StackTraceElement[] stackTrace = th.getStackTrace(); - StackTraceElement[] redone = new StackTraceElement[stackTrace.length + 1]; - System.arraycopy(stackTrace, 0, redone, 1, stackTrace.length); - redone[0] = new StackTraceElement(getClass().getName(), testName, source.getFileName().toString(), lineNumber); - - th.setStackTrace(redone); - return th; + public interface Parser { + Object parse(String line); } -} +} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlInfraSuite.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlInfraSuite.java deleted file mode 100644 index 318092013a9..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlInfraSuite.java +++ /dev/null @@ -1,49 +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.jdbc.integration.util.framework; - -import java.sql.Connection; -import java.util.function.Supplier; - -import org.elasticsearch.xpack.sql.jdbc.integration.util.H2; -import org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcTemplate; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -import static org.junit.Assert.assertNotNull; - -@RunWith(Suite.class) -public abstract class SqlInfraSuite extends EsInfra { - - private static String REMOTE_H2 = "jdbc:org.elasticsearch.xpack.sql.jdbc.h2:tcp://localhost/./essql"; - - @ClassRule - public static H2 H2 = new H2(null); - - private static JdbcTemplate H2_JDBC; - - @BeforeClass - public static void setupDB() throws Exception { - H2_JDBC = new JdbcTemplate(H2); - setupH2(); - EsInfra.setupDB(); - } - - private static void setupH2() throws Exception { - h2().execute("RUNSCRIPT FROM 'classpath:org/elasticsearch/sql/jdbc/integration/org.elasticsearch.xpack.sql.jdbc.h2-setup.sql'"); - } - - public static Supplier h2Con() { - return H2; - } - - public static JdbcTemplate h2() { - assertNotNull("H2 connection null - make sure the suite is ran", H2_JDBC); - return H2_JDBC; - } -} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlProtoHandler.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlProtoHandler.java new file mode 100644 index 00000000000..95dd6ed7b4e --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlProtoHandler.java @@ -0,0 +1,38 @@ +/* + * 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.jdbc.framework; + +import com.sun.net.httpserver.HttpExchange; + +import org.elasticsearch.client.Client; +import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.jdbc.net.protocol.ProtoUtils; +import org.elasticsearch.xpack.sql.jdbc.net.protocol.Request; +import org.elasticsearch.xpack.sql.jdbc.net.protocol.Response; +import org.elasticsearch.xpack.sql.plugin.jdbc.server.JdbcServer; +import org.elasticsearch.xpack.sql.plugin.jdbc.server.JdbcServerProtoUtils; +import org.elasticsearch.xpack.sql.test.server.ProtoHandler; + +import java.io.DataInput; +import java.io.IOException; + +import static org.elasticsearch.action.ActionListener.wrap; + +class SqlProtoHandler extends ProtoHandler { + + private final JdbcServer server; + + SqlProtoHandler(Client client) { + super(client, ProtoUtils::readHeader, JdbcServerProtoUtils::write); + this.server = new JdbcServer(TestUtils.planExecutor(client), clusterName, () -> info.getNode().getName(), info.getVersion(), info.getBuild()); + } + + @Override + protected void handle(HttpExchange http, DataInput in) throws IOException { + Request req = ProtoUtils.readRequest(in); + server.handle(req, wrap(resp -> sendHttpResponse(http, resp), ex -> fail(http, ex))); + } +} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlSpecBaseTest.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlSpecBaseTest.java deleted file mode 100644 index 83c0be66bb9..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/SqlSpecBaseTest.java +++ /dev/null @@ -1,58 +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.jdbc.integration.util.framework; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.util.List; -import java.util.Locale; - -import org.junit.Test; -import org.junit.runners.Parameterized.Parameter; - -import static java.lang.String.format; - -import static org.elasticsearch.xpack.sql.jdbc.integration.util.JdbcAssert.assertResultSets; - -public abstract class SqlSpecBaseTest extends SpecBaseTest { - - @Parameter(3) - public String query; - - protected static List readScriptSpec(String url) throws Exception { - return SpecBaseTest.readScriptSpec(url, new SqlSpecParser()); - } - - @Test - public void testQuery() throws Throwable { - // H2 resultset - try (Connection h2 = SqlInfraSuite.h2Con().get(); - Connection es = SqlInfraSuite.esCon().get()) { - ResultSet expected, actual; - try { - expected = h2.createStatement().executeQuery(query); - actual = es.createStatement().executeQuery(query); - assertResultSets(expected, actual); - } catch (AssertionError ae) { - throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); - } - } catch (Throwable th) { - throw reworkException(new RuntimeException(errorMessage(th))); - } - } - - String errorMessage(Throwable th) { - return format(Locale.ROOT, "test%s@%s:%d failed\n\"%s\"\n%s", testName, source.getFileName().toString(), lineNumber, query, th.getMessage()); - } -} - -class SqlSpecParser implements SpecBaseTest.Parser { - - @Override - public Object parse(String line) { - return line.endsWith(";") ? line.substring(0, line.length() - 1) : line; - } -} \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/CompareToH2BaseTestCase.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/TestUtils.java similarity index 52% rename from sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/CompareToH2BaseTestCase.java rename to sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/TestUtils.java index f4c4e5e3969..3b7e3abc588 100644 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/CompareToH2BaseTestCase.java +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/TestUtils.java @@ -3,127 +3,73 @@ * 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.jdbc.compare; +package org.elasticsearch.xpack.sql.jdbc.framework; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; +import org.elasticsearch.client.Client; +import org.elasticsearch.client.RestClient; import org.elasticsearch.common.CheckedBiConsumer; +import org.elasticsearch.common.CheckedConsumer; import org.elasticsearch.common.io.PathUtils; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.json.JsonXContent; -import org.elasticsearch.xpack.sql.jdbc.JdbcIntegrationTestCase; +import org.elasticsearch.transport.client.PreBuiltTransportClient; +import org.elasticsearch.xpack.sql.jdbc.h2.SqlSpecIntegrationTest; +import java.io.IOException; +import java.net.InetAddress; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; -import java.sql.DriverManager; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.Timestamp; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; -import static org.elasticsearch.xpack.sql.jdbc.compare.JdbcAssert.assertResultSets; +import static org.junit.Assert.assertEquals; + +public abstract class TestUtils { -/** - * Compares Elasticsearch's JDBC driver to H2. - */ -public abstract class CompareToH2BaseTestCase extends JdbcIntegrationTestCase { static final DateTimeFormatter UTC_FORMATTER = DateTimeFormatter.ISO_DATE_TIME .withLocale(Locale.ROOT) .withZone(ZoneId.of("UTC")); + + public static RestClient restClient(String host, int port) { + return RestClient.builder(new HttpHost(host, port)).build(); - public final String queryName; - public final String query; - public final Integer lineNumber; - public final Path source; - - protected static List readScriptSpec(String spec) throws Exception { - String url = "/" + spec + ".spec"; - URL resource = CompareToH2BaseTestCase.class.getResource(url); - if (resource == null) { - throw new IllegalArgumentException("Couldn't find [" + url + "]"); - } - Path source = PathUtils.get(resource.toURI()); - List lines = Files.readAllLines(source); - - Map testNames = new LinkedHashMap<>(); - List ctorArgs = new ArrayList<>(); - - String name = null; - StringBuilder query = new StringBuilder(); - for (int i = 0; i < lines.size(); i++) { - String line = lines.get(i).trim(); - // ignore comments - if (!line.isEmpty() && !line.startsWith("//")) { - if (name == null) { - if (testNames.keySet().contains(line)) { - throw new IllegalStateException("Duplicate test name [" + line - + "] at line [" + i + "] (previously seen at line [" + testNames.get(line) + "])"); - } else { - name = line; - testNames.put(name, Integer.valueOf(i)); - } - } else { - if (line.endsWith(";")) { - query.append(line.substring(0, line.length() - 1)); - } - ctorArgs.add(new Object[] { name, query.toString(), Integer.valueOf(i), source }); - name = null; - query.setLength(0); - } - } - } - assertNull("Cannot find query for test " + name, name); - - return ctorArgs; } - public CompareToH2BaseTestCase(String queryName, String query, Integer lineNumber, Path source) { - this.queryName = queryName; - this.query = query; - this.lineNumber = lineNumber; - this.source = source; + public static RestClient restClient(InetAddress address) { + return RestClient.builder(new HttpHost(address)).build(); + } - public void testQuery() throws Throwable { - /* - * The syntax on the connection string is fairly particular: - * mem:; creates an anonymous database in memory. The `;` is - * technically the separator that comes after the name. - * DATABASE_TO_UPPER=false turns *off* H2's Oracle-like habit - * of upper-casing everything that isn't quoted. - * ALIAS_COLUMN_NAME=true turn *on* returning alias names in - * result set metadata which is what most DBs do except - * for MySQL and, by default, H2. Our jdbc driver does it. - * RUNSCRIPT FROM 'classpath:/h2-setup.sql' initializes the - * database with test data. - */ - try (Connection h2 = DriverManager.getConnection( - "jdbc:h2:mem:;DATABASE_TO_UPPER=false;ALIAS_COLUMN_NAME=true;INIT=RUNSCRIPT FROM 'classpath:/h2-setup.sql'")) { - fillH2(h2); - try (PreparedStatement h2Query = h2.prepareStatement(query); - ResultSet expected = h2Query.executeQuery()) { - setupElasticsearchIndex(); - j.query(query, actual -> { - assertResultSets(expected, actual); - return null; - }); - }; - } + public static Client client() { + return new PreBuiltTransportClient(Settings.EMPTY) + .addTransportAddress(new TransportAddress(InetAddress.getLoopbackAddress(), 9300)); } - private void setupElasticsearchIndex() throws Exception { + public static void index(RestClient client, String index, CheckedConsumer body) throws IOException { + XContentBuilder builder = JsonXContent.contentBuilder().startObject(); + body.accept(builder); + builder.endObject(); + HttpEntity doc = new StringEntity(builder.string(), ContentType.APPLICATION_JSON); + client.performRequest("PUT", "/" + index + "/doc/1", singletonMap("refresh", "true"), doc); + } + + public static void loadDatasetInEs(RestClient client) throws Exception { XContentBuilder createIndex = JsonXContent.contentBuilder().startObject(); createIndex.startObject("settings"); { createIndex.field("number_of_shards", 1); @@ -144,7 +90,7 @@ public abstract class CompareToH2BaseTestCase extends JdbcIntegrationTestCase { createIndex.endObject(); } createIndex.endObject().endObject(); - client().performRequest("PUT", "/emp", emptyMap(), new StringEntity(createIndex.string(), ContentType.APPLICATION_JSON)); + client.performRequest("PUT", "/emp", emptyMap(), new StringEntity(createIndex.string(), ContentType.APPLICATION_JSON)); StringBuilder bulk = new StringBuilder(); csvToLines("employees", (titles, fields) -> { @@ -158,18 +104,17 @@ public abstract class CompareToH2BaseTestCase extends JdbcIntegrationTestCase { } bulk.append("}\n"); }); - client().performRequest("POST", "/emp/emp/_bulk", singletonMap("refresh", "true"), - new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON)); + client.performRequest("POST", "/emp/emp/_bulk", singletonMap("refresh", "true"), new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON)); } - + /** - * Fill the h2 database. Note that we have to parse the CSV ourselves - * because h2 interprets the CSV using the default locale which is + * Fill the H2 database. Note that we have to parse the CSV ourselves + * because H2 interprets the CSV using the default locale which is * randomized by the testing framework. Because some locales (th-TH, * for example) parse dates in very different ways we parse using the * root locale. */ - private void fillH2(Connection h2) throws Exception { + public static void loadDatesetInH2(Connection h2) throws Exception { csvToLines("employees", (titles, fields) -> { StringBuilder insert = new StringBuilder("INSERT INTO \"emp.emp\" ("); for (int t = 0; t < titles.size(); t++) { @@ -206,10 +151,9 @@ public abstract class CompareToH2BaseTestCase extends JdbcIntegrationTestCase { }); } - private void csvToLines(String name, - CheckedBiConsumer, List, Exception> consumeLine) throws Exception { + private static void csvToLines(String name, CheckedBiConsumer, List, Exception> consumeLine) throws Exception { String location = "/" + name + ".csv"; - URL dataSet = CompareToH2BaseTestCase.class.getResource(location); + URL dataSet = SqlSpecIntegrationTest.class.getResource(location); if (dataSet == null) { throw new IllegalArgumentException("Can't find [" + location + "]"); } @@ -222,4 +166,18 @@ public abstract class CompareToH2BaseTestCase extends JdbcIntegrationTestCase { consumeLine.accept(titles, Arrays.asList(lines.get(l).split(","))); } } + + + + + Throwable reworkException(Throwable th, Class testSuite, String testName, Path source, int lineNumber) { + StackTraceElement[] stackTrace = th.getStackTrace(); + StackTraceElement[] redone = new StackTraceElement[stackTrace.length + 1]; + System.arraycopy(stackTrace, 0, redone, 1, stackTrace.length); + redone[0] = new StackTraceElement(testSuite.getName(), testName, source.getFileName().toString(), lineNumber); + + th.setStackTrace(redone); + return th; + } + } \ No newline at end of file diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/AggIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/AggIT.java deleted file mode 100644 index 2522604e8e0..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/AggIT.java +++ /dev/null @@ -1,24 +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.jdbc.h2; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import java.nio.file.Path; - -/** - * Tests for aggregations created by {@code GROUP BY}. - */ -public class AggIT extends CompareToH2BaseTestCase { - public AggIT(String queryName, String query, Integer lineNumber, Path source) { - super(queryName, query, lineNumber, source); - } - - @ParametersFactory - public static Iterable queries() throws Exception { - return readScriptSpec("agg"); - } -} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/DateTimeIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/DateTimeIT.java deleted file mode 100644 index 59f55c65e01..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/DateTimeIT.java +++ /dev/null @@ -1,24 +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.jdbc.h2; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import java.nio.file.Path; - -/** - * Tests for functions related to dates and times. - */ -public class DateTimeIT extends CompareToH2BaseTestCase { - public DateTimeIT(String queryName, String query, Integer lineNumber, Path source) { - super(queryName, query, lineNumber, source); - } - - @ParametersFactory - public static Iterable queries() throws Exception { - return readScriptSpec("datetime"); - } -} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/FilterIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/FilterIT.java deleted file mode 100644 index dfd0858477c..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/FilterIT.java +++ /dev/null @@ -1,24 +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.jdbc.h2; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import java.nio.file.Path; - -/** - * Tests for filters added by {@code WHERE} clauses. - */ -public class FilterIT extends CompareToH2BaseTestCase { - public FilterIT(String queryName, String query, Integer lineNumber, Path source) { - super(queryName, query, lineNumber, source); - } - - @ParametersFactory - public static Iterable queries() throws Exception { - return readScriptSpec("filter"); - } -} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/MathIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/MathIT.java deleted file mode 100644 index 31de2121b91..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/MathIT.java +++ /dev/null @@ -1,21 +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.jdbc.h2; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import java.nio.file.Path; - -public class MathIT extends CompareToH2BaseTestCase { - public MathIT(String queryName, String query, Integer lineNumber, Path source) { - super(queryName, query, lineNumber, source); - } - - @ParametersFactory - public static Iterable queries() throws Exception { - return readScriptSpec("math"); - } -} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SelectIT.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SelectIT.java deleted file mode 100644 index 82e042faf91..00000000000 --- a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SelectIT.java +++ /dev/null @@ -1,24 +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.jdbc.h2; - -import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; - -import java.nio.file.Path; - -/** - * Tests for basic {@code SELECT} statements without {@code WHERE} or {@code GROUP BY} or functions. - */ -public class SelectIT extends CompareToH2BaseTestCase { - public SelectIT(String queryName, String query, Integer lineNumber, Path source) { - super(queryName, query, lineNumber, source); - } - - @ParametersFactory - public static Iterable queries() throws Exception { - return readScriptSpec("select"); - } -} diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SqlSpecIntegrationTest.java b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SqlSpecIntegrationTest.java new file mode 100644 index 00000000000..0f64f200ae4 --- /dev/null +++ b/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/h2/SqlSpecIntegrationTest.java @@ -0,0 +1,83 @@ +/* + * 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.jdbc.h2; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.xpack.sql.jdbc.framework.LocalH2; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase; +import org.elasticsearch.xpack.sql.jdbc.framework.SpecBaseIntegrationTestCase.Parser; +import org.elasticsearch.xpack.sql.util.CollectionUtils; +import org.junit.ClassRule; +import org.junit.Test; + +import java.nio.file.Path; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Locale; + +import static java.lang.String.format; +import static org.elasticsearch.xpack.sql.jdbc.framework.JdbcAssert.assertResultSets; + +public class SqlSpecIntegrationTest extends SpecBaseIntegrationTestCase { + + private String query; + + @ClassRule + public static LocalH2 H2 = new LocalH2(); + + @ParametersFactory(shuffle = false, argumentFormatting = "name=%1s") + public static List readScriptSpec() throws Exception { + SqlSpecParser parser = new SqlSpecParser(); + return CollectionUtils.combine( + readScriptSpec("/select.sql-spec", parser), + readScriptSpec("/filter.sql-spec", parser), + readScriptSpec("/datetime.sql-spec", parser), + readScriptSpec("/math.sql-spec", parser), + readScriptSpec("/agg.sql-spec", parser)); + } + + private static class SqlSpecParser implements Parser { + @Override + public Object parse(String line) { + return line.endsWith(";") ? line.substring(0, line.length() - 1) : line; + } + } + + public Connection h2Con() throws SQLException { + return H2.get(); + } + + public SqlSpecIntegrationTest(String groupName, @Name("testName") String testName, Integer lineNumber, Path source, String query) { + super(groupName, testName, lineNumber, source); + this.query = query; + } + + @Test + public void testQuery() throws Throwable { + // H2 resultset + try (Connection h2 = h2Con(); + Connection es = esCon()) { + ResultSet expected, actual; + try { + expected = h2.createStatement().executeQuery(query); + actual = es.createStatement().executeQuery(query); + assertResultSets(expected, actual); + } catch (AssertionError ae) { + throw reworkException(new AssertionError(errorMessage(ae), ae.getCause())); + } + } catch (Throwable th) { + throw reworkException(new RuntimeException(errorMessage(th))); + } + } + + String errorMessage(Throwable th) { + return format(Locale.ROOT, "test%s@%s:%d failed\n\"%s\"\n%s", testName, source.getFileName().toString(), lineNumber, query, th.getMessage()); + } +} \ No newline at end of file diff --git a/sql/jdbc/src/test/resources/agg.spec b/sql/jdbc/src/test/resources/agg.sql-spec similarity index 100% rename from sql/jdbc/src/test/resources/agg.spec rename to sql/jdbc/src/test/resources/agg.sql-spec diff --git a/sql/jdbc/src/test/resources/command.csv-spec b/sql/jdbc/src/test/resources/command.csv-spec new file mode 100644 index 00000000000..7b183af898c --- /dev/null +++ b/sql/jdbc/src/test/resources/command.csv-spec @@ -0,0 +1,107 @@ +// +// Commands +// + +// SHOW_FUNCTIONS +showFunctions +SHOW FUNCTIONS; + + name | type +AVG |AGGREGATE +COUNT |AGGREGATE +MAX |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE +DAY_OF_MONTH |SCALAR +DAY |SCALAR +DOM |SCALAR +DAY_OF_WEEK |SCALAR +DOW |SCALAR +DAY_OF_YEAR |SCALAR +DOY |SCALAR +HOUR_OF_DAY |SCALAR +HOUR |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MINUTE |SCALAR +SECOND_OF_MINUTE|SCALAR +SECOND |SCALAR +MONTH_OF_YEAR |SCALAR +MONTH |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +CBRT |SCALAR +CEIL |SCALAR +COS |SCALAR +COSH |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +PI |SCALAR +RADIANS |SCALAR +ROUND |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR +; + +showFunctionsWithExactMatch +SHOW FUNCTIONS LIKE 'ABS'; + + name | type +ABS |SCALAR +; + + +showFunctionsWithPatternWildcard +SHOW FUNCTIONS LIKE 'A%'; + + name | type +AVG |AGGREGATE +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +; + +showFunctionsWithPatternChar +SHOW FUNCTIONS LIKE 'A__'; + + name | type +AVG |AGGREGATE +ABS |SCALAR +; + +showFunctions +SHOW FUNCTIONS '%DAY%'; + + name | type +DAY_OF_MONTH |SCALAR +DAY |SCALAR +DAY_OF_WEEK |SCALAR +DAY_OF_YEAR |SCALAR +HOUR_OF_DAY |SCALAR +MINUTE_OF_DAY |SCALAR +; + +// DESCRIBE + +describe +DESCRIBE "test_emp.emp"; + + column | type +birth_date |TIMESTAMP_WITH_TIMEZONE +emp_no |INTEGER +first_name |VARCHAR +gender |VARCHAR +hire_date |TIMESTAMP_WITH_TIMEZONE +last_name |VARCHAR +; \ No newline at end of file diff --git a/sql/jdbc/src/test/resources/datetime.spec b/sql/jdbc/src/test/resources/datetime.sql-spec similarity index 100% rename from sql/jdbc/src/test/resources/datetime.spec rename to sql/jdbc/src/test/resources/datetime.sql-spec diff --git a/sql/jdbc/src/test/resources/debug.csv-spec b/sql/jdbc/src/test/resources/debug.csv-spec new file mode 100644 index 00000000000..fa25ee25ded --- /dev/null +++ b/sql/jdbc/src/test/resources/debug.csv-spec @@ -0,0 +1,53 @@ +// +// Spec used for debugging a certain test (without having to alter the spec suite of which it might be part of) +// + +debug +SHOW FUNCTIONS; + + name | type +AVG |AGGREGATE +COUNT |AGGREGATE +MAX |AGGREGATE +MIN |AGGREGATE +SUM |AGGREGATE +DAY_OF_MONTH |SCALAR +DAY |SCALAR +DOM |SCALAR +DAY_OF_WEEK |SCALAR +DOW |SCALAR +DAY_OF_YEAR |SCALAR +DOY |SCALAR +HOUR_OF_DAY |SCALAR +HOUR |SCALAR +MINUTE_OF_DAY |SCALAR +MINUTE_OF_HOUR |SCALAR +MINUTE |SCALAR +SECOND_OF_MINUTE|SCALAR +SECOND |SCALAR +MONTH_OF_YEAR |SCALAR +MONTH |SCALAR +YEAR |SCALAR +ABS |SCALAR +ACOS |SCALAR +ASIN |SCALAR +ATAN |SCALAR +CBRT |SCALAR +CEIL |SCALAR +COS |SCALAR +COSH |SCALAR +DEGREES |SCALAR +E |SCALAR +EXP |SCALAR +EXPM1 |SCALAR +FLOOR |SCALAR +LOG |SCALAR +LOG10 |SCALAR +PI |SCALAR +RADIANS |SCALAR +ROUND |SCALAR +SIN |SCALAR +SINH |SCALAR +SQRT |SCALAR +TAN |SCALAR +; \ No newline at end of file diff --git a/sql/jdbc/src/test/resources/debug.sql-spec b/sql/jdbc/src/test/resources/debug.sql-spec new file mode 100644 index 00000000000..8328feb7ae4 --- /dev/null +++ b/sql/jdbc/src/test/resources/debug.sql-spec @@ -0,0 +1,6 @@ +// +// Spec used for debugging a certain test (without having to alter the spec suite of which it might be part of) +// + +debug +SELECT YEAR(birth_date) AS d, CAST(SUM(emp_no) AS INT) s FROM "test_emp.emp" GROUP BY YEAR(birth_date) ORDER BY YEAR(birth_date) LIMIT 5; diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/example.csv-spec b/sql/jdbc/src/test/resources/example.csv-spec similarity index 100% rename from sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/example.csv-spec rename to sql/jdbc/src/test/resources/example.csv-spec diff --git a/sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/example.sql-spec b/sql/jdbc/src/test/resources/example.sql-spec similarity index 100% rename from sql/jdbc/src/test/java/org/elasticsearch/xpack/sql/jdbc/framework/example.sql-spec rename to sql/jdbc/src/test/resources/example.sql-spec diff --git a/sql/jdbc/src/test/resources/filter.spec b/sql/jdbc/src/test/resources/filter.sql-spec similarity index 100% rename from sql/jdbc/src/test/resources/filter.spec rename to sql/jdbc/src/test/resources/filter.sql-spec diff --git a/sql/jdbc/src/test/resources/fulltext.csv-spec b/sql/jdbc/src/test/resources/fulltext.csv-spec new file mode 100644 index 00000000000..9a482b49b7a --- /dev/null +++ b/sql/jdbc/src/test/resources/fulltext.csv-spec @@ -0,0 +1,31 @@ +// +// Full-text +// + +simpleQueryAllFields +SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE QUERY('Baek fox') LIMIT 3; + + emp_no | first_name | gender | last_name +10080 |Premal |M |Baek +; + +simpleQueryDedicatedField +SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE QUERY('Man*', 'fields=last_name') LIMIT 5; + + emp_no | first_name | gender | last_name +10096 |Jayson |M |Mandell +; + +matchQuery +SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE MATCH(first_name, 'Erez'); + + emp_no | first_name | gender | last_name +10076 |Erez |F |Ritzmann +; + +multiMatchQuery +SELECT emp_no, first_name, gender, last_name FROM test_emp.emp WHERE MATCH('first_name,last_name', 'Morton', 'type=best_fields;default_operator=OR'); + + emp_no | first_name | gender | last_name +10095 |Hilari |M |Morton +; diff --git a/sql/jdbc/src/test/resources/h2-setup.sql b/sql/jdbc/src/test/resources/h2-setup.sql index 59b9fbd4306..443cb1b963b 100644 --- a/sql/jdbc/src/test/resources/h2-setup.sql +++ b/sql/jdbc/src/test/resources/h2-setup.sql @@ -1,7 +1,9 @@ -CREATE TABLE "emp.emp" ("birth_date" TIMESTAMP, - "emp_no" INT, - "first_name" VARCHAR(50), - "gender" VARCHAR(1), +DROP TABLE IF EXISTS "test_emp.emp"; +CREATE TABLE "test_emp.emp" ("birth_date" TIMESTAMP, + "emp_no" INT, + "first_name" VARCHAR(50), + "gender" VARCHAR(1), "hire_date" TIMESTAMP, - "last_name" VARCHAR(50) - ); + "last_name" VARCHAR(50) + ) + AS SELECT * FROM CSVREAD('classpath:/employees.csv'); \ No newline at end of file diff --git a/sql/jdbc/src/test/resources/math.spec b/sql/jdbc/src/test/resources/math.sql-spec similarity index 100% rename from sql/jdbc/src/test/resources/math.spec rename to sql/jdbc/src/test/resources/math.sql-spec diff --git a/sql/jdbc/src/test/resources/select.spec b/sql/jdbc/src/test/resources/select.sql-spec similarity index 100% rename from sql/jdbc/src/test/resources/select.spec rename to sql/jdbc/src/test/resources/select.sql-spec