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 2018/07/20 17:41:48 UTC

[35/53] [abbrv] calcite git commit: [CALCITE-2376] Unify ES2 and ES5 adapters. Migrate to low-level ES rest client as main transport. (Andrei Sereda)

[CALCITE-2376] Unify ES2 and ES5 adapters. Migrate to low-level ES rest client as main transport. (Andrei Sereda)

== Major change to elastic search adapter(s)

1. Combine ES2 and ES5 under single maven module (called elasticsearch). Move shared ES source from core to
separate elasticsearch module.

2. Migrate transport layer to low-level rest client. There are no more heavy core server-side ES dependencies
(like Lucene, Netty etc.) in adapter, just apache http client and apache codecs.
Native Transport client will be removed by the vendor in the next release (ES7-8).

3. Manually parse search results using jackson JSON library (this is already a transitive dependency from core)

== Expected breaking changes for clients:
1. Change class names of Schema and SchemaFactory. They don't contain ES major version number anymore (2, 5, 6 etc.):
   - ElasticsearchSchemaFactory(new) vs Elasticsearch{2|5}SchemaFactory (old)
   - ElasticsearchSchema(new) vs Elasticsearch{2|5}Schema (old)
   - changed package name(s)
This affects existing configurations (especially JSON files)

2. There is a single maven module elasticsearch. elasticsearch2 and elasticsearch5 are removed.
Client will have to manually update their artifact dependencies.

Close apache/calcite#744


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/0204f286
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/0204f286
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/0204f286

Branch: refs/heads/site
Commit: 0204f2860c8c83915c62085a47d42a78a10aac46
Parents: 195414d
Author: Andrei Sereda <an...@nospam.com>
Authored: Tue Jun 26 21:11:06 2018 -0400
Committer: Michael Mior <mm...@uwaterloo.ca>
Committed: Mon Jul 9 12:16:24 2018 -0400

----------------------------------------------------------------------
 .../AbstractElasticsearchTable.java             | 140 -------
 .../elasticsearch/ElasticsearchFilter.java      | 294 --------------
 .../elasticsearch/ElasticsearchMethod.java      |  50 ---
 .../elasticsearch/ElasticsearchProject.java     | 115 ------
 .../adapter/elasticsearch/ElasticsearchRel.java |  58 ---
 .../elasticsearch/ElasticsearchRules.java       | 238 -----------
 .../elasticsearch/ElasticsearchSchema.java      |  33 --
 .../elasticsearch/ElasticsearchSort.java        | 104 -----
 .../elasticsearch/ElasticsearchTableScan.java   |  89 ----
 .../ElasticsearchToEnumerableConverter.java     | 115 ------
 .../ElasticsearchToEnumerableConverterRule.java |  54 ---
 .../MapProjectionFieldVisitor.java              |  42 --
 .../adapter/elasticsearch/package-info.java     |  26 --
 elasticsearch/pom.xml                           | 187 +++++++++
 .../AbstractElasticsearchTable.java             | 145 +++++++
 .../elasticsearch/ElasticsearchEnumerators.java | 111 +++++
 .../elasticsearch/ElasticsearchFilter.java      | 305 ++++++++++++++
 .../elasticsearch/ElasticsearchMethod.java      |  50 +++
 .../elasticsearch/ElasticsearchProject.java     | 115 ++++++
 .../adapter/elasticsearch/ElasticsearchRel.java |  58 +++
 .../elasticsearch/ElasticsearchRules.java       | 240 +++++++++++
 .../elasticsearch/ElasticsearchSchema.java      | 114 ++++++
 .../ElasticsearchSchemaFactory.java             |  95 +++++
 .../ElasticsearchSearchResult.java              | 173 ++++++++
 .../elasticsearch/ElasticsearchSort.java        | 104 +++++
 .../elasticsearch/ElasticsearchTable.java       | 135 +++++++
 .../elasticsearch/ElasticsearchTableScan.java   |  89 ++++
 .../ElasticsearchToEnumerableConverter.java     | 124 ++++++
 .../ElasticsearchToEnumerableConverterRule.java |  54 +++
 .../elasticsearch/ElasticsearchVersion.java     |  58 +++
 .../MapProjectionFieldVisitor.java              |  43 ++
 .../adapter/elasticsearch/package-info.java     |  26 ++
 .../elasticsearch/ElasticSearchAdapterTest.java | 400 ++++++++++++++++++
 .../elasticsearch/ElasticsearchVersionTest.java |  65 +++
 .../EmbeddedElasticsearchNode.java              | 157 +++++++
 .../EmbeddedElasticsearchPolicy.java            | 119 ++++++
 .../calcite/test/ElasticsearchChecker.java      |  44 ++
 elasticsearch/src/test/resources/log4j2.xml     |  36 ++
 elasticsearch/src/test/resources/zips-mini.json | 149 +++++++
 elasticsearch2/pom.xml                          | 150 -------
 .../Elasticsearch2Enumerator.java               | 150 -------
 .../elasticsearch2/Elasticsearch2Schema.java    | 149 -------
 .../Elasticsearch2SchemaFactory.java            |  63 ---
 .../elasticsearch2/Elasticsearch2Table.java     |  77 ----
 .../adapter/elasticsearch2/package-info.java    |  26 --
 .../Elasticsearch2AdapterTest.java              | 398 ------------------
 .../EmbeddedElasticsearchNode.java              | 155 -------
 .../EmbeddedElasticsearchPolicy.java            | 102 -----
 .../calcite/test/Elasticsearch2AdapterIT.java   | 265 ------------
 .../calcite/test/ElasticsearchChecker.java      |  45 ---
 .../src/test/resources/log4j.properties         |  24 --
 .../src/test/resources/zips-mini.json           | 149 -------
 elasticsearch5/pom.xml                          | 180 ---------
 .../Elasticsearch5Enumerator.java               | 147 -------
 .../elasticsearch5/Elasticsearch5Schema.java    | 154 -------
 .../Elasticsearch5SchemaFactory.java            |  63 ---
 .../elasticsearch5/Elasticsearch5Table.java     |  96 -----
 .../adapter/elasticsearch5/package-info.java    |  26 --
 .../Elasticsearch5AdapterTest.java              | 405 -------------------
 .../EmbeddedElasticsearchNode.java              | 162 --------
 .../EmbeddedElasticsearchPolicy.java            | 102 -----
 .../calcite/test/Elasticsearch5AdapterIT.java   | 265 ------------
 .../calcite/test/ElasticsearchChecker.java      |  45 ---
 .../src/test/resources/log4j.properties         |  24 --
 elasticsearch5/src/test/resources/log4j2.xml    |  32 --
 .../src/test/resources/zips-mini.json           | 149 -------
 pom.xml                                         |  21 +-
 67 files changed, 3200 insertions(+), 4978 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
deleted file mode 100644
index 8cc5933..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
+++ /dev/null
@@ -1,140 +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.elasticsearch;
-
-import org.apache.calcite.adapter.java.AbstractQueryableTable;
-import org.apache.calcite.linq4j.Enumerable;
-import org.apache.calcite.linq4j.Enumerator;
-import org.apache.calcite.linq4j.QueryProvider;
-import org.apache.calcite.linq4j.Queryable;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.schema.TranslatableTable;
-import org.apache.calcite.schema.impl.AbstractTableQueryable;
-import org.apache.calcite.sql.type.SqlTypeName;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Table based on an Elasticsearch type.
- */
-public abstract class AbstractElasticsearchTable extends AbstractQueryableTable
-    implements TranslatableTable {
-  protected final String indexName;
-  protected final String typeName;
-
-  /**
-   * Creates an ElasticsearchTable.
-   */
-  public AbstractElasticsearchTable(String indexName, String typeName) {
-    super(Object[].class);
-    this.indexName = indexName;
-    this.typeName = typeName;
-  }
-
-  @Override public String toString() {
-    return "ElasticsearchTable{" + typeName + "}";
-  }
-
-  public RelDataType getRowType(RelDataTypeFactory relDataTypeFactory) {
-    final RelDataType mapType = relDataTypeFactory.createMapType(
-        relDataTypeFactory.createSqlType(SqlTypeName.VARCHAR),
-        relDataTypeFactory.createTypeWithNullability(
-            relDataTypeFactory.createSqlType(SqlTypeName.ANY),
-            true));
-    return relDataTypeFactory.builder().add("_MAP", mapType).build();
-  }
-
-  public <T> Queryable<T> asQueryable(QueryProvider queryProvider, SchemaPlus schema,
-      String tableName) {
-    return new ElasticsearchQueryable<>(queryProvider, schema, this, tableName);
-  }
-
-  public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable relOptTable) {
-    final RelOptCluster cluster = context.getCluster();
-    return new ElasticsearchTableScan(cluster, cluster.traitSetOf(ElasticsearchRel.CONVENTION),
-        relOptTable, this, null);
-  }
-
-  /**
-   * In ES 5.x scripted fields start with {@code params._source.foo} while in ES2.x
-   * {@code _source.foo}. Helper method to build correct query based on runtime version of elastic.
-   *
-   * @see <a href="https://github.com/elastic/elasticsearch/issues/20068">_source variable</a>
-   * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-fields.html">Scripted Fields</a>
-   */
-  protected String scriptedFieldPrefix() {
-    // this is default pattern starting 5.x
-    return "params._source";
-  }
-
-  /** Executes a "find" operation on the underlying type.
-   *
-   * <p>For example,
-   * <code>client.prepareSearch(index).setTypes(type)
-   * .setSource("{\"fields\" : [\"state\"]}")</code></p>
-   *
-   * @param index Elasticsearch index
-   * @param ops List of operations represented as Json strings.
-   * @param fields List of fields to project; or null to return map
-   * @return Enumerator of results
-   */
-  protected abstract Enumerable<Object> find(String index, List<String> ops,
-      List<Map.Entry<String, Class>> fields);
-
-  /**
-   * Implementation of {@link Queryable} based on
-   * a {@link AbstractElasticsearchTable}.
-   *
-   * @param <T> element type
-   */
-  public static class ElasticsearchQueryable<T> extends AbstractTableQueryable<T> {
-    public ElasticsearchQueryable(QueryProvider queryProvider, SchemaPlus schema,
-        AbstractElasticsearchTable table, String tableName) {
-      super(queryProvider, schema, table, tableName);
-    }
-
-    public Enumerator<T> enumerator() {
-      return null;
-    }
-
-    private String getIndex() {
-      return schema.unwrap(ElasticsearchSchema.class).getIndex();
-    }
-
-    private AbstractElasticsearchTable getTable() {
-      return (AbstractElasticsearchTable) table;
-    }
-
-    /** Called via code-generation.
-     *
-     * @see ElasticsearchMethod#ELASTICSEARCH_QUERYABLE_FIND
-     */
-    @SuppressWarnings("UnusedDeclaration")
-    public Enumerable<Object> find(List<String> ops,
-        List<Map.Entry<String, Class>> fields) {
-      return getTable().find(getIndex(), ops, fields);
-    }
-  }
-}
-
-// End AbstractElasticsearchTable.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchFilter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchFilter.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchFilter.java
deleted file mode 100644
index 06b39c0..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchFilter.java
+++ /dev/null
@@ -1,294 +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.elasticsearch;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Filter;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.JsonBuilder;
-import org.apache.calcite.util.Pair;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of a {@link org.apache.calcite.rel.core.Filter}
- * relational expression in Elasticsearch.
- */
-public class ElasticsearchFilter extends Filter implements ElasticsearchRel {
-  public ElasticsearchFilter(RelOptCluster cluster, RelTraitSet traitSet, RelNode child,
-      RexNode condition) {
-    super(cluster, traitSet, child, condition);
-    assert getConvention() == ElasticsearchRel.CONVENTION;
-    assert getConvention() == child.getConvention();
-  }
-
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
-    return super.computeSelfCost(planner, mq).multiplyBy(0.1);
-  }
-
-  @Override public Filter copy(RelTraitSet relTraitSet, RelNode input, RexNode condition) {
-    return new ElasticsearchFilter(getCluster(), relTraitSet, input, condition);
-  }
-
-  @Override public void implement(Implementor implementor) {
-    implementor.visitChild(0, getInput());
-    List<String> fieldNames;
-    if (input instanceof Project) {
-      final List<RexNode> projects = ((Project) input).getProjects();
-      fieldNames = new ArrayList<>(projects.size());
-      for (RexNode project : projects) {
-        String name = project.accept(MapProjectionFieldVisitor.INSTANCE);
-        fieldNames.add(name);
-      }
-    } else {
-      fieldNames = ElasticsearchRules.elasticsearchFieldNames(getRowType());
-    }
-    Translator translator = new Translator(fieldNames);
-    String match = translator.translateMatch(condition);
-    implementor.add(match);
-  }
-
-  /**
-   * Translates {@link RexNode} expressions into Elasticsearch expression strings.
-   */
-  static class Translator {
-    final JsonBuilder builder = new JsonBuilder();
-    final Multimap<String, Pair<String, RexLiteral>> multimap =
-        HashMultimap.create();
-    final Map<String, RexLiteral> eqMap = new LinkedHashMap<>();
-    private final List<String> fieldNames;
-
-    Translator(List<String> fieldNames) {
-      this.fieldNames = fieldNames;
-    }
-
-    private String translateMatch(RexNode condition) {
-      // filter node
-      final Map<String, Object> filterMap = new LinkedHashMap<>();
-      filterMap.put("filter", translateOr(condition));
-
-      // constant_score node
-      final Map<String, Object> map = builder.map();
-      map.put("constant_score", filterMap);
-
-      return "\"query\" : " + builder.toJsonString(map).replaceAll("\\s+", "");
-    }
-
-    private Object translateOr(RexNode condition) {
-      final List<Object> list = new ArrayList<>();
-
-      final List<RexNode> orNodes = RelOptUtil.disjunctions(condition);
-      for (RexNode node : orNodes) {
-        List<Map<String, Object>> andNodes = translateAnd(node);
-
-        if (andNodes.size() > 0) {
-          Map<String, Object> andClause = new HashMap<>();
-          andClause.put("must", andNodes);
-
-          // boolean filters
-          LinkedHashMap<String, Object> filterEvaluator = new LinkedHashMap<>();
-          filterEvaluator.put("bool", andClause);
-          list.add(filterEvaluator);
-        } else {
-          list.add(andNodes.get(0));
-        }
-      }
-
-      if (orNodes.size() > 1) {
-        Map<String, Object> map = builder.map();
-        map.put("should", list);
-
-        // boolean filters
-        LinkedHashMap<String, Object> filterEvaluator = new LinkedHashMap<>();
-        filterEvaluator.put("bool", map);
-        return filterEvaluator;
-      } else {
-        return list.get(0);
-      }
-    }
-
-    private void addPredicate(Map<String, Object> map, String op, Object v) {
-      if (map.containsKey(op) && stronger(op, map.get(op), v)) {
-        return;
-      }
-      map.put(op, v);
-    }
-
-    /**
-     * Translates a condition that may be an AND of other conditions. Gathers
-     * together conditions that apply to the same field.
-     */
-    private List<Map<String, Object>> translateAnd(RexNode node0) {
-      eqMap.clear();
-      multimap.clear();
-      for (RexNode node : RelOptUtil.conjunctions(node0)) {
-        translateMatch2(node);
-      }
-      List<Map<String, Object>> filters = new ArrayList<>();
-      for (Map.Entry<String, RexLiteral> entry : eqMap.entrySet()) {
-        multimap.removeAll(entry.getKey());
-
-        Map<String, Object> filter = new HashMap<>();
-        filter.put(entry.getKey(), literalValue(entry.getValue()));
-
-        Map<String, Object> map = new HashMap<>();
-        map.put("term", filter);
-        filters.add(map);
-      }
-      for (Map.Entry<String, Collection<Pair<String, RexLiteral>>> entry
-          : multimap.asMap().entrySet()) {
-        Map<String, Object> map2 = builder.map();
-
-        Map<String, Object> map = new HashMap<>();
-        for (Pair<String, RexLiteral> s : entry.getValue()) {
-          if (!s.left.equals("not")) {
-            addPredicate(map2, s.left, literalValue(s.right));
-
-            Map<String, Object> filter = new HashMap<>();
-            filter.put(entry.getKey(), map2);
-
-            map.put("range", filter);
-          } else {
-            map2.put(entry.getKey(), literalValue(s.right));
-
-            Map<String, Object> termMap = new HashMap<>();
-            termMap.put("term", map2);
-
-            map.put("not", termMap);
-          }
-        }
-        filters.add(map);
-      }
-      return filters;
-    }
-
-    private boolean stronger(String key, Object v0, Object v1) {
-      if (key.equals("lt") || key.equals("lte")) {
-        if (v0 instanceof Number && v1 instanceof Number) {
-          return ((Number) v0).doubleValue() < ((Number) v1).doubleValue();
-        }
-        if (v0 instanceof String && v1 instanceof String) {
-          return v0.toString().compareTo(v1.toString()) < 0;
-        }
-      }
-      if (key.equals("gt") || key.equals("gte")) {
-        return stronger("lt", v1, v0);
-      }
-      return false;
-    }
-
-    private static Object literalValue(RexLiteral literal) {
-      return literal.getValue2();
-    }
-
-    private Void translateMatch2(RexNode node) {
-      switch (node.getKind()) {
-      case EQUALS:
-        return translateBinary(null, null, (RexCall) node);
-      case LESS_THAN:
-        return translateBinary("lt", "gt", (RexCall) node);
-      case LESS_THAN_OR_EQUAL:
-        return translateBinary("lte", "gte", (RexCall) node);
-      case NOT_EQUALS:
-        return translateBinary("not", "not", (RexCall) node);
-      case GREATER_THAN:
-        return translateBinary("gt", "lt", (RexCall) node);
-      case GREATER_THAN_OR_EQUAL:
-        return translateBinary("gte", "lte", (RexCall) node);
-      default:
-        throw new AssertionError("cannot translate " + node);
-      }
-    }
-
-    /**
-     * Translates a call to a binary operator, reversing arguments if
-     * necessary.
-     */
-    private Void translateBinary(String op, String rop, RexCall call) {
-      final RexNode left = call.operands.get(0);
-      final RexNode right = call.operands.get(1);
-      boolean b = translateBinary2(op, left, right);
-      if (b) {
-        return null;
-      }
-      b = translateBinary2(rop, right, left);
-      if (b) {
-        return null;
-      }
-      throw new AssertionError("cannot translate op " + op + " call " + call);
-    }
-
-    /**
-     * Translates a call to a binary operator. Returns whether successful.
-     */
-    private boolean translateBinary2(String op, RexNode left, RexNode right) {
-      switch (right.getKind()) {
-      case LITERAL:
-        break;
-      default:
-        return false;
-      }
-      final RexLiteral rightLiteral = (RexLiteral) right;
-      switch (left.getKind()) {
-      case INPUT_REF:
-        final RexInputRef left1 = (RexInputRef) left;
-        String name = fieldNames.get(left1.getIndex());
-        translateOp2(op, name, rightLiteral);
-        return true;
-      case CAST:
-        return translateBinary2(op, ((RexCall) left).operands.get(0), right);
-      case OTHER_FUNCTION:
-        String itemName = ElasticsearchRules.isItem((RexCall) left);
-        if (itemName != null) {
-          translateOp2(op, itemName, rightLiteral);
-          return true;
-        }
-        // fall through
-      default:
-        return false;
-      }
-    }
-
-    private void translateOp2(String op, String name, RexLiteral right) {
-      if (op == null) {
-        eqMap.put(name, right);
-      } else {
-        multimap.put(name, Pair.of(op, right));
-      }
-    }
-  }
-}
-
-// End ElasticsearchFilter.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchMethod.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchMethod.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchMethod.java
deleted file mode 100644
index 72753e6..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchMethod.java
+++ /dev/null
@@ -1,50 +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.elasticsearch;
-
-import org.apache.calcite.linq4j.tree.Types;
-
-import com.google.common.collect.ImmutableMap;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * Builtin methods in the Elasticsearch adapter.
- */
-enum ElasticsearchMethod {
-  ELASTICSEARCH_QUERYABLE_FIND(AbstractElasticsearchTable.ElasticsearchQueryable.class,
-      "find", List.class, List.class);
-
-  public final Method method;
-
-  public static final ImmutableMap<Method, ElasticsearchMethod> MAP;
-
-  static {
-    final ImmutableMap.Builder<Method, ElasticsearchMethod> builder = ImmutableMap.builder();
-    for (ElasticsearchMethod value: ElasticsearchMethod.values()) {
-      builder.put(value.method, value);
-    }
-    MAP = builder.build();
-  }
-
-  ElasticsearchMethod(Class clazz, String methodName, Class... argumentTypes) {
-    this.method = Types.lookupMethod(clazz, methodName, argumentTypes);
-  }
-}
-
-// End ElasticsearchMethod.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
deleted file mode 100644
index 63270db..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchProject.java
+++ /dev/null
@@ -1,115 +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.elasticsearch;
-
-import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.Pair;
-
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of {@link org.apache.calcite.rel.core.Project}
- * relational expression in Elasticsearch.
- */
-public class ElasticsearchProject extends Project implements ElasticsearchRel {
-  public ElasticsearchProject(RelOptCluster cluster, RelTraitSet traitSet, RelNode input,
-      List<? extends RexNode> projects, RelDataType rowType) {
-    super(cluster, traitSet, input, projects, rowType);
-    assert getConvention() == ElasticsearchRel.CONVENTION;
-    assert getConvention() == input.getConvention();
-  }
-
-  @Override public Project copy(RelTraitSet relTraitSet, RelNode input, List<RexNode> projects,
-      RelDataType relDataType) {
-    return new ElasticsearchProject(getCluster(), traitSet, input, projects, relDataType);
-  }
-
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
-    return super.computeSelfCost(planner, mq).multiplyBy(0.1);
-  }
-
-  @Override public void implement(Implementor implementor) {
-    implementor.visitChild(0, getInput());
-
-    final List<String> inFields =
-            ElasticsearchRules.elasticsearchFieldNames(getInput().getRowType());
-    final ElasticsearchRules.RexToElasticsearchTranslator translator =
-            new ElasticsearchRules.RexToElasticsearchTranslator(
-                    (JavaTypeFactory) getCluster().getTypeFactory(), inFields);
-
-    final List<String> fields = new ArrayList<>();
-    final List<String> scriptFields = new ArrayList<>();
-    for (Pair<RexNode, String> pair: getNamedProjects()) {
-      final String name = pair.right;
-      final String expr = pair.left.accept(translator);
-
-      if (expr.equals("\"" + name + "\"")) {
-        fields.add(name);
-      } else if (expr.matches("\"literal\":.+")) {
-        scriptFields.add(ElasticsearchRules.quote(name)
-                + ":{\"script\": "
-                + expr.split(":")[1] + "}");
-      } else {
-        scriptFields.add(ElasticsearchRules.quote(name)
-                + ":{\"script\":"
-                // _source (ES2) vs params._source (ES5)
-                + "\"" + implementor.elasticsearchTable.scriptedFieldPrefix() + "."
-                + expr.replaceAll("\"", "") + "\"}");
-      }
-    }
-
-    StringBuilder query = new StringBuilder();
-    if (scriptFields.isEmpty()) {
-      List<String> newList = Lists.transform(fields, ElasticsearchRules::quote);
-
-      final String findString = String.join(", ", newList);
-      query.append("\"_source\" : [").append(findString).append("]");
-    } else {
-      // if scripted fields are present, ES ignores _source attribute
-      for (String field: fields) {
-        scriptFields.add(ElasticsearchRules.quote(field) + ":{\"script\": "
-            // _source (ES2) vs params._source (ES5)
-            + "\"" + implementor.elasticsearchTable.scriptedFieldPrefix() + "."
-            + field + "\"}");
-      }
-      query.append("\"script_fields\": {")
-          .append(String.join(", ", scriptFields))
-          .append("}");
-    }
-
-    for (String opfield : implementor.list) {
-      if (opfield.startsWith("\"_source\"")) {
-        implementor.list.remove(opfield);
-      }
-    }
-    implementor.add(query.toString());
-  }
-}
-
-// End ElasticsearchProject.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRel.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRel.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRel.java
deleted file mode 100644
index 436adf9..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRel.java
+++ /dev/null
@@ -1,58 +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.elasticsearch;
-
-import org.apache.calcite.plan.Convention;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.rel.RelNode;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Relational expression that uses Elasticsearch calling convention.
- */
-public interface ElasticsearchRel extends RelNode {
-  void implement(Implementor implementor);
-
-  /**
-   * Calling convention for relational operations that occur in Elasticsearch.
-   */
-  Convention CONVENTION = new Convention.Impl("ELASTICSEARCH", ElasticsearchRel.class);
-
-  /**
-   * Callback for the implementation process that converts a tree of
-   * {@link ElasticsearchRel} nodes into an Elasticsearch query.
-   */
-  class Implementor {
-    final List<String> list = new ArrayList<>();
-
-    RelOptTable table;
-    AbstractElasticsearchTable elasticsearchTable;
-
-    public void add(String findOp) {
-      list.add(findOp);
-    }
-
-    public void visitChild(int ordinal, RelNode input) {
-      assert ordinal == 0;
-      ((ElasticsearchRel) input).implement(this);
-    }
-  }
-}
-
-// End ElasticsearchRel.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
deleted file mode 100644
index c4f6728..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchRules.java
+++ /dev/null
@@ -1,238 +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.elasticsearch;
-
-import org.apache.calcite.adapter.enumerable.RexImpTable;
-import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
-import org.apache.calcite.adapter.java.JavaTypeFactory;
-import org.apache.calcite.plan.Convention;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelTrait;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelCollations;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.convert.ConverterRule;
-import org.apache.calcite.rel.core.Sort;
-import org.apache.calcite.rel.logical.LogicalFilter;
-import org.apache.calcite.rel.logical.LogicalProject;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexVisitorImpl;
-import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.sql.validate.SqlValidatorUtil;
-
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Rules and relational operators for
- * {@link ElasticsearchRel#CONVENTION ELASTICSEARCH}
- * calling convention.
- */
-class ElasticsearchRules {
-  static final RelOptRule[] RULES = {
-      ElasticsearchSortRule.INSTANCE,
-      ElasticsearchFilterRule.INSTANCE,
-      ElasticsearchProjectRule.INSTANCE
-  };
-
-  private ElasticsearchRules() {}
-
-  /**
-   * Returns 'string' if it is a call to item['string'], null otherwise.
-   */
-  static String isItem(RexCall call) {
-    if (call.getOperator() != SqlStdOperatorTable.ITEM) {
-      return null;
-    }
-    final RexNode op0 = call.getOperands().get(0);
-    final RexNode op1 = call.getOperands().get(1);
-
-    if (op0 instanceof RexInputRef
-        && ((RexInputRef) op0).getIndex() == 0
-        && op1 instanceof RexLiteral
-        && ((RexLiteral) op1).getValue2() instanceof String) {
-      return (String) ((RexLiteral) op1).getValue2();
-    }
-    return null;
-  }
-
-  static List<String> elasticsearchFieldNames(final RelDataType rowType) {
-    return SqlValidatorUtil.uniquify(
-        new AbstractList<String>() {
-          @Override public String get(int index) {
-            final String name = rowType.getFieldList().get(index).getName();
-            return name.startsWith("$") ? "_" + name.substring(2) : name;
-          }
-
-          @Override public int size() {
-            return rowType.getFieldCount();
-          }
-        },
-        SqlValidatorUtil.EXPR_SUGGESTER, true);
-  }
-
-  static String quote(String s) {
-    return "\"" + s + "\"";
-  }
-
-  /**
-   * Translator from {@link RexNode} to strings in Elasticsearch's expression
-   * language.
-   */
-  static class RexToElasticsearchTranslator extends RexVisitorImpl<String> {
-    private final JavaTypeFactory typeFactory;
-    private final List<String> inFields;
-
-    RexToElasticsearchTranslator(JavaTypeFactory typeFactory, List<String> inFields) {
-      super(true);
-      this.typeFactory = typeFactory;
-      this.inFields = inFields;
-    }
-
-    @Override public String visitLiteral(RexLiteral literal) {
-      if (literal.getValue() == null) {
-        return "null";
-      }
-      return "\"literal\":\""
-        + RexToLixTranslator.translateLiteral(literal, literal.getType(),
-          typeFactory, RexImpTable.NullAs.NOT_POSSIBLE)
-        + "\"";
-    }
-
-    @Override public String visitInputRef(RexInputRef inputRef) {
-      return quote(inFields.get(inputRef.getIndex()));
-    }
-
-    @Override public String visitCall(RexCall call) {
-      final String name = isItem(call);
-      if (name != null) {
-        return "\"" + name + "\"";
-      }
-
-      final List<String> strings = visitList(call.operands);
-      if (call.getKind() == SqlKind.CAST) {
-        return strings.get(0).startsWith("$") ? strings.get(0).substring(1) : strings.get(0);
-      }
-      if (call.getOperator() == SqlStdOperatorTable.ITEM) {
-        final RexNode op1 = call.getOperands().get(1);
-        if (op1 instanceof RexLiteral && op1.getType().getSqlTypeName() == SqlTypeName.INTEGER) {
-          return stripQuotes(strings.get(0)) + "[" + ((RexLiteral) op1).getValue2() + "]";
-        }
-      }
-      throw new IllegalArgumentException("Translation of " + call.toString()
-        + "is not supported by ElasticsearchProject");
-    }
-
-    private String stripQuotes(String s) {
-      return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
-    }
-
-    List<String> visitList(List<RexNode> list) {
-      final List<String> strings = new ArrayList<>();
-      for (RexNode node: list) {
-        strings.add(node.accept(this));
-      }
-      return strings;
-    }
-  }
-
-  /**
-   * Base class for planner rules that convert a relational expression to
-   * Elasticsearch calling convention.
-   */
-  abstract static class ElasticsearchConverterRule extends ConverterRule {
-    final Convention out;
-
-    ElasticsearchConverterRule(Class<? extends RelNode> clazz, RelTrait in, Convention out,
-        String description) {
-      super(clazz, in, out, description);
-      this.out = out;
-    }
-  }
-
-  /**
-   * Rule to convert a {@link org.apache.calcite.rel.core.Sort} to an
-   * {@link ElasticsearchSort}.
-   */
-  private static class ElasticsearchSortRule extends ElasticsearchConverterRule {
-    private static final ElasticsearchSortRule INSTANCE =
-        new ElasticsearchSortRule();
-
-    private ElasticsearchSortRule() {
-      super(Sort.class, Convention.NONE, ElasticsearchRel.CONVENTION,
-          "ElasticsearchSortRule");
-    }
-
-    @Override public RelNode convert(RelNode relNode) {
-      final Sort sort = (Sort) relNode;
-      final RelTraitSet traitSet = sort.getTraitSet().replace(out).replace(sort.getCollation());
-      return new ElasticsearchSort(relNode.getCluster(), traitSet,
-        convert(sort.getInput(), traitSet.replace(RelCollations.EMPTY)), sort.getCollation(),
-        sort.offset, sort.fetch);
-    }
-  }
-
-  /**
-   * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalFilter} to an
-   * {@link ElasticsearchFilter}.
-   */
-  private static class ElasticsearchFilterRule extends ElasticsearchConverterRule {
-    private static final ElasticsearchFilterRule INSTANCE = new ElasticsearchFilterRule();
-
-    private ElasticsearchFilterRule() {
-      super(LogicalFilter.class, Convention.NONE, ElasticsearchRel.CONVENTION,
-        "ElasticsearchFilterRule");
-    }
-
-    @Override public RelNode convert(RelNode relNode) {
-      final LogicalFilter filter = (LogicalFilter) relNode;
-      final RelTraitSet traitSet = filter.getTraitSet().replace(out);
-      return new ElasticsearchFilter(relNode.getCluster(), traitSet,
-        convert(filter.getInput(), out),
-        filter.getCondition());
-    }
-  }
-
-  /**
-   * Rule to convert a {@link org.apache.calcite.rel.logical.LogicalProject}
-   * to an {@link ElasticsearchProject}.
-   */
-  private static class ElasticsearchProjectRule extends ElasticsearchConverterRule {
-    private static final ElasticsearchProjectRule INSTANCE = new ElasticsearchProjectRule();
-
-    private ElasticsearchProjectRule() {
-      super(LogicalProject.class, Convention.NONE, ElasticsearchRel.CONVENTION,
-        "ElasticsearchProjectRule");
-    }
-
-    @Override public RelNode convert(RelNode relNode) {
-      final LogicalProject project = (LogicalProject) relNode;
-      final RelTraitSet traitSet = project.getTraitSet().replace(out);
-      return new ElasticsearchProject(project.getCluster(), traitSet,
-        convert(project.getInput(), out), project.getProjects(), project.getRowType());
-    }
-  }
-}
-
-// End ElasticsearchRules.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
deleted file mode 100644
index 7247d19..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSchema.java
+++ /dev/null
@@ -1,33 +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.elasticsearch;
-
-import org.apache.calcite.schema.Schema;
-
-/**
- * Gives access to some basic information of the Elasticsearch schema.
- */
-public interface ElasticsearchSchema extends Schema {
-  /**
-   * The name of the Elasticsearch index.
-   *
-   * @return The index name
-   */
-  String getIndex();
-}
-
-// End ElasticsearchSchema.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSort.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSort.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSort.java
deleted file mode 100644
index 851e51b..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchSort.java
+++ /dev/null
@@ -1,104 +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.elasticsearch;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelCollation;
-import org.apache.calcite.rel.RelFieldCollation;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.Sort;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.util.Util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of {@link org.apache.calcite.rel.core.Sort}
- * relational expression in Elasticsearch.
- */
-public class ElasticsearchSort extends Sort implements ElasticsearchRel {
-  public ElasticsearchSort(RelOptCluster cluster, RelTraitSet traitSet, RelNode child,
-      RelCollation collation, RexNode offset, RexNode fetch) {
-    super(cluster, traitSet, child, collation, offset, fetch);
-    assert getConvention() == ElasticsearchRel.CONVENTION;
-    assert getConvention() == child.getConvention();
-  }
-
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
-    return super.computeSelfCost(planner, mq).multiplyBy(0.05);
-  }
-
-  @Override public Sort copy(RelTraitSet traitSet, RelNode relNode, RelCollation relCollation,
-      RexNode offset, RexNode fetch) {
-    return new ElasticsearchSort(getCluster(), traitSet, relNode, collation, offset, fetch);
-  }
-
-  @Override public void implement(Implementor implementor) {
-    implementor.visitChild(0, getInput());
-    if (!collation.getFieldCollations().isEmpty()) {
-      final List<String> keys = new ArrayList<>();
-      if (input instanceof Project) {
-        final List<RexNode> projects = ((Project) input).getProjects();
-
-        for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
-          RexNode project = projects.get(fieldCollation.getFieldIndex());
-          String name = project.accept(MapProjectionFieldVisitor.INSTANCE);
-          keys.add(ElasticsearchRules.quote(name) + ": " + direction(fieldCollation));
-        }
-      } else {
-        final List<RelDataTypeField> fields = getRowType().getFieldList();
-
-        for (RelFieldCollation fieldCollation : collation.getFieldCollations()) {
-          final String name = fields.get(fieldCollation.getFieldIndex()).getName();
-          keys.add(ElasticsearchRules.quote(name) + ": " + direction(fieldCollation));
-        }
-      }
-
-      implementor.add("\"sort\": [ " + Util.toString(keys, "{", "}, {", "}") + "]");
-    }
-
-    if (offset != null) {
-      implementor.add("\"from\": " + ((RexLiteral) offset).getValue());
-    }
-
-    if (fetch != null) {
-      implementor.add("\"size\": " + ((RexLiteral) fetch).getValue());
-    }
-  }
-
-  private String direction(RelFieldCollation fieldCollation) {
-    switch (fieldCollation.getDirection()) {
-    case DESCENDING:
-    case STRICTLY_DESCENDING:
-      return "\"desc\"";
-    case ASCENDING:
-    case STRICTLY_ASCENDING:
-    default:
-      return "\"asc\"";
-    }
-  }
-}
-
-// End ElasticsearchSort.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchTableScan.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchTableScan.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchTableScan.java
deleted file mode 100644
index 1020faa..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchTableScan.java
+++ /dev/null
@@ -1,89 +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.elasticsearch;
-
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelOptRule;
-import org.apache.calcite.plan.RelOptTable;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.TableScan;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rel.type.RelDataType;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Relational expression representing a scan of an Elasticsearch type.
- *
- * <p> Additional operations might be applied,
- * using the "find" method.</p>
- */
-public class ElasticsearchTableScan extends TableScan implements ElasticsearchRel {
-  private final AbstractElasticsearchTable elasticsearchTable;
-  private final RelDataType projectRowType;
-
-  /**
-   * Creates an ElasticsearchTableScan.
-   *
-   * @param cluster Cluster
-   * @param traitSet Trait set
-   * @param table Table
-   * @param elasticsearchTable Elasticsearch table
-   * @param projectRowType Fields and types to project; null to project raw row
-   */
-  protected ElasticsearchTableScan(RelOptCluster cluster, RelTraitSet traitSet,
-       RelOptTable table, AbstractElasticsearchTable elasticsearchTable,
-       RelDataType projectRowType) {
-    super(cluster, traitSet, table);
-    this.elasticsearchTable = Objects.requireNonNull(elasticsearchTable);
-    this.projectRowType = projectRowType;
-
-    assert getConvention() == ElasticsearchRel.CONVENTION;
-  }
-
-  @Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
-    assert inputs.isEmpty();
-    return this;
-  }
-
-  @Override public RelDataType deriveRowType() {
-    return projectRowType != null ? projectRowType : super.deriveRowType();
-  }
-
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
-    final float f = projectRowType == null ? 1f : (float) projectRowType.getFieldCount() / 100f;
-    return super.computeSelfCost(planner, mq).multiplyBy(.1 * f);
-  }
-
-  @Override public void register(RelOptPlanner planner) {
-    planner.addRule(ElasticsearchToEnumerableConverterRule.INSTANCE);
-    for (RelOptRule rule: ElasticsearchRules.RULES) {
-      planner.addRule(rule);
-    }
-  }
-
-  @Override public void implement(Implementor implementor) {
-    implementor.elasticsearchTable = elasticsearchTable;
-    implementor.table = table;
-  }
-}
-
-// End ElasticsearchTableScan.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverter.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverter.java
deleted file mode 100644
index 3cebd3c..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverter.java
+++ /dev/null
@@ -1,115 +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.elasticsearch;
-
-import org.apache.calcite.adapter.enumerable.EnumerableRel;
-import org.apache.calcite.adapter.enumerable.EnumerableRelImplementor;
-import org.apache.calcite.adapter.enumerable.JavaRowFormat;
-import org.apache.calcite.adapter.enumerable.PhysType;
-import org.apache.calcite.adapter.enumerable.PhysTypeImpl;
-import org.apache.calcite.linq4j.tree.BlockBuilder;
-import org.apache.calcite.linq4j.tree.Expression;
-import org.apache.calcite.linq4j.tree.Expressions;
-import org.apache.calcite.linq4j.tree.MethodCallExpression;
-import org.apache.calcite.plan.ConventionTraitDef;
-import org.apache.calcite.plan.RelOptCluster;
-import org.apache.calcite.plan.RelOptCost;
-import org.apache.calcite.plan.RelOptPlanner;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.prepare.CalcitePrepareImpl;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.convert.ConverterImpl;
-import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.runtime.Hook;
-import org.apache.calcite.util.BuiltInMethod;
-import org.apache.calcite.util.Pair;
-
-import com.google.common.collect.Lists;
-
-import java.util.AbstractList;
-import java.util.List;
-
-/**
- * Relational expression representing a scan of a table in an Elasticsearch data source.
- */
-public class ElasticsearchToEnumerableConverter extends ConverterImpl implements EnumerableRel {
-  protected ElasticsearchToEnumerableConverter(RelOptCluster cluster, RelTraitSet traits,
-      RelNode input) {
-    super(cluster, ConventionTraitDef.INSTANCE, traits, input);
-  }
-
-  @Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
-    return new ElasticsearchToEnumerableConverter(getCluster(), traitSet, sole(inputs));
-  }
-
-  @Override public RelOptCost computeSelfCost(RelOptPlanner planner, RelMetadataQuery mq) {
-    return super.computeSelfCost(planner, mq).multiplyBy(.1);
-  }
-
-  @Override public Result implement(EnumerableRelImplementor implementor, Prefer prefer) {
-    final BlockBuilder list = new BlockBuilder();
-    final ElasticsearchRel.Implementor elasticsearchImplementor =
-        new ElasticsearchRel.Implementor();
-    elasticsearchImplementor.visitChild(0, getInput());
-    final RelDataType rowType = getRowType();
-    final PhysType physType = PhysTypeImpl.of(implementor.getTypeFactory(), rowType,
-        prefer.prefer(JavaRowFormat.ARRAY));
-    final Expression fields = list.append("fields",
-        constantArrayList(
-            Pair.zip(ElasticsearchRules.elasticsearchFieldNames(rowType),
-                new AbstractList<Class>() {
-                  @Override public Class get(int index) {
-                    return physType.fieldClass(index);
-                  }
-
-                  @Override public int size() {
-                    return rowType.getFieldCount();
-                  }
-                }),
-            Pair.class));
-    final Expression table = list.append("table",
-        elasticsearchImplementor.table
-            .getExpression(AbstractElasticsearchTable.ElasticsearchQueryable.class));
-    List<String> opList = elasticsearchImplementor.list;
-    final Expression ops = list.append("ops", constantArrayList(opList, String.class));
-    Expression enumerable = list.append("enumerable",
-        Expressions.call(table, ElasticsearchMethod.ELASTICSEARCH_QUERYABLE_FIND.method, ops,
-            fields));
-    if (CalcitePrepareImpl.DEBUG) {
-      System.out.println("Elasticsearch: " + opList);
-    }
-    Hook.QUERY_PLAN.run(opList);
-    list.add(Expressions.return_(null, enumerable));
-    return implementor.result(physType, list.toBlock());
-  }
-
-  /** E.g. {@code constantArrayList("x", "y")} returns
-   * "Arrays.asList('x', 'y')". */
-  private static <T> MethodCallExpression constantArrayList(List<T> values, Class clazz) {
-    return Expressions.call(BuiltInMethod.ARRAYS_AS_LIST.method,
-        Expressions.newArrayInit(clazz, constantList(values)));
-  }
-
-  /** E.g. {@code constantList("x", "y")} returns
-   * {@code {ConstantExpression("x"), ConstantExpression("y")}}. */
-  private static <T> List<Expression> constantList(List<T> values) {
-    return Lists.transform(values, Expressions::constant);
-  }
-}
-
-// End ElasticsearchToEnumerableConverter.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverterRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverterRule.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverterRule.java
deleted file mode 100644
index 756c078..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchToEnumerableConverterRule.java
+++ /dev/null
@@ -1,54 +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.elasticsearch;
-
-import org.apache.calcite.adapter.enumerable.EnumerableConvention;
-import org.apache.calcite.plan.RelTraitSet;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.convert.ConverterRule;
-import org.apache.calcite.rel.core.RelFactories;
-import org.apache.calcite.tools.RelBuilderFactory;
-
-import java.util.function.Predicate;
-
-/**
- * Rule to convert a relational expression from
- * {@link ElasticsearchRel#CONVENTION} to {@link EnumerableConvention}.
- */
-public class ElasticsearchToEnumerableConverterRule extends ConverterRule {
-  public static final ConverterRule INSTANCE =
-      new ElasticsearchToEnumerableConverterRule(RelFactories.LOGICAL_BUILDER);
-
-  /**
-   * Creates an ElasticsearchToEnumerableConverterRule.
-   *
-   * @param relBuilderFactory Builder for relational expressions
-   */
-  public ElasticsearchToEnumerableConverterRule(
-      RelBuilderFactory relBuilderFactory) {
-    super(RelNode.class, (Predicate<RelNode>) r -> true,
-        ElasticsearchRel.CONVENTION, EnumerableConvention.INSTANCE,
-        relBuilderFactory, "ElasticsearchToEnumerableConverterRule");
-  }
-
-  @Override public RelNode convert(RelNode relNode) {
-    RelTraitSet newTraitSet = relNode.getTraitSet().replace(getOutConvention());
-    return new ElasticsearchToEnumerableConverter(relNode.getCluster(), newTraitSet, relNode);
-  }
-}
-
-// End ElasticsearchToEnumerableConverterRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/MapProjectionFieldVisitor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/MapProjectionFieldVisitor.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/MapProjectionFieldVisitor.java
deleted file mode 100644
index bcb99a7..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/MapProjectionFieldVisitor.java
+++ /dev/null
@@ -1,42 +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.elasticsearch;
-
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexVisitorImpl;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-
-/**
- * Visitor that extracts the actual field name from an item expression.
- */
-public class MapProjectionFieldVisitor extends RexVisitorImpl<String> {
-  public static final MapProjectionFieldVisitor INSTANCE = new MapProjectionFieldVisitor();
-
-  private MapProjectionFieldVisitor() {
-    super(true);
-  }
-
-  @Override public String visitCall(RexCall call) {
-    if (call.op == SqlStdOperatorTable.ITEM) {
-      return ((RexLiteral) call.getOperands().get(1)).getValueAs(String.class);
-    }
-    return super.visitCall(call);
-  }
-}
-
-// End MapProjectionFieldVisitor.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/core/src/main/java/org/apache/calcite/adapter/elasticsearch/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/package-info.java b/core/src/main/java/org/apache/calcite/adapter/elasticsearch/package-info.java
deleted file mode 100644
index 98e1a92..0000000
--- a/core/src/main/java/org/apache/calcite/adapter/elasticsearch/package-info.java
+++ /dev/null
@@ -1,26 +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.
- */
-
-/**
- * Base classes for a query provider based on an Elasticsearch DB.
- */
-@PackageMarker
-package org.apache.calcite.adapter.elasticsearch;
-
-import org.apache.calcite.avatica.util.PackageMarker;
-
-// End package-info.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/elasticsearch/pom.xml
----------------------------------------------------------------------
diff --git a/elasticsearch/pom.xml b/elasticsearch/pom.xml
new file mode 100644
index 0000000..d938da8
--- /dev/null
+++ b/elasticsearch/pom.xml
@@ -0,0 +1,187 @@
+<?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.17.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>calcite-elasticsearch</artifactId>
+  <packaging>jar</packaging>
+  <version>1.17.0-SNAPSHOT</version>
+  <name>Calcite Elasticsearch</name>
+  <description>Elasticsearch 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>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</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>elasticsearch-rest-client</artifactId>
+      <version>${elasticsearch.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpcore</artifactId>
+      <version>${httpcore.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.elasticsearch</groupId>
+      <artifactId>elasticsearch</artifactId>
+      <version>${elasticsearch.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <!-- Using special netty transport to start embedded ES instance during tests -->
+      <groupId>org.elasticsearch.plugin</groupId>
+      <artifactId>transport-netty4-client</artifactId>
+      <version>${elasticsearch.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <!-- Elastic search doesn't export painless script artifact to maven central.
+      Using 3rd party version (codelibs)
+      This JAR is used only in tests
+      https://discuss.elastic.co/t/5-0-0-using-painless-in-esintegtestcase/64447/13
+      -->
+      <groupId>org.codelibs.elasticsearch.module</groupId>
+      <artifactId>lang-painless</artifactId>
+      <version>${elasticsearch.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <!-- log4j2 is default logging framework for ES server -->
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+      <version>${log4j2.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+      <version>${log4j2.version}</version>
+      <scope>test</scope>
+    </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>
+                <ignoredUnusedDeclaredDependency>org.apache.logging.log4j:log4j-api</ignoredUnusedDeclaredDependency>
+                <ignoredUnusedDeclaredDependency>org.apache.logging.log4j:log4j-core</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/0204f286/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
----------------------------------------------------------------------
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
new file mode 100644
index 0000000..66aa1f7
--- /dev/null
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/AbstractElasticsearchTable.java
@@ -0,0 +1,145 @@
+/*
+ * 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.elasticsearch;
+
+import org.apache.calcite.adapter.java.AbstractQueryableTable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.QueryProvider;
+import org.apache.calcite.linq4j.Queryable;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.TranslatableTable;
+import org.apache.calcite.schema.impl.AbstractTableQueryable;
+import org.apache.calcite.sql.type.SqlTypeName;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Table based on an Elasticsearch type.
+ */
+abstract class AbstractElasticsearchTable extends AbstractQueryableTable
+    implements TranslatableTable {
+
+  final String indexName;
+  final String typeName;
+
+  /**
+   * Creates an ElasticsearchTable.
+   * @param indexName Elastic Search index
+   * @param typeName Elastic Search index type
+   */
+  AbstractElasticsearchTable(String indexName, String typeName) {
+    super(Object[].class);
+    this.indexName = Objects.requireNonNull(indexName, "indexName");
+    this.typeName = Objects.requireNonNull(typeName, "typeName");
+  }
+
+  @Override public String toString() {
+    return "ElasticsearchTable{" + indexName + "/" + typeName + "}";
+  }
+
+  public RelDataType getRowType(RelDataTypeFactory relDataTypeFactory) {
+    final RelDataType mapType = relDataTypeFactory.createMapType(
+        relDataTypeFactory.createSqlType(SqlTypeName.VARCHAR),
+        relDataTypeFactory.createTypeWithNullability(
+            relDataTypeFactory.createSqlType(SqlTypeName.ANY),
+            true));
+    return relDataTypeFactory.builder().add("_MAP", mapType).build();
+  }
+
+  public <T> Queryable<T> asQueryable(QueryProvider queryProvider, SchemaPlus schema,
+      String tableName) {
+    return new ElasticsearchQueryable<>(queryProvider, schema, this, tableName);
+  }
+
+  public RelNode toRel(RelOptTable.ToRelContext context, RelOptTable relOptTable) {
+    final RelOptCluster cluster = context.getCluster();
+    return new ElasticsearchTableScan(cluster, cluster.traitSetOf(ElasticsearchRel.CONVENTION),
+        relOptTable, this, null);
+  }
+
+  /**
+   * In ES 5.x scripted fields start with {@code params._source.foo} while in ES2.x
+   * {@code _source.foo}. Helper method to build correct query based on runtime version of elastic.
+   * Used to keep backwards compatibility with ES2.
+   *
+   * @see <a href="https://github.com/elastic/elasticsearch/issues/20068">_source variable</a>
+   * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-scripting-fields.html">Scripted Fields</a>
+   * @return string to be used for scripted fields
+   */
+  protected abstract String scriptedFieldPrefix();
+
+  /** Executes a "find" operation on the underlying type.
+   *
+   * <p>For example,
+   * <code>client.prepareSearch(index).setTypes(type)
+   * .setSource("{\"fields\" : [\"state\"]}")</code></p>
+   *
+   * @param index Elasticsearch index
+   * @param ops List of operations represented as Json strings.
+   * @param fields List of fields to project; or null to return map
+   * @return Enumerator of results
+   */
+  protected abstract Enumerable<Object> find(String index, List<String> ops,
+      List<Map.Entry<String, Class>> fields);
+
+  /**
+   * Implementation of {@link Queryable} based on
+   * a {@link AbstractElasticsearchTable}.
+   *
+   * @param <T> element type
+   */
+  public static class ElasticsearchQueryable<T> extends AbstractTableQueryable<T> {
+    ElasticsearchQueryable(QueryProvider queryProvider, SchemaPlus schema,
+        AbstractElasticsearchTable table, String tableName) {
+      super(queryProvider, schema, table, tableName);
+    }
+
+    public Enumerator<T> enumerator() {
+      return null;
+    }
+
+    private String getIndex() {
+      return schema.unwrap(ElasticsearchSchema.class).getIndex();
+    }
+
+    private AbstractElasticsearchTable getTable() {
+      return (AbstractElasticsearchTable) table;
+    }
+
+    /** Called via code-generation.
+     * @param ops list of queries (as strings)
+     * @param fields projection
+     * @see ElasticsearchMethod#ELASTICSEARCH_QUERYABLE_FIND
+     * @return result as enumerable
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    public Enumerable<Object> find(List<String> ops,
+        List<Map.Entry<String, Class>> fields) {
+      return getTable().find(getIndex(), ops, fields);
+    }
+  }
+}
+
+// End AbstractElasticsearchTable.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/0204f286/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
----------------------------------------------------------------------
diff --git a/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
new file mode 100644
index 0000000..d87de7e
--- /dev/null
+++ b/elasticsearch/src/main/java/org/apache/calcite/adapter/elasticsearch/ElasticsearchEnumerators.java
@@ -0,0 +1,111 @@
+/*
+ * 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.elasticsearch;
+
+import org.apache.calcite.avatica.util.DateTimeUtils;
+import org.apache.calcite.linq4j.function.Function1;
+import org.apache.calcite.linq4j.tree.Primitive;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Util functions which convert
+ * {@link org.apache.calcite.adapter.elasticsearch.ElasticsearchSearchResult.SearchHit}
+ * into calcite specific return type (map, object[], list etc.)
+ */
+class ElasticsearchEnumerators {
+
+  private ElasticsearchEnumerators() {}
+
+  private static Function1<ElasticsearchSearchResult.SearchHit, Map> mapGetter() {
+    return new Function1<ElasticsearchSearchResult.SearchHit, Map>() {
+      public Map apply(ElasticsearchSearchResult.SearchHit hits) {
+        return hits.sourceOrFields();
+      }
+    };
+  }
+
+  private static Function1<ElasticsearchSearchResult.SearchHit, Object> singletonGetter(
+      final String fieldName,
+      final Class fieldClass) {
+    return new Function1<ElasticsearchSearchResult.SearchHit, Object>() {
+      public Object apply(ElasticsearchSearchResult.SearchHit hits) {
+        return convert(hits.sourceOrFields(), fieldClass);
+      }
+    };
+  }
+
+  /**
+   * Function that extracts a given set of fields from elastic search result
+   * objects.
+   *
+   * @param fields List of fields to project
+   *
+   * @return function that converts the search result into a generic array
+   */
+  private static Function1<ElasticsearchSearchResult.SearchHit, Object[]> listGetter(
+      final List<Map.Entry<String, Class>> fields) {
+    return new Function1<ElasticsearchSearchResult.SearchHit, Object[]>() {
+      public Object[] apply(ElasticsearchSearchResult.SearchHit hit) {
+        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();
+          final Class type = field.getValue();
+          objects[i] = convert(hit.value(name), type);
+        }
+        return objects;
+      }
+    };
+  }
+
+  static Function1<ElasticsearchSearchResult.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 ElasticsearchEnumerators.java