You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by mm...@apache.org on 2017/09/05 14:36:46 UTC
[03/16] calcite git commit: [CALCITE-1967] Elasticsearch 5 adapter
(Christian Beikov)
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java
new file mode 100644
index 0000000..636aa5f
--- /dev/null
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java
@@ -0,0 +1,66 @@
+/*
+ * 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.adapter.elasticsearch.AbstractElasticsearchTable;
+import org.apache.calcite.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.function.Function1;
+
+import org.apache.calcite.util.Util;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.search.SearchHit;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Table based on an Elasticsearch2 type.
+ */
+public class Elasticsearch2Table extends AbstractElasticsearchTable {
+ private final Client client;
+
+ /**
+ * Creates an Elasticsearch2Table.
+ */
+ public Elasticsearch2Table(Client client, String indexName, String typeName) {
+ super(indexName, typeName);
+ this.client = client;
+ }
+
+ @Override protected Enumerable<Object> find(String index, List<String> ops,
+ List<Map.Entry<String, Class>> fields) {
+ final String dbName = index;
+
+ final String queryString = "{" + Util.toString(ops, "", ", ", "") + "}";
+
+ final Function1<SearchHit, Object> getter = Elasticsearch2Enumerator.getter(fields);
+
+ return new AbstractEnumerable<Object>() {
+ public Enumerator<Object> enumerator() {
+ final Iterator<SearchHit> cursor = client.prepareSearch(dbName).setTypes(typeName)
+ .setSource(queryString).execute().actionGet().getHits().iterator();
+ return new Elasticsearch2Enumerator(cursor, getter);
+ }
+ };
+ }
+}
+
+// End Elasticsearch2Table.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/package-info.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/package-info.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/package-info.java
new file mode 100644
index 0000000..a1c10c9
--- /dev/null
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Query provider based on an Elasticsearch2 DB.
+ */
+@PackageMarker
+package org.apache.calcite.adapter.elasticsearch2;
+
+import org.apache.calcite.avatica.util.PackageMarker;
+
+// End package-info.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch2/src/test/java/org/apache/calcite/test/Elasticsearch2AdapterIT.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/Elasticsearch2AdapterIT.java b/elasticsearch2/src/test/java/org/apache/calcite/test/Elasticsearch2AdapterIT.java
new file mode 100644
index 0000000..4e0c2b6
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/test/Elasticsearch2AdapterIT.java
@@ -0,0 +1,270 @@
+/*
+ * 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 org.apache.calcite.util.Util;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Test;
+
+import java.util.List;
+import javax.annotation.Nullable;
+
+/**
+ * Tests for the {@code org.apache.calcite.adapter.elasticsearch2} package.
+ *
+ * <p>Before calling this test, you need to populate Elasticsearch, as follows:
+ *
+ * <blockquote><code>
+ * git clone https://github.com/vlsi/calcite-test-dataset<br>
+ * cd calcite-test-dataset<br>
+ * mvn install
+ * </code></blockquote>
+ *
+ * <p>This will create a virtual machine with Elasticsearch and the "zips" test
+ * dataset.
+ */
+public class Elasticsearch2AdapterIT {
+ /**
+ * Whether to run Elasticsearch tests. Enabled by default, however test is only
+ * included if "it" profile is activated ({@code -Pit}). To disable,
+ * specify {@code -Dcalcite.test.elasticsearch=false} on the Java command line.
+ */
+ private static final boolean ENABLED = Util.getBooleanProperty("calcite.test.elasticsearch",
+ true);
+
+ /** Connection factory based on the "zips-es" model. */
+ private static final ImmutableMap<String, String> ZIPS = ImmutableMap.of("model",
+ Elasticsearch2AdapterIT.class.getResource("/elasticsearch-zips-model.json").getPath());
+
+ /** Whether to run this test. */
+ private boolean enabled() {
+ return ENABLED;
+ }
+
+ /** Returns a function that checks that a particular Elasticsearch pipeline is
+ * generated to implement a query. */
+ private 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;
+ }
+ };
+ }
+
+ @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=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .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.that()
+ .with(ZIPS)
+ .query(sql)
+ .returnsUnordered("state=AK; id=99503",
+ "state=AK; id=99504",
+ "state=AK; id=99505")
+ .queryContains(
+ elasticsearchChecker(
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}",
+ "\"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.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(
+ "\"from\": 2",
+ "\"size\": 3",
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}"));
+ }
+
+ @Test public void testLimit() {
+ final String sql = "select \"state\", \"id\" from zips\n"
+ + "fetch next 3 rows only";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(
+ "\"size\": 3",
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}"));
+ }
+
+ @Test public void testFilterSort() {
+ final String sql = "select * from zips\n"
+ + "where \"city\" = 'SPRINGFIELD' 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, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'SPRINGFIELD'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
+ + " ElasticsearchTableScan(table=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .returnsOrdered(
+ "city=SPRINGFIELD; longitude=-92.54567; latitude=35.274879; pop=752; state=AR; id=72157",
+ "city=SPRINGFIELD; longitude=-102.617322; latitude=37.406727; pop=1992; state=CO; id=81073",
+ "city=SPRINGFIELD; longitude=-90.577479; latitude=30.415738; pop=5597; state=LA; id=70462",
+ "city=SPRINGFIELD; longitude=-123.015259; latitude=44.06106; pop=32384; state=OR; id=97477",
+ "city=SPRINGFIELD; longitude=-122.917108; latitude=44.056056; pop=27521; state=OR; id=97478")
+ .queryContains(
+ elasticsearchChecker("\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"city\":\"springfield\"}},{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}",
+ "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterSortDesc() {
+ final String sql = "select * from zips\n"
+ + "where \"pop\" BETWEEN 20000 AND 20100\n"
+ + "order by \"state\" desc, \"pop\"";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .limit(4)
+ .returnsOrdered(
+ "city=SHERIDAN; longitude=-106.964795; latitude=44.78486; pop=20025; state=WY; id=82801",
+ "city=MOUNTLAKE TERRAC; longitude=-122.304036; latitude=47.793061; pop=20059; state=WA; id=98043",
+ "city=FALMOUTH; longitude=-77.404537; latitude=38.314557; pop=20039; state=VA; id=22405",
+ "city=FORT WORTH; longitude=-97.318409; latitude=32.725551; pop=20012; state=TX; id=76104");
+ }
+
+ @Test public void testFilterRedundant() {
+ final String sql = "select * from zips\n"
+ + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(""
+ + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"state\":\"ok\"}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}"));
+ }
+
+ @Test public void testInPlan() {
+ final String[] searches = {
+ "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
+ + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":20012}}]}},{\"bool\":{\"must\":[{\"term\":"
+ + "{\"pop\":15590}}]}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}"
+ };
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select * from zips where \"pop\" in (20012, 15590)")
+ .returnsUnordered(
+ "city=COVINA; longitude=-117.884285; latitude=34.08596; pop=15590; state=CA; id=91723",
+ "city=ARLINGTON; longitude=-97.091987; latitude=32.654752; pop=15590; state=TX; id=76018",
+ "city=CROFTON; longitude=-76.680166; latitude=39.011163; pop=15590; state=MD; id=21114",
+ "city=FORT WORTH; longitude=-97.318409; latitude=32.725551; pop=20012; state=TX; id=76104",
+ "city=DINUBA; longitude=-119.39087; latitude=36.534931; pop=20012; state=CA; id=93618")
+ .queryContains(elasticsearchChecker(searches));
+ }
+
+ @Test public void testZips() {
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .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.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .limit(2)
+ .returnsUnordered("state=AK; city=ELMENDORF AFB; zero=0",
+ "state=AK; city=EIELSON AFB; zero=0")
+ .queryContains(
+ elasticsearchChecker("\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]",
+ "\"fields\" : [\"state\", \"city\"], \"script_fields\": {\"zero\":{\"script\": \"0\"}}"));
+ }
+
+ @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=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
+ .limit(2)
+ .returnsUnordered("state=CA; city=LOS ANGELES",
+ "state=CA; city=LOS ANGELES")
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterReversed() {
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where 'WI' < \"state\"")
+ .limit(2)
+ .returnsUnordered("state=WV; city=WELCH",
+ "state=WV; city=HANOVER");
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where \"state\" > 'WI'")
+ .limit(2)
+ .returnsUnordered("state=WV; city=WELCH",
+ "state=WV; city=HANOVER");
+ }
+}
+
+// End Elasticsearch2AdapterIT.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch2/src/test/resources/elasticsearch-zips-model.json
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/resources/elasticsearch-zips-model.json b/elasticsearch2/src/test/resources/elasticsearch-zips-model.json
new file mode 100644
index 0000000..6c00a9c
--- /dev/null
+++ b/elasticsearch2/src/test/resources/elasticsearch-zips-model.json
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+{
+ "version": "1.0",
+ "defaultSchema": "elasticsearch",
+ "schemas": [
+ {
+ "type": "custom",
+ "name": "elasticsearch_raw",
+ "factory": "org.apache.calcite.adapter.elasticsearch2.Elasticsearch2SchemaFactory",
+ "operand": {
+ "coordinates": "{'127.0.0.1': 9300}",
+ "userConfig": "{'bulk.flush.max.actions': 10, 'bulk.flush.max.size.mb': 1}",
+ "index": "usa"
+ }
+ },
+ {
+ "name": "elasticsearch",
+ "tables": [
+ {
+ "name": "ZIPS",
+ "type": "view",
+ "sql": [
+ "select cast(_MAP['city'] AS varchar(20)) AS \"city\",\n",
+ " 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\",\n",
+ " cast(_MAP['state'] AS varchar(2)) AS \"state\",\n",
+ " cast(_MAP['id'] AS varchar(5)) AS \"id\"\n",
+ "from \"elasticsearch_raw\".\"zips\""
+ ]
+ }
+ ]
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch2/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/resources/log4j.properties b/elasticsearch2/src/test/resources/log4j.properties
new file mode 100644
index 0000000..834e2db
--- /dev/null
+++ b/elasticsearch2/src/test/resources/log4j.properties
@@ -0,0 +1,24 @@
+# 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.
+
+# Root logger is configured at INFO and is sent to A1
+log4j.rootLogger=INFO, A1
+
+# A1 goes to the console
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# Set the pattern for each log message
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p - %m%n
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/pom.xml
----------------------------------------------------------------------
diff --git a/elasticsearch5/pom.xml b/elasticsearch5/pom.xml
new file mode 100644
index 0000000..a599bac
--- /dev/null
+++ b/elasticsearch5/pom.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite</artifactId>
+ <version>1.14.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>calcite-elasticsearch5</artifactId>
+ <packaging>jar</packaging>
+ <version>1.14.0-SNAPSHOT</version>
+ <name>Calcite Elasticsearch5</name>
+ <description>Elasticsearch5 adapter for Calcite</description>
+
+ <properties>
+ <top.dir>${project.basedir}/..</top.dir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-core</artifactId>
+ <type>jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-core</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.calcite</groupId>
+ <artifactId>calcite-linq4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.elasticsearch.client</groupId>
+ <artifactId>transport</artifactId>
+ <version>${elasticsearch5-java-driver.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.elasticsearch</groupId>
+ <artifactId>elasticsearch</artifactId>
+ <version>${elasticsearch5-java-driver.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.carrotsearch</groupId>
+ <artifactId>hppc</artifactId>
+ <version>${hppc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>jsr305</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>${maven-dependency-plugin.version}</version>
+ <executions>
+ <execution>
+ <id>analyze</id>
+ <goals>
+ <goal>analyze-only</goal>
+ </goals>
+ <configuration>
+ <failOnWarning>true</failOnWarning>
+ <!-- ignore "unused but declared" warnings -->
+ <ignoredUnusedDeclaredDependencies>
+ <ignoredUnusedDeclaredDependency>org.apache.calcite.avatica:avatica</ignoredUnusedDeclaredDependency>
+ <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-api</ignoredUnusedDeclaredDependency>
+ <ignoredUnusedDeclaredDependency>org.slf4j:slf4j-log4j12</ignoredUnusedDeclaredDependency>
+ </ignoredUnusedDeclaredDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ </plugin>
+ <!-- Parent module has the same plugin and does the work of
+ generating -sources.jar for each project. But without the
+ plugin declared here, IDEs don't know the sources are
+ available. -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ <goal>test-jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.java b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.java
new file mode 100644
index 0000000..262058a
--- /dev/null
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.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.elasticsearch5;
+
+import org.apache.calcite.avatica.util.DateTimeUtils;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.function.Function1;
+import org.apache.calcite.linq4j.tree.Primitive;
+
+import org.elasticsearch.search.SearchHit;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Enumerator that reads from an Elasticsearch type.
+ */
+public class Elasticsearch5Enumerator implements Enumerator<Object> {
+ private final Iterator<SearchHit> cursor;
+ private final Function1<SearchHit, Object> getter;
+ private Object current;
+
+ /**
+ * Creates an Elasticsearch5Enumerator.
+ *
+ * @param cursor Iterator over Elasticsearch {@link SearchHit} objects
+ * @param getter Converts an object into a list of fields
+ */
+ public Elasticsearch5Enumerator(Iterator<SearchHit> cursor,
+ Function1<SearchHit, Object> getter) {
+ this.cursor = cursor;
+ this.getter = getter;
+ }
+
+ public Object current() {
+ return current;
+ }
+
+ public boolean moveNext() {
+ if (cursor.hasNext()) {
+ SearchHit map = cursor.next();
+ current = getter.apply(map);
+ return true;
+ } else {
+ current = null;
+ return false;
+ }
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void close() {
+ // nothing to do
+ }
+
+ private static Function1<SearchHit, Map> mapGetter() {
+ return new Function1<SearchHit, Map>() {
+ public Map apply(SearchHit searchHitFields) {
+ return (Map) searchHitFields.getFields();
+ }
+ };
+ }
+
+ private static Function1<SearchHit, Object> singletonGetter(final String fieldName,
+ final Class fieldClass) {
+ return new Function1<SearchHit, Object>() {
+ public Object apply(SearchHit searchHitFields) {
+ if (searchHitFields.getFields().isEmpty()) {
+ return convert(searchHitFields.getSource(), fieldClass);
+ } else {
+ return convert(searchHitFields.getFields(), fieldClass);
+ }
+ }
+ };
+ }
+
+ /**
+ * Function that extracts a given set of fields from {@link SearchHit}
+ * objects.
+ *
+ * @param fields List of fields to project
+ */
+ private static Function1<SearchHit, Object[]> listGetter(
+ final List<Map.Entry<String, Class>> fields) {
+ return new Function1<SearchHit, Object[]>() {
+ public Object[] apply(SearchHit searchHitFields) {
+ Object[] objects = new Object[fields.size()];
+ for (int i = 0; i < fields.size(); i++) {
+ final Map.Entry<String, Class> field = fields.get(i);
+ final String name = field.getKey();
+ if (searchHitFields.getFields().isEmpty()) {
+ objects[i] = convert(searchHitFields.getSource().get(name),
+ field.getValue());
+ } else {
+ objects[i] = convert(searchHitFields.getField(name).getValue(),
+ field.getValue());
+ }
+ }
+ return objects;
+ }
+ };
+ }
+
+ static Function1<SearchHit, Object> getter(List<Map.Entry<String, Class>> fields) {
+ //noinspection unchecked
+ return fields == null
+ ? (Function1) mapGetter()
+ : fields.size() == 1
+ ? singletonGetter(fields.get(0).getKey(), fields.get(0).getValue())
+ : (Function1) listGetter(fields);
+ }
+
+ private static Object convert(Object o, Class clazz) {
+ if (o == null) {
+ return null;
+ }
+ Primitive primitive = Primitive.of(clazz);
+ if (primitive != null) {
+ clazz = primitive.boxClass;
+ } else {
+ primitive = Primitive.ofBox(clazz);
+ }
+ if (clazz.isInstance(o)) {
+ return o;
+ }
+ if (o instanceof Date && primitive != null) {
+ o = ((Date) o).getTime() / DateTimeUtils.MILLIS_PER_DAY;
+ }
+ if (o instanceof Number && primitive != null) {
+ return primitive.number((Number) o);
+ }
+ return o;
+ }
+}
+
+// End Elasticsearch5Enumerator.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java
new file mode 100644
index 0000000..6e16f2f
--- /dev/null
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java
@@ -0,0 +1,138 @@
+/*
+ * 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.adapter.elasticsearch.ElasticsearchSchema;
+import org.apache.calcite.schema.Table;
+import org.apache.calcite.schema.impl.AbstractSchema;
+
+import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
+import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
+import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.cluster.metadata.MappingMetaData;
+import org.elasticsearch.cluster.node.DiscoveryNode;
+import org.elasticsearch.common.collect.ImmutableOpenMap;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.transport.client.PreBuiltTransportClient;
+
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Schema mapped onto an index of ELASTICSEARCH types.
+ *
+ * <p>Each table in the schema is an ELASTICSEARCH type in that index.
+ */
+public class Elasticsearch5Schema extends AbstractSchema
+ implements ElasticsearchSchema {
+ final String index;
+
+ private transient Client client;
+
+ /**
+ * Creates an Elasticsearch5 schema.
+ *
+ * @param coordinates Map of Elasticsearch node locations (host, port)
+ * @param userConfig Map of user-specified configurations
+ * @param indexName Elasticsearch database name, e.g. "usa".
+ */
+ Elasticsearch5Schema(Map<String, Integer> coordinates,
+ Map<String, String> userConfig, String indexName) {
+ super();
+
+ final List<InetSocketAddress> transportAddresses = new ArrayList<>();
+ for (Map.Entry<String, Integer> coordinate: coordinates.entrySet()) {
+ transportAddresses.add(
+ new InetSocketAddress(coordinate.getKey(), coordinate.getValue()));
+ }
+
+ open(transportAddresses, userConfig);
+
+ if (client != null) {
+ final String[] indices = client.admin().indices()
+ .getIndex(new GetIndexRequest().indices(indexName))
+ .actionGet().getIndices();
+ if (indices.length == 1) {
+ index = indices[0];
+ } else {
+ index = null;
+ }
+ } else {
+ index = null;
+ }
+ }
+
+ @Override protected Map<String, Table> getTableMap() {
+ final ImmutableMap.Builder<String, Table> builder = ImmutableMap.builder();
+
+ try {
+ final GetMappingsResponse response = client.admin().indices()
+ .getMappings(new GetMappingsRequest().indices(index))
+ .get();
+ ImmutableOpenMap<String, MappingMetaData> mapping =
+ response.getMappings().get(index);
+ for (ObjectObjectCursor<String, MappingMetaData> c : mapping) {
+ builder.put(c.key, new Elasticsearch5Table(client, index, c.key));
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return builder.build();
+ }
+
+ private void open(List<InetSocketAddress> transportAddresses,
+ Map<String, String> userConfig) {
+ final List<TransportAddress> transportNodes = new ArrayList<>(transportAddresses.size());
+ for (InetSocketAddress address : transportAddresses) {
+ transportNodes.add(new InetSocketTransportAddress(address));
+ }
+
+ Settings settings = Settings.builder().put(userConfig).build();
+
+ final TransportClient transportClient = new PreBuiltTransportClient(settings);
+ for (TransportAddress transport : transportNodes) {
+ transportClient.addTransportAddress(transport);
+ }
+
+ final List<DiscoveryNode> nodes =
+ ImmutableList.copyOf(transportClient.connectedNodes());
+ if (nodes.isEmpty()) {
+ throw new RuntimeException("Cannot connect to any elasticsearch nodes");
+ }
+
+ client = transportClient;
+ }
+
+ @Override public String getIndex() {
+ return index;
+ }
+}
+
+// End Elasticsearch5Schema.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5SchemaFactory.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5SchemaFactory.java b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5SchemaFactory.java
new file mode 100644
index 0000000..b573d37
--- /dev/null
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5SchemaFactory.java
@@ -0,0 +1,63 @@
+/*
+ * 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.schema.Schema;
+import org.apache.calcite.schema.SchemaFactory;
+import org.apache.calcite.schema.SchemaPlus;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Factory that creates an {@link Elasticsearch5Schema}.
+ *
+ * <p>Allows a custom schema to be included in a model.json file.
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class Elasticsearch5SchemaFactory implements SchemaFactory {
+
+ public Elasticsearch5SchemaFactory() {
+ }
+
+ @Override public Schema create(SchemaPlus parentSchema, String name,
+ Map<String, Object> operand) {
+ final Map map = (Map) operand;
+
+ final ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+
+ try {
+ final Map<String, Integer> coordinates =
+ mapper.readValue((String) map.get("coordinates"),
+ new TypeReference<Map<String, Integer>>() { });
+ final Map<String, String> userConfig =
+ mapper.readValue((String) map.get("userConfig"),
+ new TypeReference<Map<String, String>>() { });
+ final String index = (String) map.get("index");
+ return new Elasticsearch5Schema(coordinates, userConfig, index);
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot parse values from json", e);
+ }
+ }
+}
+
+// End Elasticsearch5SchemaFactory.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java
new file mode 100644
index 0000000..175e3cc
--- /dev/null
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java
@@ -0,0 +1,86 @@
+/*
+ * 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.adapter.elasticsearch.AbstractElasticsearchTable;
+import org.apache.calcite.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.function.Function1;
+
+import org.apache.calcite.util.Util;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.common.xcontent.XContent;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+import org.elasticsearch.index.query.QueryParseContext;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Table based on an Elasticsearch5 type.
+ */
+public class Elasticsearch5Table extends AbstractElasticsearchTable {
+ private final Client client;
+
+ /**
+ * Creates an Elasticsearch5Table.
+ */
+ public Elasticsearch5Table(Client client, String indexName, String typeName) {
+ super(indexName, typeName);
+ this.client = client;
+ }
+
+ @Override protected Enumerable<Object> find(String index, List<String> ops,
+ List<Map.Entry<String, Class>> fields) {
+ final String dbName = index;
+
+ final SearchSourceBuilder searchSourceBuilder;
+ if (ops.isEmpty()) {
+ searchSourceBuilder = new SearchSourceBuilder();
+ } else {
+ String queryString = "{" + Util.toString(ops, "", ", ", "") + "}";
+ NamedXContentRegistry xContentRegistry = NamedXContentRegistry.EMPTY;
+ XContent xContent = JsonXContent.jsonXContent;
+ try (XContentParser parser = xContent.createParser(xContentRegistry, queryString)) {
+ final QueryParseContext queryParseContext = new QueryParseContext(parser);
+ searchSourceBuilder = SearchSourceBuilder.fromXContent(queryParseContext);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ final Function1<SearchHit, Object> getter = Elasticsearch5Enumerator.getter(fields);
+
+ return new AbstractEnumerable<Object>() {
+ public Enumerator<Object> enumerator() {
+ final Iterator<SearchHit> cursor = client.prepareSearch(dbName).setTypes(typeName)
+ .setSource(searchSourceBuilder)
+ .execute().actionGet().getHits().iterator();
+ return new Elasticsearch5Enumerator(cursor, getter);
+ }
+ };
+ }
+}
+
+// End Elasticsearch5Table.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/package-info.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/package-info.java b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/package-info.java
new file mode 100644
index 0000000..70c4695
--- /dev/null
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Query provider based on an Elasticsearch5 DB.
+ */
+@PackageMarker
+package org.apache.calcite.adapter.elasticsearch5;
+
+import org.apache.calcite.avatica.util.PackageMarker;
+
+// End package-info.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/test/java/org/apache/calcite/test/Elasticsearch5AdapterIT.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/test/Elasticsearch5AdapterIT.java b/elasticsearch5/src/test/java/org/apache/calcite/test/Elasticsearch5AdapterIT.java
new file mode 100644
index 0000000..1cf52fe
--- /dev/null
+++ b/elasticsearch5/src/test/java/org/apache/calcite/test/Elasticsearch5AdapterIT.java
@@ -0,0 +1,270 @@
+/*
+ * 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 org.apache.calcite.util.Util;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+
+import org.junit.Test;
+
+import java.util.List;
+import javax.annotation.Nullable;
+
+/**
+ * Tests for the {@code org.apache.calcite.adapter.elasticsearch} package.
+ *
+ * <p>Before calling this test, you need to populate Elasticsearch, as follows:
+ *
+ * <blockquote><code>
+ * git clone https://github.com/vlsi/calcite-test-dataset<br>
+ * cd calcite-test-dataset<br>
+ * mvn install
+ * </code></blockquote>
+ *
+ * <p>This will create a virtual machine with Elasticsearch and the "zips" test
+ * dataset.
+ */
+public class Elasticsearch5AdapterIT {
+ /**
+ * Whether to run Elasticsearch tests. Enabled by default, however test is only
+ * included if "it" profile is activated ({@code -Pit}). To disable,
+ * specify {@code -Dcalcite.test.elasticsearch=false} on the Java command line.
+ */
+ private static final boolean ENABLED = Util.getBooleanProperty("calcite.test.elasticsearch",
+ true);
+
+ /** Connection factory based on the "zips-es" model. */
+ private static final ImmutableMap<String, String> ZIPS = ImmutableMap.of("model",
+ Elasticsearch5AdapterIT.class.getResource("/elasticsearch-zips-model.json").getPath());
+
+ /** Whether to run this test. */
+ private boolean enabled() {
+ return ENABLED;
+ }
+
+ /** Returns a function that checks that a particular Elasticsearch pipeline is
+ * generated to implement a query. */
+ private 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;
+ }
+ };
+ }
+
+ @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=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .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.that()
+ .with(ZIPS)
+ .query(sql)
+ .returnsUnordered("state=AK; id=99503",
+ "state=AK; id=99504",
+ "state=AK; id=99505")
+ .queryContains(
+ elasticsearchChecker(
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}",
+ "\"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.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(
+ "\"from\": 2",
+ "\"size\": 3",
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}"));
+ }
+
+ @Test public void testLimit() {
+ final String sql = "select \"state\", \"id\" from zips\n"
+ + "fetch next 3 rows only";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(
+ "\"size\": 3",
+ "\"fields\" : [\"state\", \"id\"], \"script_fields\": {}"));
+ }
+
+ @Test public void testFilterSort() {
+ final String sql = "select * from zips\n"
+ + "where \"city\" = 'SPRINGFIELD' 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, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'SPRINGFIELD'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
+ + " ElasticsearchTableScan(table=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .returnsOrdered(
+ "city=SPRINGFIELD; longitude=-92.54567; latitude=35.274879; pop=752; state=AR; id=72157",
+ "city=SPRINGFIELD; longitude=-102.617322; latitude=37.406727; pop=1992; state=CO; id=81073",
+ "city=SPRINGFIELD; longitude=-90.577479; latitude=30.415738; pop=5597; state=LA; id=70462",
+ "city=SPRINGFIELD; longitude=-123.015259; latitude=44.06106; pop=32384; state=OR; id=97477",
+ "city=SPRINGFIELD; longitude=-122.917108; latitude=44.056056; pop=27521; state=OR; id=97478")
+ .queryContains(
+ elasticsearchChecker("\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"city\":\"springfield\"}},{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}",
+ "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterSortDesc() {
+ final String sql = "select * from zips\n"
+ + "where \"pop\" BETWEEN 20000 AND 20100\n"
+ + "order by \"state\" desc, \"pop\"";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .limit(4)
+ .returnsOrdered(
+ "city=SHERIDAN; longitude=-106.964795; latitude=44.78486; pop=20025; state=WY; id=82801",
+ "city=MOUNTLAKE TERRAC; longitude=-122.304036; latitude=47.793061; pop=20059; state=WA; id=98043",
+ "city=FALMOUTH; longitude=-77.404537; latitude=38.314557; pop=20039; state=VA; id=22405",
+ "city=FORT WORTH; longitude=-97.318409; latitude=32.725551; pop=20012; state=TX; id=76104");
+ }
+
+ @Test public void testFilterRedundant() {
+ final String sql = "select * from zips\n"
+ + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .runs()
+ .queryContains(
+ elasticsearchChecker(""
+ + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+ + "{\"must\":[{\"term\":{\"state\":\"ok\"}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}"));
+ }
+
+ @Test public void testInPlan() {
+ final String[] searches = {
+ "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
+ + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":20012}}]}},{\"bool\":{\"must\":[{\"term\":"
+ + "{\"pop\":15590}}]}}]}}}}",
+ "\"fields\" : [\"city\", \"pop\", \"state\", \"id\"], \"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, \"latitude\":{\"script\":\"_source.loc[1]\"}}"
+ };
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select * from zips where \"pop\" in (20012, 15590)")
+ .returnsUnordered(
+ "city=COVINA; longitude=-117.884285; latitude=34.08596; pop=15590; state=CA; id=91723",
+ "city=ARLINGTON; longitude=-97.091987; latitude=32.654752; pop=15590; state=TX; id=76018",
+ "city=CROFTON; longitude=-76.680166; latitude=39.011163; pop=15590; state=MD; id=21114",
+ "city=FORT WORTH; longitude=-97.318409; latitude=32.725551; pop=20012; state=TX; id=76104",
+ "city=DINUBA; longitude=-119.39087; latitude=36.534931; pop=20012; state=CA; id=93618")
+ .queryContains(elasticsearchChecker(searches));
+ }
+
+ @Test public void testZips() {
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .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.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query(sql)
+ .limit(2)
+ .returnsUnordered("state=AK; city=ELMENDORF AFB; zero=0",
+ "state=AK; city=EIELSON AFB; zero=0")
+ .queryContains(
+ elasticsearchChecker("\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]",
+ "\"fields\" : [\"state\", \"city\"], \"script_fields\": {\"zero\":{\"script\": \"0\"}}"));
+ }
+
+ @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=[[elasticsearch_raw, zips]])";
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
+ .limit(2)
+ .returnsUnordered("state=CA; city=LOS ANGELES",
+ "state=CA; city=LOS ANGELES")
+ .explainContains(explain);
+ }
+
+ @Test public void testFilterReversed() {
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where 'WI' < \"state\"")
+ .limit(2)
+ .returnsUnordered("state=WV; city=WELCH",
+ "state=WV; city=HANOVER");
+ CalciteAssert.that()
+ .enable(enabled())
+ .with(ZIPS)
+ .query("select \"state\", \"city\" from zips where \"state\" > 'WI'")
+ .limit(2)
+ .returnsUnordered("state=WV; city=WELCH",
+ "state=WV; city=HANOVER");
+ }
+}
+
+// End Elasticsearch5AdapterIT.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/test/resources/elasticsearch-zips-model.json
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/resources/elasticsearch-zips-model.json b/elasticsearch5/src/test/resources/elasticsearch-zips-model.json
new file mode 100644
index 0000000..626923e
--- /dev/null
+++ b/elasticsearch5/src/test/resources/elasticsearch-zips-model.json
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+{
+ "version": "1.0",
+ "defaultSchema": "elasticsearch",
+ "schemas": [
+ {
+ "type": "custom",
+ "name": "elasticsearch_raw",
+ "factory": "org.apache.calcite.adapter.elasticsearch5.Elasticsearch5SchemaFactory",
+ "operand": {
+ "coordinates": "{'127.0.0.1': 9300}",
+ "userConfig": "{'bulk.flush.max.actions': 10, 'bulk.flush.max.size.mb': 1}",
+ "index": "usa"
+ }
+ },
+ {
+ "name": "elasticsearch",
+ "tables": [
+ {
+ "name": "ZIPS",
+ "type": "view",
+ "sql": [
+ "select cast(_MAP['city'] AS varchar(20)) AS \"city\",\n",
+ " 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\",\n",
+ " cast(_MAP['state'] AS varchar(2)) AS \"state\",\n",
+ " cast(_MAP['id'] AS varchar(5)) AS \"id\"\n",
+ "from \"elasticsearch_raw\".\"zips\""
+ ]
+ }
+ ]
+ }
+ ]
+}
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/elasticsearch5/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/resources/log4j.properties b/elasticsearch5/src/test/resources/log4j.properties
new file mode 100644
index 0000000..834e2db
--- /dev/null
+++ b/elasticsearch5/src/test/resources/log4j.properties
@@ -0,0 +1,24 @@
+# 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.
+
+# Root logger is configured at INFO and is sent to A1
+log4j.rootLogger=INFO, A1
+
+# A1 goes to the console
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# Set the pattern for each log message
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p - %m%n
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 3372f99..a8f4df3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,7 @@ limitations under the License.
<commons-lang3.version>3.2</commons-lang3.version>
<commons-logging.version>1.1.3</commons-logging.version>
<elasticsearch-java-driver.version>2.3.2</elasticsearch-java-driver.version>
+ <elasticsearch5-java-driver.version>5.5.2</elasticsearch5-java-driver.version>
<findbugs.version>3.0.1</findbugs.version>
<fmpp-maven-plugin.version>1.0</fmpp-maven-plugin.version>
<foodmart-data-hsqldb.version>0.3</foodmart-data-hsqldb.version>
@@ -139,7 +140,8 @@ limitations under the License.
<module>cassandra</module>
<module>core</module>
<module>druid</module>
- <module>elasticsearch</module>
+ <module>elasticsearch2</module>
+ <module>elasticsearch5</module>
<module>example</module>
<module>file</module>
<module>linq4j</module>
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/site/_docs/adapter.md
----------------------------------------------------------------------
diff --git a/site/_docs/adapter.md b/site/_docs/adapter.md
index ef8e761..3987804 100644
--- a/site/_docs/adapter.md
+++ b/site/_docs/adapter.md
@@ -30,7 +30,10 @@ presenting the data as tables within a schema.
* [Cassandra adapter](cassandra_adapter.html) (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/cassandra/package-summary.html">calcite-cassandra</a>)
* CSV adapter (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/csv/package-summary.html">example/csv</a>)
* [Druid adapter](druid_adapter.html) (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/druid/package-summary.html">calcite-druid</a>)
-* [Elasticsearch adapter](elasticsearch_adapter.html) (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/elasticsearch/package-summary.html">calcite-elasticsearch</a>)
+* [Elasticsearch adapter](elasticsearch_adapter.html)
+ (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/elasticsearch2/package-summary.html">calcite-elasticsearch2</a>
+ and
+ <a href="{{ site.apiRoot }}/org/apache/calcite/adapter/elasticsearch5/package-summary.html">calcite-elasticsearch5</a>)
* [File adapter](file_adapter.html) (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/file/package-summary.html">calcite-file</a>)
* JDBC adapter (part of <a href="{{ site.apiRoot }}/org/apache/calcite/adapter/jdbc/package-summary.html">calcite-core</a>)
* MongoDB adapter (<a href="{{ site.apiRoot }}/org/apache/calcite/adapter/mongodb/package-summary.html">calcite-mongodb</a>)
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/site/_docs/elasticsearch_adapter.md
----------------------------------------------------------------------
diff --git a/site/_docs/elasticsearch_adapter.md b/site/_docs/elasticsearch_adapter.md
index d87d9e3..21f2459 100644
--- a/site/_docs/elasticsearch_adapter.md
+++ b/site/_docs/elasticsearch_adapter.md
@@ -47,7 +47,7 @@ A basic example of a model file is given below:
{
"type": "custom",
"name": "elasticsearch",
- "factory": "org.apache.calcite.adapter.elasticsearch.ElasticsearchSchemaFactory",
+ "factory": "org.apache.calcite.adapter.elasticsearch2.Elasticsearch2SchemaFactory",
"operand": {
"coordinates": "{'127.0.0.1': 9300}",
"userConfig": "{'bulk.flush.max.actions': 10, 'bulk.flush.max.size.mb': 1}",
@@ -58,6 +58,9 @@ A basic example of a model file is given below:
}
{% endhighlight %}
+This adapter is targeted for Elasticsearch 2.x. To use Calcite with Elasticsearch 5.x+ you can use the factory
+of the adapter targeted for Elasticsearch 5.x: `org.apache.calcite.adapter.elasticsearch5.Elasticsearch5SchemaFactory`
+
Assuming this file is stored as `model.json`, you can connect to
Elasticsearch via [`sqlline`](https://github.com/julianhyde/sqlline) as
follows:
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/sqlline
----------------------------------------------------------------------
diff --git a/sqlline b/sqlline
index 6e4b4e9..b0fc489 100755
--- a/sqlline
+++ b/sqlline
@@ -37,7 +37,7 @@ if [ ! -f target/fullclasspath.txt ]; then
fi
CP=
-for module in core cassandra druid elasticsearch file mongodb spark splunk example/csv example/function; do
+for module in core cassandra druid elasticsearch2 elasticsearch5 file mongodb spark splunk example/csv example/function; do
CP=${CP}${module}/target/classes:
CP=${CP}${module}/target/test-classes:
done
http://git-wip-us.apache.org/repos/asf/calcite/blob/e1525926/sqlline.bat
----------------------------------------------------------------------
diff --git a/sqlline.bat b/sqlline.bat
index 99548de..53f7159 100644
--- a/sqlline.bat
+++ b/sqlline.bat
@@ -23,6 +23,6 @@
:: Copy dependency jars on first call. (To force jar refresh, remove target\dependencies)
if not exist target\dependencies (call mvn -B dependency:copy-dependencies -DoverWriteReleases=false -DoverWriteSnapshots=false -DoverWriteIfNewer=true -DoutputDirectory=target\dependencies)
-java -Xmx1G -cp ".\target\dependencies\*;core\target\dependencies\*;cassandra\target\dependencies\*;druid\target\dependencies\*;elasticsearch\target\dependencies\*;file\target\dependencies\*;mongodb\target\dependencies\*;spark\target\dependencies\*;splunk\target\dependencies\*" sqlline.SqlLine --verbose=true %*
+java -Xmx1G -cp ".\target\dependencies\*;core\target\dependencies\*;cassandra\target\dependencies\*;druid\target\dependencies\*;elasticsearch2\target\dependencies\*;elasticsearch5\target\dependencies\*;file\target\dependencies\*;mongodb\target\dependencies\*;spark\target\dependencies\*;splunk\target\dependencies\*" sqlline.SqlLine --verbose=true %*
:: End sqlline.bat