You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2018/06/26 05:41:45 UTC
[3/3] calcite git commit: Fix-up for [CALCITE-2345] and [CALCITE-2347]
Fix-up for [CALCITE-2345] and [CALCITE-2347]
Terminology: Standardize on Elasticsearch, not Elastic or ElasticSearch.
Rename MongoDatabaseRule to MongoDatabasePolicy to avoid confusion
with planner rule classes; similarly ElasticsearchPolicy.
Use project standard indentation.
Ensure that files end in newlines.
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/6e8bb5a1
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/6e8bb5a1
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/6e8bb5a1
Branch: refs/heads/master
Commit: 6e8bb5a16c9c8c0397b79f3e98c0134ab9a32fb3
Parents: 4f83546
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Jun 14 22:06:27 2018 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jun 25 21:27:04 2018 -0700
----------------------------------------------------------------------
.../java/org/apache/calcite/util/UtilTest.java | 1 +
.../org/apache/calcite/test/DruidAdapterIT.java | 4 +-
.../apache/calcite/test/DruidAdapterIT2.java | 4 +-
.../Elasticsearch2Enumerator.java | 2 +-
.../ElasticSearch2AdapterTest.java | 397 ---------
.../Elasticsearch2AdapterTest.java | 398 +++++++++
.../elasticsearch2/EmbeddedElasticNode.java | 154 ----
.../elasticsearch2/EmbeddedElasticRule.java | 108 ---
.../EmbeddedElasticsearchNode.java | 154 ++++
.../EmbeddedElasticsearchPolicy.java | 102 +++
.../org/apache/calcite/test/ElasticChecker.java | 53 --
.../calcite/test/ElasticsearchChecker.java | 53 ++
.../src/test/resources/zips-mini.json | 2 +-
.../ElasticSearch5AdapterTest.java | 401 ---------
.../Elasticsearch5AdapterTest.java | 405 +++++++++
.../EmbeddedElasticsearchNode.java | 2 +-
.../EmbeddedElasticsearchPolicy.java | 103 +++
.../calcite/test/ElasticsearchChecker.java | 53 ++
elasticsearch5/src/test/resources/log4j2.xml | 2 +-
.../src/test/resources/zips-mini.json | 2 +-
.../adapter/mongodb/MongoAdapterTest.java | 812 +++++++++----------
.../adapter/mongodb/MongoDatabasePolicy.java | 84 ++
.../adapter/mongodb/MongoDatabaseRule.java | 84 --
.../org/apache/calcite/test/MongoAdapterIT.java | 6 +-
mongodb/src/test/resources/zips-mini.json | 2 +-
25 files changed, 1772 insertions(+), 1616 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/core/src/test/java/org/apache/calcite/util/UtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java
index 96f810f..4560fd5 100644
--- a/core/src/test/java/org/apache/calcite/util/UtilTest.java
+++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java
@@ -843,6 +843,7 @@ public class UtilTest {
Locale.getDefault(),
Locale.US,
Locale.TRADITIONAL_CHINESE,
+ Locale.ROOT,
};
for (Locale locale : locales) {
assertEquals(locale, Util.parseLocale(locale.toString()));
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
----------------------------------------------------------------------
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
index 2a57303..36940b8 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
@@ -71,8 +71,8 @@ import static org.junit.Assert.assertTrue;
* <li>push HAVING into "groupBy" query</li>
* </ul>
*
- * These tests use "timestamp with local time zone" type for the
- * Druid timestamp column, instead of "timestamp" type as
+ * <p>These tests use TIMESTAMP WITH LOCAL TIME ZONE type for the
+ * Druid timestamp column, instead of TIMESTAMP type as
* {@link DruidAdapterIT2}.
*/
public class DruidAdapterIT {
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
----------------------------------------------------------------------
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
index 64f26de..c673c7c 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
@@ -71,8 +71,8 @@ import static org.junit.Assert.assertTrue;
* <li>push HAVING into "groupBy" query</li>
* </ul>
*
- * These tests use "timestamp" type for the Druid timestamp column, instead
- * of "timestamp with local time zone" type as {@link DruidAdapterIT}.
+ * <p>These tests use TIMESTAMP type for the Druid timestamp column, instead
+ * of TIMESTAMP WITH LOCAL TIME ZONE type as {@link DruidAdapterIT}.
*/
public class DruidAdapterIT2 {
/** URL of the "druid-foodmart" model. */
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
index 8247957..62aa197 100644
--- a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
@@ -115,7 +115,7 @@ public class Elasticsearch2Enumerator implements Enumerator<Object> {
objects[i] = convert(hit.field(name).getValue(), field.getValue());
} else {
throw new IllegalStateException(
- String.format(Locale.getDefault(), "No result for %s", field));
+ String.format(Locale.ROOT, "No result for %s", field));
}
}
return objects;
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
deleted file mode 100644
index a7eff8f..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you 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.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.schema.impl.ViewTable;
-import org.apache.calcite.schema.impl.ViewTableMacro;
-import org.apache.calcite.test.CalciteAssert;
-import org.apache.calcite.test.ElasticChecker;
-
-import com.google.common.io.LineProcessor;
-import com.google.common.io.Resources;
-
-import org.elasticsearch.action.bulk.BulkItemResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Locale;
-
-/**
- * Set of tests for ES adapter. Uses real instance via {@link EmbeddedElasticRule}. Document
- * source is local {@code zips-mini.json} file (located in the classpath).
- */
-public class ElasticSearch2AdapterTest {
-
- @ClassRule //init once for all tests
- public static final EmbeddedElasticRule NODE = EmbeddedElasticRule.create();
-
- private static final String ZIPS = "zips";
-
- /**
- * Used to create {@code zips} index and insert some data
- *
- * @throws Exception when couldn't create the instance
- */
- @BeforeClass
- public static void setupInstance() throws Exception {
- // define mapping so fields are searchable (term query)
- XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
- .startObject("properties")
- .startObject("city").field("type", "string")
- .field("index", "not_analyzed").endObject()
- .startObject("state").field("type", "string")
- .field("index", "not_analyzed").endObject()
- .startObject("pop").field("type", "long").endObject()
- .endObject()
- .endObject();
-
- // create index
- NODE.client().admin().indices()
- .prepareCreate(ZIPS)
- .addMapping(ZIPS, mapping)
- .get();
-
- BulkRequestBuilder bulk = NODE.client().prepareBulk().setRefresh(true);
-
- // load records from file
- Resources.readLines(ElasticSearch2AdapterTest.class.getResource("/zips-mini.json"),
- StandardCharsets.UTF_8, new LineProcessor<Void>() {
- @Override public boolean processLine(String line) throws IOException {
- line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
- bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS).setSource(line));
- return true;
- }
-
- @Override public Void getResult() {
- return null;
- }
- });
-
- if (bulk.numberOfActions() == 0) {
- throw new IllegalStateException("No records to be indexed");
- }
-
- BulkResponse response = bulk.execute().get();
-
- if (response.hasFailures()) {
- throw new IllegalStateException(
- String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
- Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
- .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
- }
-
- }
-
- private CalciteAssert.ConnectionFactory newConnectionFactory() {
- return new CalciteAssert.ConnectionFactory() {
- @Override public Connection createConnection() throws SQLException {
- final Connection connection = DriverManager.getConnection("jdbc:calcite:");
- final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
-
- root.add("elastic", new Elasticsearch2Schema(NODE.client(), ZIPS));
-
- // add calcite view programmatically
- final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
- + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
- + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
- + " cast(_MAP['pop'] AS integer) AS \"pop\", "
- + " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
- + " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
- + "from \"elastic\".\"zips\"";
-
- ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
- Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
- root.add("ZIPS", macro);
-
- return connection;
- }
- };
- }
-
- private CalciteAssert.AssertThat calciteAssert() {
- return CalciteAssert.that()
- .with(newConnectionFactory());
- }
-
- /**
- * Tests using calcite view
- */
- @Test
- public void view() {
- calciteAssert()
- .query("select * from zips where \"city\" = 'BROOKLYN'")
- .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
- + "pop=111396; state=NY; id=11226\n")
- .returnsCount(1);
- }
-
- @Test
- public void emptyResult() {
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from zips limit 0")
- .returnsCount(0);
-
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
- .returnsCount(0);
- }
-
- @Test
- public void basic() throws Exception {
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
- .returnsCount(1);
-
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where"
- + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
- .returnsCount(2);
-
- // lower-case
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where "
- + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
- .returnsCount(0);
-
- // missing field
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
- .returnsCount(0);
-
- // limit works
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" limit 42")
- .returnsCount(42);
-
- }
-
- @Test public void testSort() {
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
- + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])";
-
- calciteAssert()
- .query("select * from zips order by \"state\"")
- .returnsCount(10)
- .explainContains(explain);
- }
-
- @Test public void testSortLimit() {
- final String sql = "select \"state\", \"id\" from zips\n"
- + "order by \"state\", \"id\" offset 2 rows fetch next 3 rows only";
- calciteAssert()
- .query(sql)
- .returnsUnordered("state=AK; id=99801",
- "state=AL; id=35215",
- "state=AL; id=35401")
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"_source\" : [\"state\", \"id\"]",
- "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]",
- "\"from\": 2",
- "\"size\": 3"));
- }
-
-
-
- @Test public void testOffsetLimit() {
- final String sql = "select \"state\", \"id\" from zips\n"
- + "offset 2 fetch next 3 rows only";
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"from\": 2",
- "\"size\": 3",
- "\"_source\" : [\"state\", \"id\"]"));
- }
-
- @Test public void testLimit() {
- final String sql = "select \"state\", \"id\" from zips\n"
- + "fetch next 3 rows only";
-
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"size\": 3",
- "\"_source\" : [\"state\", \"id\"]"));
- }
-
- @Test public void testFilterSort() {
- final String sql = "select * from zips\n"
- + "where \"state\" = 'CA' and \"id\" >= '70000'\n"
- + "order by \"state\", \"id\"";
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
- + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])";
- calciteAssert()
- .query(sql)
- .returnsOrdered("city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; "
- + "pop=96074; state=CA; id=90011",
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; "
- + "pop=99568; state=CA; id=90201",
- "city=NORWALK; longitude=-118.081767; latitude=33.90564; "
- + "pop=94188; state=CA; id=90650")
- .queryContains(
- ElasticChecker.elasticsearchChecker("\"query\" : "
- + "{\"constant_score\":{\"filter\":{\"bool\":"
- + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
- + "{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
- + "\"city\":{\"script\": \"_source.city\"}, "
- + "\"pop\":{\"script\": \"_source.pop\"}, "
- + "\"state\":{\"script\": \"_source.state\"}, "
- + "\"id\":{\"script\": \"_source.id\"}}",
- "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
- .explainContains(explain);
- }
-
- @Test public void testFilterSortDesc() {
- final String sql = "select * from zips\n"
- + "where \"pop\" BETWEEN 95000 AND 100000\n"
- + "order by \"state\" desc, \"pop\"";
- calciteAssert()
- .query(sql)
- .limit(4)
- .returnsOrdered(
- "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
- }
-
- @Test public void testFilterRedundant() {
- final String sql = "select * from zips\n"
- + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(""
- + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
- + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
- + "\"city\":{\"script\": \"_source.city\"}, "
- + "\"pop\":{\"script\": \"_source.pop\"}, \"state\":{\"script\": \"_source.state\"}, "
- + "\"id\":{\"script\": \"_source.id\"}}"
- ));
- }
-
- @Test public void testInPlan() {
- final String[] searches = {
- "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
- + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
- + "{\"pop\":99568}}]}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
- + "\"city\":{\"script\": \"_source.city\"}, "
- + "\"pop\":{\"script\": \"_source.pop\"}, "
- + "\"state\":{\"script\": \"_source.state\"}, "
- + "\"id\":{\"script\": \"_source.id\"}}"
- };
-
- calciteAssert()
- .query("select * from zips where \"pop\" in (96074, 99568)")
- .returnsUnordered(
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
- "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011"
- )
- .queryContains(ElasticChecker.elasticsearchChecker(searches));
- }
-
- @Test public void testZips() {
- calciteAssert()
- .query("select \"state\", \"city\" from zips")
- .returnsCount(10);
- }
-
- @Test public void testProject() {
- final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
- + "from zips\n"
- + "order by \"state\", \"city\"";
-
- calciteAssert()
- .query(sql)
- .limit(2)
- .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
- "state=AK; city=FAIRBANKS; zero=0")
- .queryContains(
- ElasticChecker.elasticsearchChecker("\"script_fields\": "
- + "{\"zero\":{\"script\": \"0\"}, "
- + "\"state\":{\"script\": \"_source.state\"}, "
- + "\"city\":{\"script\": \"_source.city\"}}",
- "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
- }
-
- @Test public void testFilter() {
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])";
- calciteAssert()
- .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
- .limit(3)
- .returnsUnordered("state=CA; city=BELL GARDENS",
- "state=CA; city=LOS ANGELES",
- "state=CA; city=NORWALK")
- .explainContains(explain);
- }
-
- @Test public void testFilterReversed() {
- calciteAssert()
- .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
- .limit(2)
- .returnsUnordered("state=WV; city=BECKLEY",
- "state=WY; city=CHEYENNE");
- calciteAssert()
- .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
- .limit(2)
- .returnsUnordered("state=WV; city=BECKLEY",
- "state=WY; city=CHEYENNE");
- }
-
-}
-
-// End ElasticSearch2AdapterTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
new file mode 100644
index 0000000..8624ac7
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.ViewTable;
+import org.apache.calcite.schema.impl.ViewTableMacro;
+import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ElasticsearchChecker;
+
+import com.google.common.io.LineProcessor;
+import com.google.common.io.Resources;
+
+import org.elasticsearch.action.bulk.BulkItemResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Locale;
+
+/**
+ * Set of tests for the Elasticsearch 2 adapter.
+ *
+ * <p>Uses a real instance via {@link EmbeddedElasticsearchPolicy}.
+ * The document source is a local {@code zips-mini.json} file
+ * (located in the classpath).
+ */
+public class Elasticsearch2AdapterTest {
+
+ @ClassRule // init once for all tests
+ public static final EmbeddedElasticsearchPolicy NODE =
+ EmbeddedElasticsearchPolicy.create();
+
+ private static final String ZIPS = "zips";
+
+ /**
+ * Used to create {@code zips} index and insert some data
+ *
+ * @throws Exception when couldn't create the instance
+ */
+ @BeforeClass
+ public static void setupInstance() throws Exception {
+ // define mapping so fields are searchable (term query)
+ XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
+ .startObject("properties")
+ .startObject("city").field("type", "string")
+ .field("index", "not_analyzed").endObject()
+ .startObject("state").field("type", "string")
+ .field("index", "not_analyzed").endObject()
+ .startObject("pop").field("type", "long").endObject()
+ .endObject()
+ .endObject();
+
+ // create index
+ NODE.client().admin().indices()
+ .prepareCreate(ZIPS)
+ .addMapping(ZIPS, mapping)
+ .get();
+
+ BulkRequestBuilder bulk = NODE.client().prepareBulk().setRefresh(true);
+
+ // load records from file
+ Resources.readLines(Elasticsearch2AdapterTest.class.getResource("/zips-mini.json"),
+ StandardCharsets.UTF_8, new LineProcessor<Void>() {
+ @Override public boolean processLine(String line) throws IOException {
+ line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
+ bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS).setSource(line));
+ return true;
+ }
+
+ @Override public Void getResult() {
+ return null;
+ }
+ });
+
+ if (bulk.numberOfActions() == 0) {
+ throw new IllegalStateException("No records to be indexed");
+ }
+
+ BulkResponse response = bulk.execute().get();
+
+ if (response.hasFailures()) {
+ throw new IllegalStateException(
+ String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
+ Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
+ .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
+ }
+
+ }
+
+ private CalciteAssert.ConnectionFactory newConnectionFactory() {
+ return new CalciteAssert.ConnectionFactory() {
+ @Override public Connection createConnection() throws SQLException {
+ final Connection connection = DriverManager.getConnection("jdbc:calcite:");
+ final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
+
+ root.add("elastic", new Elasticsearch2Schema(NODE.client(), ZIPS));
+
+ // add calcite view programmatically
+ final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
+ + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
+ + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
+ + " cast(_MAP['pop'] AS integer) AS \"pop\", "
+ + " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
+ + " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
+ + "from \"elastic\".\"zips\"";
+
+ ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
+ Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
+ root.add("ZIPS", macro);
+
+ return connection;
+ }
+ };
+ }
+
+ private CalciteAssert.AssertThat calciteAssert() {
+ return CalciteAssert.that()
+ .with(newConnectionFactory());
+ }
+
+ /**
+ * Tests using calcite view
+ */
+ @Test
+ public void view() {
+ calciteAssert()
+ .query("select * from zips where \"city\" = 'BROOKLYN'")
+ .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
+ + "pop=111396; state=NY; id=11226\n")
+ .returnsCount(1);
+ }
+
+ @Test
+ public void emptyResult() {
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from zips limit 0")
+ .returnsCount(0);
+
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
+ .returnsCount(0);
+ }
+
+ @Test
+ public void basic() throws Exception {
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
+ .returnsCount(1);
+
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" where"
+ + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
+ .returnsCount(2);
+
+ // lower-case
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" where "
+ + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
+ .returnsCount(0);
+
+ // missing field
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
+ .returnsCount(0);
+
+ // limit works
+ CalciteAssert.that()
+ .with(newConnectionFactory())
+ .query("select * from \"elastic\".\"zips\" limit 42")
+ .returnsCount(42);
+
+ }
+
+ @Test public void testSort() {
+ final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+ + " ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
+ + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+ + " ElasticsearchTableScan(table=[[elastic, zips]])";
+
+ calciteAssert()
+ .query("select * from zips order by \"state\"")
+ .returnsCount(10)
+ .explainContains(explain);
+ }
+
+ @Test public void testSortLimit() {
+ final String sql = "select \"state\", \"id\" from zips\n"
+ + "order by \"state\", \"id\" offset 2 rows fetch next 3 rows only";
+ calciteAssert()
+ .query(sql)
+ .returnsUnordered("state=AK; id=99801",
+ "state=AL; id=35215",
+ "state=AL; id=35401")
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker(
+ "\"_source\" : [\"state\", \"id\"]",
+ "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]",
+ "\"from\": 2",
+ "\"size\": 3"));
+ }
+
+
+
+ @Test public void testOffsetLimit() {
+ final String sql = "select \"state\", \"id\" from zips\n"
+ + "offset 2 fetch next 3 rows only";
+ calciteAssert()
+ .query(sql)
+ .runs()
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker(
+ "\"from\": 2",
+ "\"size\": 3",
+ "\"_source\" : [\"state\", \"id\"]"));
+ }
+
+ @Test public void testLimit() {
+ final String sql = "select \"state\", \"id\" from zips\n"
+ + "fetch next 3 rows only";
+
+ calciteAssert()
+ .query(sql)
+ .runs()
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker(
+ "\"size\": 3",
+ "\"_source\" : [\"state\", \"id\"]"));
+ }
+
+ @Test public void testFilterSort() {
+ final String sql = "select * from zips\n"
+ + "where \"state\" = 'CA' and \"id\" >= '70000'\n"
+ + "order by \"state\", \"id\"";
+ final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+ + " ElasticsearchSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
+ + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+ + " ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
+ + " ElasticsearchTableScan(table=[[elastic, zips]])";
+ calciteAssert()
+ .query(sql)
+ .returnsOrdered("city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; "
+ + "pop=96074; state=CA; id=90011",
+ "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; "
+ + "pop=99568; state=CA; id=90201",
+ "city=NORWALK; longitude=-118.081767; latitude=33.90564; "
+ + "pop=94188; state=CA; id=90650")
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker("\"query\" : "
+ + "{\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
+ + "{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
+ "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+ + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+ + "\"city\":{\"script\": \"_source.city\"}, "
+ + "\"pop\":{\"script\": \"_source.pop\"}, "
+ + "\"state\":{\"script\": \"_source.state\"}, "
+ + "\"id\":{\"script\": \"_source.id\"}}",
+ "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterSortDesc() {
+ final String sql = "select * from zips\n"
+ + "where \"pop\" BETWEEN 95000 AND 100000\n"
+ + "order by \"state\" desc, \"pop\"";
+ calciteAssert()
+ .query(sql)
+ .limit(4)
+ .returnsOrdered(
+ "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
+ "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
+ }
+
+ @Test public void testFilterRedundant() {
+ final String sql = "select * from zips\n"
+ + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
+ calciteAssert()
+ .query(sql)
+ .runs()
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker(""
+ + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
+ "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+ + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+ + "\"city\":{\"script\": \"_source.city\"}, "
+ + "\"pop\":{\"script\": \"_source.pop\"}, \"state\":{\"script\": \"_source.state\"}, "
+ + "\"id\":{\"script\": \"_source.id\"}}"));
+ }
+
+ @Test public void testInPlan() {
+ final String[] searches = {
+ "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
+ + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
+ + "{\"pop\":99568}}]}}]}}}}",
+ "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+ + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+ + "\"city\":{\"script\": \"_source.city\"}, "
+ + "\"pop\":{\"script\": \"_source.pop\"}, "
+ + "\"state\":{\"script\": \"_source.state\"}, "
+ + "\"id\":{\"script\": \"_source.id\"}}"
+ };
+
+ calciteAssert()
+ .query("select * from zips where \"pop\" in (96074, 99568)")
+ .returnsUnordered(
+ "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
+ "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011")
+ .queryContains(ElasticsearchChecker.elasticsearchChecker(searches));
+ }
+
+ @Test public void testZips() {
+ calciteAssert()
+ .query("select \"state\", \"city\" from zips")
+ .returnsCount(10);
+ }
+
+ @Test public void testProject() {
+ final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
+ + "from zips\n"
+ + "order by \"state\", \"city\"";
+
+ calciteAssert()
+ .query(sql)
+ .limit(2)
+ .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
+ "state=AK; city=FAIRBANKS; zero=0")
+ .queryContains(
+ ElasticsearchChecker.elasticsearchChecker("\"script_fields\": "
+ + "{\"zero\":{\"script\": \"0\"}, "
+ + "\"state\":{\"script\": \"_source.state\"}, "
+ + "\"city\":{\"script\": \"_source.city\"}}",
+ "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
+ }
+
+ @Test public void testFilter() {
+ final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+ + " ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+ + " ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
+ + " ElasticsearchTableScan(table=[[elastic, zips]])";
+ calciteAssert()
+ .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
+ .limit(3)
+ .returnsUnordered("state=CA; city=BELL GARDENS",
+ "state=CA; city=LOS ANGELES",
+ "state=CA; city=NORWALK")
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterReversed() {
+ calciteAssert()
+ .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
+ .limit(2)
+ .returnsUnordered("state=WV; city=BECKLEY",
+ "state=WY; city=CHEYENNE");
+ calciteAssert()
+ .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
+ .limit(2)
+ .returnsUnordered("state=WV; city=BECKLEY",
+ "state=WY; city=CHEYENNE");
+ }
+
+}
+
+// End Elasticsearch2AdapterTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
deleted file mode 100644
index 55f83f9..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you 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.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-
-import org.elasticsearch.Version;
-import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
-import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.node.internal.InternalSettingsPreparer;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.script.groovy.GroovyPlugin;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Represents a single elastic search node which can run embedded in a java application.
- * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
- */
-class EmbeddedElasticNode implements AutoCloseable {
-
- private final LocalNode node;
- private volatile boolean isStarted;
-
- private EmbeddedElasticNode(LocalNode node) {
- this.node = Preconditions.checkNotNull(node, "node");
- }
-
- /**
- * Having separate class to expose (protected) constructor which allows to install
- * different plugins. In our case it is {@code GroovyPlugin} for scripted fields like
- * {@code loc[0]} or {@code loc[1]['foo']}.
- */
- private static class LocalNode extends Node {
- private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
- super(InternalSettingsPreparer.prepareEnvironment(settings, null),
- Version.CURRENT, classpathPlugins);
- }
- }
-
- /**
- * Creates an instance with existing settings
- *
- * @param settings ES settings for the node
- * @return un-started node; call {@link #start()} to start the instance
- */
- private static EmbeddedElasticNode create(Settings settings) {
- // ensure GroovyPlugin is installed or otherwise scripted fields would not work
- LocalNode node = new LocalNode(settings, Collections.singleton(GroovyPlugin.class));
- return new EmbeddedElasticNode(node);
- }
-
- /**
- * Creates elastic node as single member of a cluster. Node will not be started
- * unless {@link #start()} is explicitly called.
- *
- * @return node with default configuration
- */
- public static EmbeddedElasticNode create() {
- File data = Files.createTempDir();
- data.deleteOnExit();
- File home = Files.createTempDir();
- home.deleteOnExit();
-
- Settings settings = Settings.builder()
- .put("node.name", "fake-elastic")
- .put("path.home", home.getAbsolutePath())
- .put("path.data", data.getAbsolutePath())
- .put("script.inline", true) // requires GroovyPlugin
- .put("script.indexed", true) // requires GroovyPlugin
- .put("cluster.routing.allocation.disk.threshold_enabled", false)
- .put("node.local", true)
- .put("node.data", true)
- .put("network.host", "localhost")
- .build();
-
- return create(settings);
- }
-
- /**
- * Starts current node
- */
- public void start() {
- Preconditions.checkState(!isStarted, "already started");
- node.start();
- this.isStarted = true;
- }
-
- /**
- * Returns the current address to connect to with HTTP client.
- *
- * @return {@code HTTP} address (hostname / port)
- */
- public TransportAddress httpAddress() {
- Preconditions.checkState(isStarted, "node is not started");
-
- NodesInfoResponse response = client().admin().cluster().prepareNodesInfo()
- .execute().actionGet();
- if (response.getNodes().length != 1) {
- throw new IllegalStateException("Expected single node but got "
- + response.getNodes().length);
- }
- NodeInfo node = response.getNodes()[0];
- return node.getHttp().address().boundAddresses()[0];
- }
-
- /**
- * Exposes elastic
- * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
- * (use of HTTP client is preferred).
- *
- * @return client API to access ES functionality
- */
- public Client client() {
- Preconditions.checkState(isStarted, "node is not started");
- return node.client();
- }
-
- @Override public void close() throws Exception {
- node.close();
- // cleanup data dirs
- File data = new File(node.settings().get("path.data"));
- File home = new File(node.settings().get("path.home"));
- for (File file: Arrays.asList(data, home)) {
- if (file.exists()) {
- file.delete();
- }
- }
- }
-}
-
-// End EmbeddedElasticNode.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
deleted file mode 100644
index 4bd9c25..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you 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.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import com.google.common.base.Preconditions;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.junit.rules.ExternalResource;
-
-/**
- * Used to initialize a single elastic node. For performance reasons (node startup costs),
- * same instance is usually shared across multiple tests.
- *
- * This rule should be used as follows:
- * <pre>
- *
- * public class MyTest {
- * @ClassRule
- * public static final ElasticSearchRule RULE = ElasticSearchRule.create();
- *
- * @BeforeClass
- * public static void setup() {
- * // ... populate instance
- * }
- *
- * @Test
- * public void myTest() {
- * TransportAddress address = RULE.httpAddress();
- * // .... (connect)
- * }
- * }
- * </pre>
- *
- * @see ExternalResource
- */
-class EmbeddedElasticRule extends ExternalResource {
-
- private final EmbeddedElasticsearchNode node;
-
- private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
- this.node = Preconditions.checkNotNull(resource, "resource");
- }
-
- @Override protected void before() throws Throwable {
- node.start();
- }
-
- @Override protected void after() {
- try {
- node.close();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Factory method to create this rule.
- *
- * @return new rule instance to be used in unit tests
- */
-<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
- public static EmbeddedElasticRule create() {
- return new EmbeddedElasticRule(EmbeddedElasticNode.create());
-=======
- public static EmbeddedElasticsearchPolicy create() {
- return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
->>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
- }
-
- /**
- * Exposes current ES transport client.
- *
- * @return initialized instance of ES
- */
- Client client() {
- return node.client();
- }
-
- /**
- * HTTP address for rest clients (can be ES native or any other).
- *
-<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
- * @return HTTP hostname/port to connect to this ES instance
-=======
- * @return {@code HTTP} connection parameters
->>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
- */
- TransportAddress httpAddress() {
- return node.httpAddress();
- }
-}
-
-// End EmbeddedElasticRule.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
new file mode 100644
index 0000000..d7e3464
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.Files;
+
+import org.elasticsearch.Version;
+import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
+import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.internal.InternalSettingsPreparer;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.script.groovy.GroovyPlugin;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Represents a single Elasticsearch node that can run embedded in a java application.
+ * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
+ */
+class EmbeddedElasticsearchNode implements AutoCloseable {
+
+ private final LocalNode node;
+ private volatile boolean isStarted;
+
+ private EmbeddedElasticsearchNode(LocalNode node) {
+ this.node = Preconditions.checkNotNull(node, "node");
+ }
+
+ /**
+ * Having separate class to expose (protected) constructor which allows to install
+ * different plugins. In our case it is {@code GroovyPlugin} for scripted fields like
+ * {@code loc[0]} or {@code loc[1]['foo']}.
+ */
+ private static class LocalNode extends Node {
+ private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
+ super(InternalSettingsPreparer.prepareEnvironment(settings, null),
+ Version.CURRENT, classpathPlugins);
+ }
+ }
+
+ /**
+ * Creates an instance with existing settings
+ *
+ * @param settings ES settings for the node
+ * @return un-started node; call {@link #start()} to start the instance
+ */
+ private static EmbeddedElasticsearchNode create(Settings settings) {
+ // ensure GroovyPlugin is installed or otherwise scripted fields would not work
+ LocalNode node = new LocalNode(settings, Collections.singleton(GroovyPlugin.class));
+ return new EmbeddedElasticsearchNode(node);
+ }
+
+ /**
+ * Creates elastic node as single member of a cluster. Node will not be started
+ * unless {@link #start()} is explicitly called.
+ *
+ * @return node with default configuration
+ */
+ public static EmbeddedElasticsearchNode create() {
+ File data = Files.createTempDir();
+ data.deleteOnExit();
+ File home = Files.createTempDir();
+ home.deleteOnExit();
+
+ Settings settings = Settings.builder()
+ .put("node.name", "fake-elastic")
+ .put("path.home", home.getAbsolutePath())
+ .put("path.data", data.getAbsolutePath())
+ .put("script.inline", true) // requires GroovyPlugin
+ .put("script.indexed", true) // requires GroovyPlugin
+ .put("cluster.routing.allocation.disk.threshold_enabled", false)
+ .put("node.local", true)
+ .put("node.data", true)
+ .put("network.host", "localhost")
+ .build();
+
+ return create(settings);
+ }
+
+ /**
+ * Starts current node
+ */
+ public void start() {
+ Preconditions.checkState(!isStarted, "already started");
+ node.start();
+ this.isStarted = true;
+ }
+
+ /**
+ * Returns the current address to connect to with HTTP client.
+ *
+ * @return {@code HTTP} address (hostname / port)
+ */
+ public TransportAddress httpAddress() {
+ Preconditions.checkState(isStarted, "node is not started");
+
+ NodesInfoResponse response = client().admin().cluster().prepareNodesInfo()
+ .execute().actionGet();
+ if (response.getNodes().length != 1) {
+ throw new IllegalStateException("Expected single node but got "
+ + response.getNodes().length);
+ }
+ NodeInfo node = response.getNodes()[0];
+ return node.getHttp().address().boundAddresses()[0];
+ }
+
+ /**
+ * Exposes an Elasticsearch
+ * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
+ * (use of HTTP client is preferred).
+ *
+ * @return client API to access ES functionality
+ */
+ public Client client() {
+ Preconditions.checkState(isStarted, "node is not started");
+ return node.client();
+ }
+
+ @Override public void close() throws Exception {
+ node.close();
+ // cleanup data dirs
+ File data = new File(node.settings().get("path.data"));
+ File home = new File(node.settings().get("path.home"));
+ for (File file: Arrays.asList(data, home)) {
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ }
+}
+
+// End EmbeddedElasticsearchNode.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
new file mode 100644
index 0000000..6b25ecf
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import com.google.common.base.Preconditions;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.junit.rules.ExternalResource;
+
+/**
+ * Junit rule that is used to initialize a single Elasticsearch node for tests.
+ *
+ * <p>For performance reasons (node startup costs),
+ * the same instance is usually shared across multiple tests.
+ *
+ * <p>This rule should be used as follows:
+ * <pre>
+ *
+ * public class MyTest {
+ * @ClassRule
+ * public static final EmbeddedElasticsearchPolicy POLICY =
+ * EmbeddedElasticsearchPolicy.create();
+ *
+ * @BeforeClass
+ * public static void setup() {
+ * // ... populate instance
+ * }
+ *
+ * @Test
+ * public void myTest() {
+ * TransportAddress address = POLICY.httpAddress();
+ * // .... (connect)
+ * }
+ * }
+ * </pre>
+ *
+ * @see ExternalResource
+ */
+class EmbeddedElasticsearchPolicy extends ExternalResource {
+
+ private final EmbeddedElasticsearchNode node;
+
+ private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
+ this.node = Preconditions.checkNotNull(resource, "resource");
+ }
+
+ @Override protected void before() throws Throwable {
+ node.start();
+ }
+
+ @Override protected void after() {
+ try {
+ node.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Factory method to create this rule.
+ *
+ * @return new rule instance to be used in unit tests
+ */
+ public static EmbeddedElasticsearchPolicy create() {
+ return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
+ }
+
+ /**
+ * Exposes current ES transport client.
+ *
+ * @return initialized instance of ES
+ */
+ Client client() {
+ return node.client();
+ }
+
+ /**
+ * HTTP address for rest clients (can be ES native or any other).
+ *
+ * @return HTTP hostname/port to connect to this ES instance
+ */
+ TransportAddress httpAddress() {
+ return node.httpAddress();
+ }
+}
+
+// End EmbeddedElasticsearchPolicy.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
deleted file mode 100644
index 86e9d9f..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you 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.
- */
-package org.apache.calcite.test;
-
-import com.google.common.base.Function;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * Internal util methods for ElasticSearch tests
- */
-public class ElasticChecker {
-
- private ElasticChecker() {}
-
-
- /** Returns a function that checks that a particular Elasticsearch pipeline is
- * generated to implement a query.
- *
- * @param strings list of expected queries
- * @return function to perform the check
- */
- public static Function<List, Void> elasticsearchChecker(final String... strings) {
- return new Function<List, Void>() {
- @Nullable
- @Override public Void apply(@Nullable List actual) {
- Object[] actualArray = actual == null || actual.isEmpty() ? null
- : ((List) actual.get(0)).toArray();
- CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
- actualArray);
- return null;
- }
- };
- }
-}
-
-// End ElasticChecker.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
new file mode 100644
index 0000000..d897dfb
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.
+ */
+package org.apache.calcite.test;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for Elasticsearch tests.
+ */
+public class ElasticsearchChecker {
+
+ private ElasticsearchChecker() {}
+
+
+ /** Returns a function that checks that a particular Elasticsearch pipeline is
+ * generated to implement a query.
+ *
+ * @param strings list of expected queries
+ * @return function to perform the check
+ */
+ public static Function<List, Void> elasticsearchChecker(final String... strings) {
+ return new Function<List, Void>() {
+ @Nullable
+ @Override public Void apply(@Nullable List actual) {
+ Object[] actualArray = actual == null || actual.isEmpty() ? null
+ : ((List) actual.get(0)).toArray();
+ CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
+ actualArray);
+ return null;
+ }
+ };
+ }
+}
+
+// End ElasticsearchChecker.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/resources/zips-mini.json
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/resources/zips-mini.json b/elasticsearch2/src/test/resources/zips-mini.json
index d70eadc..858117a 100644
--- a/elasticsearch2/src/test/resources/zips-mini.json
+++ b/elasticsearch2/src/test/resources/zips-mini.json
@@ -146,4 +146,4 @@
{ "_id" : "98310", "city" : "BREMERTON", "loc" : [ -122.629913, 47.601916 ], "pop" : 49057, "state" : "WA" }
{ "_id" : "99504", "city" : "ANCHORAGE", "loc" : [ -149.74467, 61.203696 ], "pop" : 32383, "state" : "AK" }
{ "_id" : "99709", "city" : "FAIRBANKS", "loc" : [ -147.846917, 64.85437 ], "pop" : 23238, "state" : "AK" }
-{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }
\ No newline at end of file
+{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
deleted file mode 100644
index 438e048..0000000
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you 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.
- */
-package org.apache.calcite.adapter.elasticsearch5;
-
-import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.schema.impl.ViewTable;
-import org.apache.calcite.schema.impl.ViewTableMacro;
-import org.apache.calcite.test.CalciteAssert;
-import org.apache.calcite.test.ElasticChecker;
-
-import com.google.common.io.LineProcessor;
-import com.google.common.io.Resources;
-
-import org.elasticsearch.action.bulk.BulkItemResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.support.WriteRequest;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-import org.elasticsearch.common.xcontent.XContentType;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Locale;
-
-/**
- * Set of tests for ES adapter. Uses real instance via {@link EmbeddedElasticRule}. Document
- * source is local {@code zips-mini.json} file (located in the classpath).
- */
-public class ElasticSearch5AdapterTest {
-
- @ClassRule //init once for all tests
- public static final EmbeddedElasticRule NODE = EmbeddedElasticRule.create();
-
- private static final String ZIPS = "zips";
-
- /**
- * Used to create {@code zips} index and insert some data
- *
- * @throws Exception when ES instance setup failed
- */
- @BeforeClass
- public static void setupInstance() throws Exception {
- // define mapping so fields are searchable (term query)
- XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
- .startObject("properties")
- .startObject("city").field("type", "string")
- .field("index", "not_analyzed").endObject()
- .startObject("state").field("type", "string")
- .field("index", "not_analyzed").endObject()
- .startObject("pop").field("type", "long").endObject()
- .endObject()
- .endObject();
-
- // create index
- NODE.client().admin().indices()
- .prepareCreate(ZIPS)
- .addMapping(ZIPS, mapping)
- .get();
-
- BulkRequestBuilder bulk = NODE.client().prepareBulk()
- .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
-
- // load records from file
- Resources.readLines(ElasticSearch5AdapterTest.class.getResource("/zips-mini.json"),
- StandardCharsets.UTF_8, new LineProcessor<Void>() {
- @Override public boolean processLine(String line) throws IOException {
- line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
- bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS)
- .setSource(line.getBytes(StandardCharsets.UTF_8), XContentType.JSON));
- return true;
- }
-
- @Override public Void getResult() {
- return null;
- }
- });
-
- if (bulk.numberOfActions() == 0) {
- throw new IllegalStateException("No records to be indexed");
- }
-
- BulkResponse response = bulk.execute().get();
-
- if (response.hasFailures()) {
- throw new IllegalStateException(
- String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
- Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
- .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
- }
-
- }
-
- private CalciteAssert.ConnectionFactory newConnectionFactory() {
- return new CalciteAssert.ConnectionFactory() {
- @Override public Connection createConnection() throws SQLException {
- final Connection connection = DriverManager.getConnection("jdbc:calcite:");
- final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
-
- root.add("elastic", new Elasticsearch5Schema(NODE.client(), ZIPS));
-
- // add calcite view programmatically
- final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
- + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
- + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
- + " cast(_MAP['pop'] AS integer) AS \"pop\", "
- + " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
- + " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
- + "from \"elastic\".\"zips\"";
-
- ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
- Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
- root.add("ZIPS", macro);
-
- return connection;
- }
- };
- }
-
- private CalciteAssert.AssertThat calciteAssert() {
- return CalciteAssert.that()
- .with(newConnectionFactory());
- }
-
- /**
- * Tests using calcite view
- */
- @Test
- public void view() {
- calciteAssert()
- .query("select * from zips where \"city\" = 'BROOKLYN'")
- .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
- + "pop=111396; state=NY; id=11226\n")
- .returnsCount(1);
- }
-
- @Test
- public void emptyResult() {
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from zips limit 0")
- .returnsCount(0);
-
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
- .returnsCount(0);
- }
-
- @Test
- public void basic() throws Exception {
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
- .returnsCount(1);
-
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where"
- + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
- .returnsCount(2);
-
- // lower-case
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where "
- + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
- .returnsCount(0);
-
- // missing field
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
- .returnsCount(0);
-
- // limit works
- CalciteAssert.that()
- .with(newConnectionFactory())
- .query("select * from \"elastic\".\"zips\" limit 42")
- .returnsCount(42);
-
- }
-
- @Test public void testSort() {
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
- + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])";
-
- calciteAssert()
- .query("select * from zips order by \"state\"")
- .returnsCount(10)
- .explainContains(explain);
- }
-
- @Test public void testSortLimit() {
- final String sql = "select \"state\", \"pop\" from zips\n"
- + "order by \"state\", \"pop\" offset 2 rows fetch next 3 rows only";
- calciteAssert()
- .query(sql)
- .returnsUnordered("state=AK; pop=32383",
- "state=AL; pop=42124",
- "state=AL; pop=43862")
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"_source\" : [\"state\", \"pop\"]",
- "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]",
- "\"from\": 2",
- "\"size\": 3"));
- }
-
-
-
- @Test public void testOffsetLimit() {
- final String sql = "select \"state\", \"id\" from zips\n"
- + "offset 2 fetch next 3 rows only";
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"from\": 2",
- "\"size\": 3",
- "\"_source\" : [\"state\", \"id\"]"));
- }
-
- @Test public void testLimit() {
- final String sql = "select \"state\", \"id\" from zips\n"
- + "fetch next 3 rows only";
-
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(
- "\"size\": 3",
- "\"_source\" : [\"state\", \"id\"]"));
- }
-
- @Test public void testFilterSort() {
- final String sql = "select * from zips\n"
- + "where \"state\" = 'CA' and \"pop\" >= 94000\n"
- + "order by \"state\", \"pop\"";
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchSort(sort0=[$4], sort1=[$3], dir0=[ASC], dir1=[ASC])\n"
- + " ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'pop')):INTEGER, 94000))])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])\n\n";
- calciteAssert()
- .query(sql)
- .returnsOrdered("city=NORWALK; longitude=-118.081767; latitude=33.90564;"
- + " pop=94188; state=CA; id=90650",
- "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856;"
- + " pop=96074; state=CA; id=90011",
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177;"
- + " pop=99568; state=CA; id=90201")
- .queryContains(
- ElasticChecker.elasticsearchChecker("\"query\" : "
- + "{\"constant_score\":{\"filter\":{\"bool\":"
- + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
- + "{\"range\":{\"pop\":{\"gte\":94000}}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
- + "\"city\":{\"script\": \"params._source.city\"}, "
- + "\"pop\":{\"script\": \"params._source.pop\"}, "
- + "\"state\":{\"script\": \"params._source.state\"}, "
- + "\"id\":{\"script\": \"params._source.id\"}}",
- "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]"))
- .explainContains(explain);
- }
-
- @Test public void testFilterSortDesc() {
- final String sql = "select * from zips\n"
- + "where \"pop\" BETWEEN 95000 AND 100000\n"
- + "order by \"state\" desc, \"pop\"";
- calciteAssert()
- .query(sql)
- .limit(4)
- .returnsOrdered(
- "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
- }
-
- @Test public void testFilterRedundant() {
- final String sql = "select * from zips\n"
- + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
- calciteAssert()
- .query(sql)
- .runs()
- .queryContains(
- ElasticChecker.elasticsearchChecker(""
- + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
- + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
- + "\"city\":{\"script\": \"params._source.city\"}, "
- + "\"pop\":{\"script\": \"params._source.pop\"}, \"state\":{\"script\": \"params._source.state\"}, "
- + "\"id\":{\"script\": \"params._source.id\"}}"
- ));
- }
-
- @Test public void testInPlan() {
- final String[] searches = {
- "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
- + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
- + "{\"pop\":99568}}]}}]}}}}",
- "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
- + "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
- + "\"city\":{\"script\": \"params._source.city\"}, "
- + "\"pop\":{\"script\": \"params._source.pop\"}, "
- + "\"state\":{\"script\": \"params._source.state\"}, "
- + "\"id\":{\"script\": \"params._source.id\"}}"
- };
-
- calciteAssert()
- .query("select * from zips where \"pop\" in (96074, 99568)")
- .returnsUnordered(
- "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
- "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011"
- )
- .queryContains(ElasticChecker.elasticsearchChecker(searches));
- }
-
- @Test public void testZips() {
- calciteAssert()
- .query("select \"state\", \"city\" from zips")
- .returnsCount(10);
- }
-
- @Test public void testProject() {
- final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
- + "from zips\n"
- + "order by \"state\", \"city\"";
-
- calciteAssert()
- .query(sql)
- .limit(2)
- .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
- "state=AK; city=FAIRBANKS; zero=0")
- .queryContains(
- ElasticChecker.elasticsearchChecker("\"script_fields\": "
- + "{\"zero\":{\"script\": \"0\"}, "
- + "\"state\":{\"script\": \"params._source.state\"}, "
- + "\"city\":{\"script\": \"params._source.city\"}}",
- "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
- }
-
- @Test public void testFilter() {
- final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
- + " ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
- + " ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
- + " ElasticsearchTableScan(table=[[elastic, zips]])";
- calciteAssert()
- .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
- .limit(3)
- .returnsUnordered("state=CA; city=BELL GARDENS",
- "state=CA; city=LOS ANGELES",
- "state=CA; city=NORWALK")
- .explainContains(explain);
- }
-
- @Test public void testFilterReversed() {
- calciteAssert()
- .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
- .limit(2)
- .returnsUnordered("state=WV; city=BECKLEY",
- "state=WY; city=CHEYENNE");
- calciteAssert()
- .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
- .limit(2)
- .returnsUnordered("state=WV; city=BECKLEY",
- "state=WY; city=CHEYENNE");
- }
-
-}
-
-// End ElasticSearch5AdapterTest.java