You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2018/06/26 05:41:43 UTC

[1/3] calcite git commit: [CALCITE-2380] Javadoc warnings (Andrei Sereda)

Repository: calcite
Updated Branches:
  refs/heads/master 9721283bd -> 6e8bb5a16


[CALCITE-2380] Javadoc warnings (Andrei Sereda)

Close apache/calcite#741


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

Branch: refs/heads/master
Commit: 4f8354651021dbabf123836d205aee25c658b6d9
Parents: 9721283
Author: Andrei Sereda <an...@nospam.com>
Authored: Sun Jun 24 18:59:26 2018 -0400
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jun 25 20:42:06 2018 -0700

----------------------------------------------------------------------
 .../Elasticsearch2Enumerator.java               |   2 +
 .../elasticsearch2/Elasticsearch2Schema.java    |   3 +
 .../elasticsearch2/Elasticsearch2Table.java     |   6 +-
 .../ElasticSearch2AdapterTest.java              |   4 +-
 .../elasticsearch2/EmbeddedElasticNode.java     |  15 +-
 .../elasticsearch2/EmbeddedElasticRule.java     |  35 ++--
 .../org/apache/calcite/test/ElasticChecker.java |   6 +-
 .../Elasticsearch5Enumerator.java               |   1 +
 .../elasticsearch5/Elasticsearch5Schema.java    |   2 +
 .../elasticsearch5/Elasticsearch5Table.java     |   5 +-
 .../ElasticSearch5AdapterTest.java              |   4 +-
 .../elasticsearch5/EmbeddedElasticNode.java     | 153 ------------------
 .../elasticsearch5/EmbeddedElasticRule.java     |  98 -----------
 .../EmbeddedElasticsearchNode.java              | 161 +++++++++++++++++++
 .../org/apache/calcite/test/ElasticChecker.java |  49 ------
 .../calcite/adapter/mongodb/MongoSchema.java    |   4 +-
 .../calcite/adapter/mongodb/MongoTable.java     |   5 +
 .../mongodb/MongoToEnumerableConverter.java     |   7 +-
 .../adapter/mongodb/MongoAdapterTest.java       |   9 +-
 .../adapter/mongodb/MongoDatabaseRule.java      |   1 +
 .../apache/calcite/test/MongoAssertions.java    |  15 +-
 21 files changed, 257 insertions(+), 328 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
index c3d2ac0..8247957 100644
--- a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
@@ -98,6 +98,8 @@ public class Elasticsearch2Enumerator implements Enumerator<Object> {
    * objects.
    *
    * @param fields List of fields to project
+   *
+   * @return function that converts the search result into a generic array
    */
   private static Function1<SearchHit, Object[]> listGetter(
       final List<Map.Entry<String, Class>> fields) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Schema.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Schema.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Schema.java
index 46e3fc5..f02a668 100644
--- a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Schema.java
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Schema.java
@@ -92,6 +92,9 @@ public class Elasticsearch2Schema extends AbstractSchema
   /**
    * Allows schema to be instantiated from existing elastic search client.
    * This constructor is used in tests.
+   *
+   * @param client Existing (injectable) client instance
+   * @param index Index name
    */
   @VisibleForTesting
   Elasticsearch2Schema(Client client, String index) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/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
index 2928835..8bfd8cf 100644
--- a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Table.java
@@ -39,8 +39,12 @@ public class Elasticsearch2Table extends AbstractElasticsearchTable {
 
   /**
    * Creates an Elasticsearch2Table.
+   *
+   * @param client Existing ES instance
+   * @param indexName Name of the index
+   * @param typeName Index type
    */
-  public Elasticsearch2Table(Client client, String indexName, String typeName) {
+  Elasticsearch2Table(Client client, String indexName, String typeName) {
     super(indexName, typeName);
     this.client = client;
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
index 287e094..a7eff8f 100644
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
@@ -58,6 +58,8 @@ public class ElasticSearch2AdapterTest {
 
   /**
    * Used to create {@code zips} index and insert some data
+   *
+   * @throws Exception when couldn't create the instance
    */
   @BeforeClass
   public static void setupInstance() throws Exception {
@@ -144,7 +146,7 @@ public class ElasticSearch2AdapterTest {
    * Tests using calcite view
    */
   @Test
-  public void view() throws Exception {
+  public void view() {
     calciteAssert()
           .query("select * from zips where \"city\" = 'BROOKLYN'")
           .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
index 4474add..55f83f9 100644
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
@@ -56,13 +56,15 @@ class EmbeddedElasticNode implements AutoCloseable {
   private static class LocalNode extends Node {
     private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
       super(InternalSettingsPreparer.prepareEnvironment(settings, null),
-              Version.CURRENT,
-              classpathPlugins);
+          Version.CURRENT, classpathPlugins);
     }
   }
 
   /**
    * Creates an instance with existing settings
+   *
+   * @param settings ES settings for the node
+   * @return un-started node; call {@link #start()} to start the instance
    */
   private static EmbeddedElasticNode create(Settings settings) {
     // ensure GroovyPlugin is installed or otherwise scripted fields would not work
@@ -73,6 +75,8 @@ class EmbeddedElasticNode implements AutoCloseable {
   /**
    * Creates elastic node as single member of a cluster. Node will not be started
    * unless {@link #start()} is explicitly called.
+   *
+   * @return node with default configuration
    */
   public static EmbeddedElasticNode create() {
     File data = Files.createTempDir();
@@ -105,7 +109,9 @@ class EmbeddedElasticNode implements AutoCloseable {
   }
 
   /**
-   * Returns current address to connect to with HTTP client.
+   * Returns the current address to connect to with HTTP client.
+   *
+   * @return {@code HTTP} address (hostname / port)
    */
   public TransportAddress httpAddress() {
     Preconditions.checkState(isStarted, "node is not started");
@@ -123,8 +129,9 @@ class EmbeddedElasticNode implements AutoCloseable {
   /**
    * Exposes elastic
    * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
-   *
    * (use of HTTP client is preferred).
+   *
+   * @return client API to access ES functionality
    */
   public Client client() {
     Preconditions.checkState(isStarted, "node is not started");

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
index a633078..4bd9c25 100644
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
@@ -28,33 +28,31 @@ import org.junit.rules.ExternalResource;
  *
  * This rule should be used as follows:
  * <pre>
- *  {@code
  *
  *  public class MyTest {
- *    @literal @ClassRule
+ *    &#64;ClassRule
  *    public static final ElasticSearchRule RULE = ElasticSearchRule.create();
  *
- *    @literal @BeforeClass
- *    public void setup() {
+ *    &#64;BeforeClass
+ *    public static void setup() {
  *       // ... populate instance
  *    }
  *
- *    @literal @Test
+ *    &#64;Test
  *    public void myTest() {
  *      TransportAddress address = RULE.httpAddress();
- *      // ....
+ *      // .... (connect)
  *    }
- *  }
- *  }
+ * }
  * </pre>
  *
  * @see ExternalResource
  */
 class EmbeddedElasticRule extends ExternalResource {
 
-  private final EmbeddedElasticNode node;
+  private final EmbeddedElasticsearchNode node;
 
-  private EmbeddedElasticRule(EmbeddedElasticNode resource) {
+  private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
     this.node = Preconditions.checkNotNull(resource, "resource");
   }
 
@@ -72,13 +70,22 @@ class EmbeddedElasticRule extends ExternalResource {
 
   /**
    * Factory method to create this rule.
+   *
+   * @return new rule instance to be used in unit tests
    */
+<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
   public static EmbeddedElasticRule create() {
     return new EmbeddedElasticRule(EmbeddedElasticNode.create());
+=======
+  public static EmbeddedElasticsearchPolicy create() {
+    return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
+>>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
   }
 
   /**
    * Exposes current ES transport client.
+   *
+   * @return initialized instance of ES
    */
   Client client() {
     return node.client();
@@ -86,12 +93,16 @@ class EmbeddedElasticRule extends ExternalResource {
 
   /**
    * HTTP address for rest clients (can be ES native or any other).
+   *
+<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
+   * @return HTTP hostname/port to connect to this ES instance
+=======
+   * @return {@code HTTP} connection parameters
+>>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
    */
   TransportAddress httpAddress() {
     return node.httpAddress();
   }
-
-
 }
 
 // End EmbeddedElasticRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
index 21fc491..86e9d9f 100644
--- a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
+++ b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
@@ -31,7 +31,11 @@ public class ElasticChecker {
 
 
   /** Returns a function that checks that a particular Elasticsearch pipeline is
-   * generated to implement a query. */
+   * generated to implement a query.
+   *
+   * @param strings list of expected queries
+   * @return function to perform the check
+   */
   public static Function<List, Void> elasticsearchChecker(final String... strings) {
     return new Function<List, Void>() {
       @Nullable

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/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
index 262058a..4ebb626 100644
--- a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.java
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Enumerator.java
@@ -97,6 +97,7 @@ public class Elasticsearch5Enumerator implements Enumerator<Object> {
    * objects.
    *
    * @param fields List of fields to project
+   * @return conversion function to transform ES search result into a generic array
    */
   private static Function1<SearchHit, Object[]> listGetter(
       final List<Map.Entry<String, Class>> fields) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/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
index ebb96c8..b5e0f34 100644
--- a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Schema.java
@@ -92,6 +92,8 @@ public class Elasticsearch5Schema extends AbstractSchema
   /**
    * Allows schema to be instantiated from existing elastic search client.
    * This constructor is used in tests.
+   * @param client existing client instance
+   * @param index name of ES index
    */
   @VisibleForTesting
   Elasticsearch5Schema(Client client, String index) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/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
index 66e3edf..96bef62 100644
--- a/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java
+++ b/elasticsearch5/src/main/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5Table.java
@@ -50,8 +50,11 @@ public class Elasticsearch5Table extends AbstractElasticsearchTable {
 
   /**
    * Creates an Elasticsearch5Table.
+   * @param client existing ES instance
+   * @param indexName ES index name
+   * @param typeName ES type
    */
-  public Elasticsearch5Table(Client client, String indexName, String typeName) {
+  Elasticsearch5Table(Client client, String indexName, String typeName) {
     super(indexName, typeName);
     this.client = client;
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
index adec593..438e048 100644
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
+++ b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
@@ -60,6 +60,8 @@ public class ElasticSearch5AdapterTest {
 
   /**
    * Used to create {@code zips} index and insert some data
+   *
+   * @throws Exception when ES instance setup failed
    */
   @BeforeClass
   public static void setupInstance() throws Exception {
@@ -148,7 +150,7 @@ public class ElasticSearch5AdapterTest {
    * Tests using calcite view
    */
   @Test
-  public void view() throws Exception {
+  public void view() {
     calciteAssert()
           .query("select * from zips where \"city\" = 'BROOKLYN'")
           .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticNode.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticNode.java
deleted file mode 100644
index c644406..0000000
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticNode.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch5;
-
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-
-import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
-import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.node.InternalSettingsPreparer;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.node.NodeValidationException;
-import org.elasticsearch.painless.PainlessPlugin;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.transport.Netty3Plugin;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-
-/**
- * Represents a single elastic search node which can run embedded in a java application.
- * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
- */
-class EmbeddedElasticNode implements AutoCloseable {
-
-  private final Node node;
-  private volatile boolean  isStarted;
-
-  private EmbeddedElasticNode(Node node) {
-    this.node = Preconditions.checkNotNull(node, "node");
-  }
-
-
-  /**
-   * Creates an instance with existing settings
-   */
-  private static EmbeddedElasticNode create(Settings settings) {
-    // ensure GroovyPlugin is installed or otherwise scripted fields would not work
-    Node node = new LocalNode(settings, Arrays.asList(Netty3Plugin.class, PainlessPlugin.class));
-    return new EmbeddedElasticNode(node);
-  }
-
-  /**
-   * Creates elastic node as single member of a cluster. Node will not be started
-   * unless {@link #start()} is explicitly called.
-   */
-  public static EmbeddedElasticNode create() {
-    File data = Files.createTempDir();
-    data.deleteOnExit();
-    File home = Files.createTempDir();
-    home.deleteOnExit();
-
-    Settings settings = Settings.builder()
-            .put("node.name", "fake-elastic")
-            .put("path.home", home.getAbsolutePath())
-            .put("path.data", data.getAbsolutePath())
-            .put("transport.type", "local")
-            .put("http.type", "netty3")
-            .put("script.inline", true)  // requires groovy or painless
-            .put("network.host", "localhost")
-            .build();
-
-    return create(settings);
-  }
-
-  /**
-   * Starts current node
-   */
-  public void start() {
-    Preconditions.checkState(!isStarted, "already started");
-    try {
-      node.start();
-      this.isStarted = true;
-    } catch (NodeValidationException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Returns current address to connect to with HTTP client.
-   */
-  public TransportAddress httpAddress() {
-    Preconditions.checkState(isStarted, "node is not started");
-
-    NodesInfoResponse response =  client().admin().cluster().prepareNodesInfo()
-            .execute().actionGet();
-    if (response.getNodes().size() != 1) {
-      throw new IllegalStateException("Expected single node but got "
-              + response.getNodes().size());
-    }
-    NodeInfo node = response.getNodes().get(0);
-    return node.getHttp().address().boundAddresses()[0];
-  }
-
-  /**
-   * Exposes elastic
-   * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
-   *
-   * (use of HTTP client is preferred).
-   */
-  public Client client() {
-    Preconditions.checkState(isStarted, "node is not started");
-    return node.client();
-  }
-
-  @Override public void close() throws Exception {
-    node.close();
-    // cleanup data dirs
-    for (String name: Arrays.asList("path.data", "path.home")) {
-      if (node.settings().get(name) != null) {
-        File file = new File(node.settings().get(name));
-        if (file.exists()) {
-          file.delete();
-        }
-      }
-    }
-  }
-
-  /**
-   * Having separate class to expose (protected) constructor which allows to install
-   * different plugins. In our case it is {@code GroovyPlugin} for scripted fields
-   * like {@code loc[0]} or {@code loc[1]['foo']}.
-   *
-   * <p>This class is intended solely for tests
-   */
-  private static class LocalNode extends Node {
-
-    private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
-      super(InternalSettingsPreparer.prepareEnvironment(settings, null),
-              classpathPlugins);
-    }
-  }
-}
-
-// End EmbeddedElasticNode.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticRule.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticRule.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticRule.java
deleted file mode 100644
index d25e8b1..0000000
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticRule.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch5;
-
-import com.google.common.base.Preconditions;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.transport.TransportAddress;
-
-import org.junit.rules.ExternalResource;
-
-/**
- * Used to initialize a single elastic node. For performance reasons (node startup costs),
- * same instance is usually shared across multiple tests.
- *
- * This rule should be used as follows:
- * <pre>
- *  {@code
- *
- *  public class MyTest {
- *    @literal @ClassRule
- *    public static final ElasticSearchRule RULE = ElasticSearchRule.create();
- *
- *    @literal @BeforeClass
- *    public void setup() {
- *       // ... populate instance
- *    }
- *
- *    @literal @Test
- *    public void myTest() {
- *      TransportAddress address = RULE.httpAddress();
- *      // ....
- *    }
- *  }
- *  }
- * </pre>
- *
- * @see ExternalResource
- */
-class EmbeddedElasticRule extends ExternalResource {
-
-  private final EmbeddedElasticNode node;
-
-  private EmbeddedElasticRule(EmbeddedElasticNode resource) {
-    this.node = Preconditions.checkNotNull(resource, "resource");
-  }
-
-  @Override protected void before() throws Throwable {
-    node.start();
-  }
-
-  @Override protected void after() {
-    try {
-      node.close();
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Factory method to create this rule.
-   */
-  public static EmbeddedElasticRule create() {
-    return new EmbeddedElasticRule(EmbeddedElasticNode.create());
-  }
-
-  /**
-   * Exposes current ES transport client.
-   */
-  Client client() {
-    return node.client();
-  }
-
-  /**
-   * HTTP address for rest clients (can be ES native or any other).
-   */
-  TransportAddress httpAddress() {
-    return node.httpAddress();
-  }
-
-
-}
-
-// End EmbeddedElasticRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
new file mode 100644
index 0000000..d603d87
--- /dev/null
+++ b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
@@ -0,0 +1,161 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import com.google.common.io.Files;
+
+import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
+import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.node.InternalSettingsPreparer;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.NodeValidationException;
+import org.elasticsearch.painless.PainlessPlugin;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.transport.Netty3Plugin;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+
+/**
+ * Represents a single elastic search node which can run embedded in a java application.
+ * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
+ */
+class EmbeddedElasticsearchNode implements AutoCloseable {
+
+  private final Node node;
+  private volatile boolean  isStarted;
+
+  private EmbeddedElasticsearchNode(Node node) {
+    this.node = Preconditions.checkNotNull(node, "node");
+  }
+
+
+  /**
+   * Creates an instance with existing settings
+   *
+   * @param settings ES configuration
+   * @return un-initialized node. Use {@link #start()} explicitly.
+   */
+  private static EmbeddedElasticsearchNode create(Settings settings) {
+    // ensure GroovyPlugin is installed or otherwise scripted fields would not work
+    Node node = new LocalNode(settings, Arrays.asList(Netty3Plugin.class, PainlessPlugin.class));
+    return new EmbeddedElasticsearchNode(node);
+  }
+
+  /**
+   * Creates elastic node as single member of a cluster. Node will not be started
+   * unless {@link #start()} is explicitly called.
+   *
+   * @return un-initialized node. Use {@link #start()} explicitly.
+   */
+  public static EmbeddedElasticsearchNode create() {
+    File data = Files.createTempDir();
+    data.deleteOnExit();
+    File home = Files.createTempDir();
+    home.deleteOnExit();
+
+    Settings settings = Settings.builder()
+            .put("node.name", "fake-elastic")
+            .put("path.home", home.getAbsolutePath())
+            .put("path.data", data.getAbsolutePath())
+            .put("transport.type", "local")
+            .put("http.type", "netty3")
+            .put("script.inline", true)  // requires groovy or painless
+            .put("network.host", "localhost")
+            .build();
+
+    return create(settings);
+  }
+
+  /**
+   * Starts current node
+   */
+  public void start() {
+    Preconditions.checkState(!isStarted, "already started");
+    try {
+      node.start();
+      this.isStarted = true;
+    } catch (NodeValidationException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Returns the current address to connect to with HTTP client.
+   *
+   * @return {@code HTTP} protocol connection parameters
+   */
+  TransportAddress httpAddress() {
+    Preconditions.checkState(isStarted, "node is not started");
+
+    NodesInfoResponse response =  client().admin().cluster().prepareNodesInfo()
+            .execute().actionGet();
+    if (response.getNodes().size() != 1) {
+      throw new IllegalStateException("Expected single node but got "
+              + response.getNodes().size());
+    }
+    NodeInfo node = response.getNodes().get(0);
+    return node.getHttp().address().boundAddresses()[0];
+  }
+
+  /**
+   * Exposes elastic
+   * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
+   * (use of HTTP client is preferred).
+   *
+   * @return ES client API on a running instance
+   */
+  public Client client() {
+    Preconditions.checkState(isStarted, "node is not started");
+    return node.client();
+  }
+
+  @Override public void close() throws Exception {
+    node.close();
+    // cleanup data dirs
+    for (String name: Arrays.asList("path.data", "path.home")) {
+      if (node.settings().get(name) != null) {
+        File file = new File(node.settings().get(name));
+        if (file.exists()) {
+          file.delete();
+        }
+      }
+    }
+  }
+
+  /**
+   * Having separate class to expose (protected) constructor which allows to install
+   * different plugins. In our case it is {@code GroovyPlugin} for scripted fields
+   * like {@code loc[0]} or {@code loc[1]['foo']}.
+   *
+   * <p>This class is intended solely for tests
+   */
+  private static class LocalNode extends Node {
+
+    private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
+      super(InternalSettingsPreparer.prepareEnvironment(settings, null),
+              classpathPlugins);
+    }
+  }
+}
+
+// End EmbeddedElasticsearchNode.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticChecker.java b/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticChecker.java
deleted file mode 100644
index 21fc491..0000000
--- a/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticChecker.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.test;
-
-import com.google.common.base.Function;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * Internal util methods for ElasticSearch tests
- */
-public class ElasticChecker {
-
-  private ElasticChecker() {}
-
-
-  /** Returns a function that checks that a particular Elasticsearch pipeline is
-   * generated to implement a query. */
-  public static Function<List, Void> elasticsearchChecker(final String... strings) {
-    return new Function<List, Void>() {
-      @Nullable
-      @Override public Void apply(@Nullable List actual) {
-        Object[] actualArray = actual == null || actual.isEmpty() ? null
-            : ((List) actual.get(0)).toArray();
-        CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
-            actualArray);
-        return null;
-      }
-    };
-  }
-}
-
-// End ElasticChecker.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSchema.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSchema.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSchema.java
index 85b3e61..b7202ae 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSchema.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoSchema.java
@@ -43,9 +43,11 @@ public class MongoSchema extends AbstractSchema {
    * Creates a MongoDB schema.
    *
    * @param host Mongo host, e.g. "localhost"
+   * @param credentialsList Optional credentials (empty list for none)
+   * @param options Mongo connection options
    * @param database Mongo database name, e.g. "foodmart"
    */
-  public MongoSchema(String host, String database,
+  MongoSchema(String host, String database,
       List<MongoCredential> credentialsList, MongoClientOptions options) {
     super();
     try {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTable.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTable.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTable.java
index f00b5b4..740516e 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTable.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoTable.java
@@ -197,6 +197,11 @@ public class MongoTable extends AbstractQueryableTable
 
     /** Called via code-generation.
      *
+     * @param filterJson Filter document
+     * @param projectJson Projection document
+     * @param fields List of expected fields (and their types)
+     * @return result of mongo query
+     *
      * @see org.apache.calcite.adapter.mongodb.MongoMethod#MONGO_QUERYABLE_FIND
      */
     @SuppressWarnings("UnusedDeclaration")

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
index cbbeb86..579c484 100644
--- a/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
+++ b/mongodb/src/main/java/org/apache/calcite/adapter/mongodb/MongoToEnumerableConverter.java
@@ -140,7 +140,12 @@ public class MongoToEnumerableConverter
   }
 
   /** E.g. {@code constantArrayList("x", "y")} returns
-   * "Arrays.asList('x', 'y')". */
+   * "Arrays.asList('x', 'y')".
+   *
+   * @param values List of values
+   * @param clazz Type of values
+   * @return expression
+   */
   private static <T> MethodCallExpression constantArrayList(List<T> values,
       Class clazz) {
     return Expressions.call(

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
index 00daf53..a4d8900 100644
--- a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
+++ b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
@@ -751,8 +751,13 @@ public class MongoAdapterTest implements SchemaFactory {
             });
   }
 
-  /** Returns a function that checks that a particular MongoDB pipeline is
-   * generated to implement a query. */
+  /**
+   * Returns a function that checks that a particular MongoDB pipeline is
+   * generated to implement a query.
+   *
+   * @param strings Expected expressions
+   * @return validation function
+   */
   private static Function<List, Void> mongoChecker(final String... strings) {
     return new Function<List, Void>() {
       public Void apply(List actual) {

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
index 90bd759..d73f503 100644
--- a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
+++ b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
@@ -53,6 +53,7 @@ class MongoDatabaseRule extends ExternalResource {
 
   /**
    * Create an instance based on current maven profile (as defined by {@code -Pit}).
+   * @return new instance of the rule to be used by unit tests
    */
   static MongoDatabaseRule create() {
     final MongoClient client;

http://git-wip-us.apache.org/repos/asf/calcite/blob/4f835465/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java b/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
index 028286a..67626c3 100644
--- a/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
+++ b/mongodb/src/test/java/org/apache/calcite/test/MongoAssertions.java
@@ -40,8 +40,13 @@ public class MongoAssertions {
 
   private MongoAssertions() {}
 
-  /** Similar to {@link CalciteAssert#checkResultUnordered}, but filters strings
-   * before comparing them. */
+  /**
+   * Similar to {@link CalciteAssert#checkResultUnordered}, but filters strings
+   * before comparing them.
+   *
+   * @param lines Expected expressions
+   * @return validation function
+   */
   public static Function<ResultSet, Void> checkResultUnordered(
       final String... lines) {
     return new Function<ResultSet, Void>() {
@@ -73,6 +78,8 @@ public class MongoAssertions {
    * Whether to run Mongo integration tests. Enabled by default, however test is only
    * included if "it" profile is activated ({@code -Pit}). To disable,
    * specify {@code -Dcalcite.test.mongodb=false} on the Java command line.
+   *
+   * @return Whether current tests should use an external mongo instance
    */
   public static boolean useMongo() {
     return Util.getBooleanProperty("calcite.integrationTest")
@@ -81,12 +88,14 @@ public class MongoAssertions {
 
   /**
    * Checks wherever tests should use Fongo instead of Mongo. Opposite of {@link #useMongo()}.
+   *
+   * @return Whether current tests should use embedded
+   * <a href="https://github.com/fakemongo/fongo">Fongo</a> instance
    */
   public static boolean useFongo() {
     return !useMongo();
   }
 
-
   /**
    * Used to skip tests if current instance is not mongo. Some functionalities
    * are not available in fongo.


[2/3] calcite git commit: Fix-up for [CALCITE-2345] and [CALCITE-2347]

Posted by jh...@apache.org.
http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5AdapterTest.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5AdapterTest.java
new file mode 100644
index 0000000..9dedbda
--- /dev/null
+++ b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/Elasticsearch5AdapterTest.java
@@ -0,0 +1,405 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.adapter.elasticsearch5;
+
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.ViewTable;
+import org.apache.calcite.schema.impl.ViewTableMacro;
+import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ElasticsearchChecker;
+
+import com.google.common.io.LineProcessor;
+import com.google.common.io.Resources;
+
+import org.elasticsearch.action.bulk.BulkItemResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.action.support.WriteRequest;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentType;
+
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Locale;
+
+/**
+ * Set of tests for the Elasticsearch 5 adapter.
+ *
+ * <p>Uses a real instance via {@link EmbeddedElasticsearchPolicy}.
+ * The document source is a local {@code zips-mini.json} file
+ * (located in the classpath).
+ */
+public class Elasticsearch5AdapterTest {
+
+  @ClassRule // init once for all tests
+  public static final EmbeddedElasticsearchPolicy POLICY =
+      EmbeddedElasticsearchPolicy.create();
+
+  private static final String ZIPS = "zips";
+
+  /**
+   * Used to create {@code zips} index and insert some data
+   *
+   * @throws Exception when ES instance setup failed
+   */
+  @BeforeClass
+  public static void setupInstance() throws Exception {
+    // define mapping so fields are searchable (term query)
+    XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
+        .startObject("properties")
+        .startObject("city").field("type", "string")
+        .field("index", "not_analyzed").endObject()
+        .startObject("state").field("type", "string")
+        .field("index", "not_analyzed").endObject()
+        .startObject("pop").field("type", "long").endObject()
+        .endObject()
+        .endObject();
+
+    // create index
+    POLICY.client().admin().indices()
+        .prepareCreate(ZIPS)
+        .addMapping(ZIPS, mapping)
+        .get();
+
+    BulkRequestBuilder bulk = POLICY.client().prepareBulk()
+        .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
+
+    // load records from file
+    Resources.readLines(Elasticsearch5AdapterTest.class.getResource("/zips-mini.json"),
+        StandardCharsets.UTF_8, new LineProcessor<Void>() {
+          @Override public boolean processLine(String line) throws IOException {
+            line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
+            bulk.add(POLICY.client().prepareIndex(ZIPS, ZIPS)
+                .setSource(line.getBytes(StandardCharsets.UTF_8), XContentType.JSON));
+            return true;
+          }
+
+          @Override public Void getResult() {
+            return null;
+          }
+        });
+
+    if (bulk.numberOfActions() == 0) {
+      throw new IllegalStateException("No records to be indexed");
+    }
+
+    BulkResponse response = bulk.execute().get();
+
+    if (response.hasFailures()) {
+      throw new IllegalStateException(
+          String.format(Locale.getDefault(), "Failed to populate %s:\n%s", POLICY.httpAddress(),
+              Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
+                  .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
+    }
+
+  }
+
+  private CalciteAssert.ConnectionFactory newConnectionFactory() {
+    return new CalciteAssert.ConnectionFactory() {
+      @Override public Connection createConnection() throws SQLException {
+        final Connection connection = DriverManager.getConnection("jdbc:calcite:");
+        final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
+
+        root.add("elastic", new Elasticsearch5Schema(POLICY.client(), ZIPS));
+
+        // add calcite view programmatically
+        final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
+            + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
+            + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
+            + " cast(_MAP['pop'] AS integer) AS \"pop\", "
+            +  " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
+            +  " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
+            +  "from \"elastic\".\"zips\"";
+
+        ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
+            Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
+        root.add("ZIPS", macro);
+
+        return connection;
+      }
+    };
+  }
+
+  private CalciteAssert.AssertThat calciteAssert() {
+    return CalciteAssert.that()
+        .with(newConnectionFactory());
+  }
+
+  /**
+   * Tests using calcite view
+   */
+  @Test
+  public void view() {
+    calciteAssert()
+        .query("select * from zips where \"city\" = 'BROOKLYN'")
+        .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
+            + "pop=111396; state=NY; id=11226\n")
+        .returnsCount(1);
+  }
+
+  @Test
+  public void emptyResult() {
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from zips limit 0")
+        .returnsCount(0);
+
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
+        .returnsCount(0);
+  }
+
+  @Test
+  public void basic() throws Exception {
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
+        .returnsCount(1);
+
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where"
+            + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
+        .returnsCount(2);
+
+    // lower-case
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where "
+            + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
+        .returnsCount(0);
+
+    // missing field
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
+        .returnsCount(0);
+
+    // limit works
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" limit 42")
+        .returnsCount(42);
+
+  }
+
+  @Test public void testSort() {
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
+        + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "      ElasticsearchTableScan(table=[[elastic, zips]])";
+
+    calciteAssert()
+        .query("select * from zips order by \"state\"")
+        .returnsCount(10)
+        .explainContains(explain);
+  }
+
+  @Test public void testSortLimit() {
+    final String sql = "select \"state\", \"pop\" from zips\n"
+        + "order by \"state\", \"pop\" offset 2 rows fetch next 3 rows only";
+    calciteAssert()
+        .query(sql)
+        .returnsUnordered("state=AK; pop=32383",
+            "state=AL; pop=42124",
+            "state=AL; pop=43862")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"_source\" : [\"state\", \"pop\"]",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]",
+                "\"from\": 2",
+                "\"size\": 3"));
+  }
+
+
+
+  @Test public void testOffsetLimit() {
+    final String sql = "select \"state\", \"id\" from zips\n"
+        + "offset 2 fetch next 3 rows only";
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"from\": 2",
+                "\"size\": 3",
+                "\"_source\" : [\"state\", \"id\"]"));
+  }
+
+  @Test public void testLimit() {
+    final String sql = "select \"state\", \"id\" from zips\n"
+        + "fetch next 3 rows only";
+
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"size\": 3",
+                "\"_source\" : [\"state\", \"id\"]"));
+  }
+
+  @Test public void testFilterSort() {
+    final String sql = "select * from zips\n"
+        + "where \"state\" = 'CA' and \"pop\" >= 94000\n"
+        + "order by \"state\", \"pop\"";
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchSort(sort0=[$4], sort1=[$3], dir0=[ASC], dir1=[ASC])\n"
+        + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "      ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'pop')):INTEGER, 94000))])\n"
+        + "        ElasticsearchTableScan(table=[[elastic, zips]])\n\n";
+    calciteAssert()
+        .query(sql)
+        .returnsOrdered("city=NORWALK; longitude=-118.081767; latitude=33.90564;"
+                + " pop=94188; state=CA; id=90650",
+            "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856;"
+                + " pop=96074; state=CA; id=90011",
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177;"
+                + " pop=99568; state=CA; id=90201")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker("\"query\" : "
+                    + "{\"constant_score\":{\"filter\":{\"bool\":"
+                    + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
+                    + "{\"range\":{\"pop\":{\"gte\":94000}}}]}}}}",
+                "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
+                    + "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
+                    + "\"city\":{\"script\": \"params._source.city\"}, "
+                    + "\"pop\":{\"script\": \"params._source.pop\"}, "
+                    + "\"state\":{\"script\": \"params._source.state\"}, "
+                    + "\"id\":{\"script\": \"params._source.id\"}}",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]"))
+        .explainContains(explain);
+  }
+
+  @Test public void testFilterSortDesc() {
+    final String sql = "select * from zips\n"
+        + "where \"pop\" BETWEEN 95000 AND 100000\n"
+        + "order by \"state\" desc, \"pop\"";
+    calciteAssert()
+        .query(sql)
+        .limit(4)
+        .returnsOrdered(
+            "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
+  }
+
+  @Test public void testFilterRedundant() {
+    final String sql = "select * from zips\n"
+        + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(""
+                    + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+                    + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
+                "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
+                    +  "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
+                    +   "\"city\":{\"script\": \"params._source.city\"}, "
+                    +   "\"pop\":{\"script\": \"params._source.pop\"}, \"state\":{\"script\": \"params._source.state\"}, "
+                    +            "\"id\":{\"script\": \"params._source.id\"}}"
+            ));
+  }
+
+  @Test public void testInPlan() {
+    final String[] searches = {
+        "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
+            + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
+            + "{\"pop\":99568}}]}}]}}}}",
+        "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
+            +  "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
+            +  "\"city\":{\"script\": \"params._source.city\"}, "
+            +  "\"pop\":{\"script\": \"params._source.pop\"}, "
+            +  "\"state\":{\"script\": \"params._source.state\"}, "
+            +  "\"id\":{\"script\": \"params._source.id\"}}"
+    };
+
+    calciteAssert()
+        .query("select * from zips where \"pop\" in (96074, 99568)")
+        .returnsUnordered(
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
+            "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011"
+        )
+        .queryContains(ElasticsearchChecker.elasticsearchChecker(searches));
+  }
+
+  @Test public void testZips() {
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips")
+        .returnsCount(10);
+  }
+
+  @Test public void testProject() {
+    final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
+        + "from zips\n"
+        + "order by \"state\", \"city\"";
+
+    calciteAssert()
+        .query(sql)
+        .limit(2)
+        .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
+            "state=AK; city=FAIRBANKS; zero=0")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker("\"script_fields\": "
+                    + "{\"zero\":{\"script\": \"0\"}, "
+                    + "\"state\":{\"script\": \"params._source.state\"}, "
+                    + "\"city\":{\"script\": \"params._source.city\"}}",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
+  }
+
+  @Test public void testFilter() {
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "    ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
+        + "      ElasticsearchTableScan(table=[[elastic, zips]])";
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
+        .limit(3)
+        .returnsUnordered("state=CA; city=BELL GARDENS",
+            "state=CA; city=LOS ANGELES",
+            "state=CA; city=NORWALK")
+        .explainContains(explain);
+  }
+
+  @Test public void testFilterReversed() {
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
+        .limit(2)
+        .returnsUnordered("state=WV; city=BECKLEY",
+            "state=WY; city=CHEYENNE");
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
+        .limit(2)
+        .returnsUnordered("state=WV; city=BECKLEY",
+            "state=WY; city=CHEYENNE");
+  }
+
+}
+
+// End Elasticsearch5AdapterTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
index d603d87..cd8af9a 100644
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
+++ b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchNode.java
@@ -118,7 +118,7 @@ class EmbeddedElasticsearchNode implements AutoCloseable {
   }
 
   /**
-   * Exposes elastic
+   * Exposes an Elasticsearch
    * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
    * (use of HTTP client is preferred).
    *

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
new file mode 100644
index 0000000..6db2ddb
--- /dev/null
+++ b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.transport.TransportAddress;
+
+import org.junit.rules.ExternalResource;
+
+/**
+ * Junit rule that is used to initialize a single Elasticsearch node for tests.
+ *
+ * <p>For performance reasons (node startup costs),
+ * the same instance is usually shared across multiple tests.
+ *
+ * <p>This rule should be used as follows:
+ * <pre>
+ *
+ *  public class MyTest {
+ *    &#64;ClassRule
+ *    public static final ElasticSearchRule RULE = ElasticSearchRule.create();
+ *
+ *    &#64;BeforeClass
+ *    public static void setup() {
+ *       // ... populate instance
+ *    }
+ *
+ *    &#64;Test
+ *    public void myTest() {
+ *      TransportAddress address = RULE.httpAddress();
+ *      // .... (connect to ES)
+ *    }
+ *  }
+ * </pre>
+ *
+ * @see ExternalResource
+ */
+class EmbeddedElasticsearchPolicy extends ExternalResource {
+
+  private final EmbeddedElasticsearchNode node;
+
+  private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
+    this.node = Preconditions.checkNotNull(resource, "resource");
+  }
+
+  @Override protected void before() throws Throwable {
+    node.start();
+  }
+
+  @Override protected void after() {
+    try {
+      node.close();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Factory method to create this rule.
+   *
+   * @return new rule instance to be used in unit tests
+   */
+  public static EmbeddedElasticsearchPolicy create() {
+    return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
+  }
+
+  /**
+   * Exposes current ES transport client.
+   * @return running (and initialized) instance of ES node
+   */
+  Client client() {
+    return node.client();
+  }
+
+  /**
+   * HTTP address for rest clients (can be ES native or any other).
+   *
+   * @return {@code HTTP} connection parameters
+   */
+  TransportAddress httpAddress() {
+    return node.httpAddress();
+  }
+
+
+}
+
+// End EmbeddedElasticsearchPolicy.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java b/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
new file mode 100644
index 0000000..550c04c
--- /dev/null
+++ b/elasticsearch5/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.test;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for Elasticsearch tests.
+ */
+public class ElasticsearchChecker {
+
+  private ElasticsearchChecker() {}
+
+  /**
+   * Returns a function that checks that a particular Elasticsearch pipeline is
+   * generated to implement a query.
+   *
+   * @param strings expected expressions
+   * @return validation function
+   */
+  public static Function<List, Void> elasticsearchChecker(final String... strings) {
+    return new Function<List, Void>() {
+      @Nullable
+      @Override public Void apply(@Nullable List actual) {
+        Object[] actualArray = actual == null || actual.isEmpty() ? null
+            : ((List) actual.get(0)).toArray();
+        CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
+            actualArray);
+        return null;
+      }
+    };
+  }
+}
+
+// End ElasticsearchChecker.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/resources/log4j2.xml b/elasticsearch5/src/test/resources/log4j2.xml
index b38aca2..0a12b9c 100644
--- a/elasticsearch5/src/test/resources/log4j2.xml
+++ b/elasticsearch5/src/test/resources/log4j2.xml
@@ -13,4 +13,4 @@
             <AppenderRef ref="console" />
         </Root>
     </Loggers>
-</Configuration>
\ No newline at end of file
+</Configuration>

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/resources/zips-mini.json
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/resources/zips-mini.json b/elasticsearch5/src/test/resources/zips-mini.json
index d70eadc..858117a 100644
--- a/elasticsearch5/src/test/resources/zips-mini.json
+++ b/elasticsearch5/src/test/resources/zips-mini.json
@@ -146,4 +146,4 @@
 { "_id" : "98310", "city" : "BREMERTON", "loc" : [ -122.629913, 47.601916 ], "pop" : 49057, "state" : "WA" }
 { "_id" : "99504", "city" : "ANCHORAGE", "loc" : [ -149.74467, 61.203696 ], "pop" : 32383, "state" : "AK" }
 { "_id" : "99709", "city" : "FAIRBANKS", "loc" : [ -147.846917, 64.85437 ], "pop" : 23238, "state" : "AK" }
-{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }
\ No newline at end of file
+{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
index a4d8900..d6a45d9 100644
--- a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
+++ b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoAdapterTest.java
@@ -22,7 +22,6 @@ import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.test.CalciteAssert;
 import org.apache.calcite.test.MongoAssertions;
 
-
 import org.apache.calcite.util.Bug;
 import org.apache.calcite.util.Util;
 
@@ -65,6 +64,8 @@ import java.util.Map;
  * Testing mongo adapter functionality. By default runs with
  * <a href="https://github.com/fakemongo/fongo">Fongo</a> unless {@code IT} maven profile is enabled
  * (via {@code $ mvn -Pit install}).
+ *
+ * @see MongoDatabasePolicy
  */
 public class MongoAdapterTest implements SchemaFactory {
 
@@ -75,27 +76,27 @@ public class MongoAdapterTest implements SchemaFactory {
   protected static final int ZIPS_SIZE = 149;
 
   @ClassRule
-  public static final MongoDatabaseRule RULE = MongoDatabaseRule.create();
+  public static final MongoDatabasePolicy POLICY = MongoDatabasePolicy.create();
 
   private static MongoSchema schema;
 
   @BeforeClass
   public static void setUp() throws Exception {
-    MongoDatabase database = RULE.database();
+    MongoDatabase database = POLICY.database();
 
     populate(database.getCollection("zips"), MongoAdapterTest.class.getResource("/zips-mini.json"));
     populate(database.getCollection("store"), FoodmartJson.class.getResource("/store.json"));
     populate(database.getCollection("warehouse"),
-            FoodmartJson.class.getResource("/warehouse.json"));
+        FoodmartJson.class.getResource("/warehouse.json"));
 
     // Manually insert data for data-time test.
     MongoCollection<BsonDocument> datatypes =  database.getCollection("datatypes")
-            .withDocumentClass(BsonDocument.class);
+        .withDocumentClass(BsonDocument.class);
     if (datatypes.count() > 0) {
       datatypes.deleteMany(new BsonDocument());
     }
     BsonDocument doc = new BsonDocument();
-    Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse("2012-09-05");
+    Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT).parse("2012-09-05");
     doc.put("date", new BsonDateTime(date.getTime()));
     doc.put("value", new BsonInt32(1231));
     doc.put("ownerId", new BsonString("531e7789e4b0853ddb861313"));
@@ -105,7 +106,7 @@ public class MongoAdapterTest implements SchemaFactory {
   }
 
   private static void populate(MongoCollection<Document> collection, URL resource)
-          throws IOException {
+      throws IOException {
     Preconditions.checkNotNull(collection, "collection");
 
     if (collection.count() > 0) {
@@ -130,7 +131,7 @@ public class MongoAdapterTest implements SchemaFactory {
    *  Returns always the same schema to avoid initialization costs.
    */
   @Override public Schema create(SchemaPlus parentSchema, String name,
-                                 Map<String, Object> operand) {
+      Map<String, Object> operand) {
     return schema;
   }
 
@@ -139,7 +140,7 @@ public class MongoAdapterTest implements SchemaFactory {
     model = model.replace(MongoSchemaFactory.class.getName(), MongoAdapterTest.class.getName());
 
     return CalciteAssert.that()
-            .withModel(model);
+        .withModel(model);
   }
 
   private CalciteAssert.AssertThat assertModel(URL url) {
@@ -151,53 +152,52 @@ public class MongoAdapterTest implements SchemaFactory {
     }
   }
 
-  @Test
-  public void testSort() {
+  @Test public void testSort() {
     assertModel(MODEL)
-            .query("select * from zips order by state")
-            .returnsCount(ZIPS_SIZE)
-            .explainContains("PLAN=MongoToEnumerableConverter\n"
-                    + "  MongoSort(sort0=[$4], dir0=[ASC])\n"
-                    + "    MongoProject(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"
-                    + "      MongoTableScan(table=[[mongo_raw, zips]])");
+        .query("select * from zips order by state")
+        .returnsCount(ZIPS_SIZE)
+        .explainContains("PLAN=MongoToEnumerableConverter\n"
+            + "  MongoSort(sort0=[$4], dir0=[ASC])\n"
+            + "    MongoProject(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"
+            + "      MongoTableScan(table=[[mongo_raw, zips]])");
   }
 
   @Test public void testSortLimit() {
     assertModel(MODEL)
-            .query("select state, id from zips\n"
-                    + "order by state, id offset 2 rows fetch next 3 rows only")
-            .returnsOrdered("STATE=AK; ID=99801",
-                    "STATE=AL; ID=35215",
-                    "STATE=AL; ID=35401")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state', ID: '$_id'}}",
-                            "{$sort: {STATE: 1, ID: 1}}",
-                            "{$skip: 2}",
-                            "{$limit: 3}"));
+        .query("select state, id from zips\n"
+            + "order by state, id offset 2 rows fetch next 3 rows only")
+        .returnsOrdered("STATE=AK; ID=99801",
+            "STATE=AL; ID=35215",
+            "STATE=AL; ID=35401")
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state', ID: '$_id'}}",
+                "{$sort: {STATE: 1, ID: 1}}",
+                "{$skip: 2}",
+                "{$limit: 3}"));
   }
 
   @Test public void testOffsetLimit() {
     assertModel(MODEL)
-            .query("select state, id from zips\n"
-                    + "offset 2 fetch next 3 rows only")
-            .runs()
-            .queryContains(
-                    mongoChecker(
-                            "{$skip: 2}",
-                            "{$limit: 3}",
-                            "{$project: {STATE: '$state', ID: '$_id'}}"));
+        .query("select state, id from zips\n"
+            + "offset 2 fetch next 3 rows only")
+        .runs()
+        .queryContains(
+            mongoChecker(
+                "{$skip: 2}",
+                "{$limit: 3}",
+                "{$project: {STATE: '$state', ID: '$_id'}}"));
   }
 
   @Test public void testLimit() {
     assertModel(MODEL)
-            .query("select state, id from zips\n"
-                    + "fetch next 3 rows only")
-            .runs()
-            .queryContains(
-                    mongoChecker(
-                            "{$limit: 3}",
-                            "{$project: {STATE: '$state', ID: '$_id'}}"));
+        .query("select state, id from zips\n"
+            + "fetch next 3 rows only")
+        .runs()
+        .queryContains(
+            mongoChecker(
+                "{$limit: 3}",
+                "{$project: {STATE: '$state', ID: '$_id'}}"));
   }
 
   @Ignore
@@ -205,76 +205,76 @@ public class MongoAdapterTest implements SchemaFactory {
     // LONGITUDE and LATITUDE are null because of CALCITE-194.
     Util.discard(Bug.CALCITE_194_FIXED);
     assertModel(MODEL)
-            .query("select * from zips\n"
-                    + "where city = 'SPRINGFIELD' and id >= '70000'\n"
-                    + "order by state, id")
-            .returns(""
-                    + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=752; STATE=AR; ID=72157\n"
-                    + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=1992; STATE=CO; ID=81073\n"
-                    + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=5597; STATE=LA; ID=70462\n"
-                    + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=32384; STATE=OR; ID=97477\n"
-                    + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=27521; STATE=OR; ID=97478\n")
-            .queryContains(
-                    mongoChecker(
-                            "{\n"
-                                    + "  $match: {\n"
-                                    + "    city: \"SPRINGFIELD\",\n"
-                                    + "    _id: {\n"
-                                    + "      $gte: \"70000\"\n"
-                                    + "    }\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {CITY: '$city', LONGITUDE: '$loc[0]', LATITUDE: '$loc[1]', POP: '$pop', STATE: '$state', ID: '$_id'}}",
-                            "{$sort: {STATE: 1, ID: 1}}"))
-            .explainContains("PLAN=MongoToEnumerableConverter\n"
-                    + "  MongoSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
-                    + "    MongoProject(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"
-                    + "      MongoFilter(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"
-                    + "        MongoTableScan(table=[[mongo_raw, zips]])");
+        .query("select * from zips\n"
+            + "where city = 'SPRINGFIELD' and id >= '70000'\n"
+            + "order by state, id")
+        .returns(""
+            + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=752; STATE=AR; ID=72157\n"
+            + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=1992; STATE=CO; ID=81073\n"
+            + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=5597; STATE=LA; ID=70462\n"
+            + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=32384; STATE=OR; ID=97477\n"
+            + "CITY=SPRINGFIELD; LONGITUDE=null; LATITUDE=null; POP=27521; STATE=OR; ID=97478\n")
+        .queryContains(
+            mongoChecker(
+                "{\n"
+                    + "  $match: {\n"
+                    + "    city: \"SPRINGFIELD\",\n"
+                    + "    _id: {\n"
+                    + "      $gte: \"70000\"\n"
+                    + "    }\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {CITY: '$city', LONGITUDE: '$loc[0]', LATITUDE: '$loc[1]', POP: '$pop', STATE: '$state', ID: '$_id'}}",
+                "{$sort: {STATE: 1, ID: 1}}"))
+        .explainContains("PLAN=MongoToEnumerableConverter\n"
+            + "  MongoSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
+            + "    MongoProject(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"
+            + "      MongoFilter(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"
+            + "        MongoTableScan(table=[[mongo_raw, zips]])");
   }
 
   @Test public void testFilterSortDesc() {
     assertModel(MODEL)
-            .query("select * from zips\n"
-                    + "where pop BETWEEN 45000 AND 46000\n"
-                    + "order by state desc, pop")
-            .limit(4)
-            .returnsOrdered(
-                  "CITY=BECKLEY; LONGITUDE=null; LATITUDE=null; POP=45196; STATE=WV; ID=25801",
-                  "CITY=ROCKERVILLE; LONGITUDE=null; LATITUDE=null; POP=45328; STATE=SD; ID=57701",
-                  "CITY=PAWTUCKET; LONGITUDE=null; LATITUDE=null; POP=45442; STATE=RI; ID=02860",
-                  "CITY=LAWTON; LONGITUDE=null; LATITUDE=null; POP=45542; STATE=OK; ID=73505");
+        .query("select * from zips\n"
+            + "where pop BETWEEN 45000 AND 46000\n"
+            + "order by state desc, pop")
+        .limit(4)
+        .returnsOrdered(
+            "CITY=BECKLEY; LONGITUDE=null; LATITUDE=null; POP=45196; STATE=WV; ID=25801",
+            "CITY=ROCKERVILLE; LONGITUDE=null; LATITUDE=null; POP=45328; STATE=SD; ID=57701",
+            "CITY=PAWTUCKET; LONGITUDE=null; LATITUDE=null; POP=45442; STATE=RI; ID=02860",
+            "CITY=LAWTON; LONGITUDE=null; LATITUDE=null; POP=45542; STATE=OK; ID=73505");
   }
 
   @Ignore("broken; [CALCITE-2115] is logged to fix it")
   @Test public void testUnionPlan() {
     assertModel(MODEL)
-            .query("select * from \"sales_fact_1997\"\n"
-                    + "union all\n"
-                    + "select * from \"sales_fact_1998\"")
-            .explainContains("PLAN=EnumerableUnion(all=[true])\n"
-                    + "  MongoToEnumerableConverter\n"
-                    + "    MongoProject(product_id=[CAST(ITEM($0, 'product_id')):DOUBLE])\n"
-                    + "      MongoTableScan(table=[[_foodmart, sales_fact_1997]])\n"
-                    + "  MongoToEnumerableConverter\n"
-                    + "    MongoProject(product_id=[CAST(ITEM($0, 'product_id')):DOUBLE])\n"
-                    + "      MongoTableScan(table=[[_foodmart, sales_fact_1998]])")
-            .limit(2)
-            .returns(
-                    MongoAssertions.checkResultUnordered(
-                            "product_id=337", "product_id=1512"));
+        .query("select * from \"sales_fact_1997\"\n"
+            + "union all\n"
+            + "select * from \"sales_fact_1998\"")
+        .explainContains("PLAN=EnumerableUnion(all=[true])\n"
+            + "  MongoToEnumerableConverter\n"
+            + "    MongoProject(product_id=[CAST(ITEM($0, 'product_id')):DOUBLE])\n"
+            + "      MongoTableScan(table=[[_foodmart, sales_fact_1997]])\n"
+            + "  MongoToEnumerableConverter\n"
+            + "    MongoProject(product_id=[CAST(ITEM($0, 'product_id')):DOUBLE])\n"
+            + "      MongoTableScan(table=[[_foodmart, sales_fact_1998]])")
+        .limit(2)
+        .returns(
+            MongoAssertions.checkResultUnordered(
+                "product_id=337", "product_id=1512"));
   }
 
   @Ignore(
-          "java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double")
+      "java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double")
   @Test public void testFilterUnionPlan() {
     assertModel(MODEL)
-            .query("select * from (\n"
-                    + "  select * from \"sales_fact_1997\"\n"
-                    + "  union all\n"
-                    + "  select * from \"sales_fact_1998\")\n"
-                    + "where \"product_id\" = 1")
-            .runs();
+        .query("select * from (\n"
+            + "  select * from \"sales_fact_1997\"\n"
+            + "  union all\n"
+            + "  select * from \"sales_fact_1998\")\n"
+            + "where \"product_id\" = 1")
+        .runs();
   }
 
   /** Tests that we don't generate multiple constraints on the same column.
@@ -282,111 +282,111 @@ public class MongoAdapterTest implements SchemaFactory {
    * operators. */
   @Test public void testFilterRedundant() {
     assertModel(MODEL)
-            .query(
-                    "select * from zips where state > 'CA' and state < 'AZ' and state = 'OK'")
-            .runs()
-            .queryContains(
-                    mongoChecker(
-                            "{\n"
-                                    + "  \"$match\": {\n"
-                                    + "    \"state\": \"OK\"\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {CITY: '$city', LONGITUDE: '$loc[0]', LATITUDE: '$loc[1]', POP: '$pop', STATE: '$state', ID: '$_id'}}"));
+        .query(
+            "select * from zips where state > 'CA' and state < 'AZ' and state = 'OK'")
+        .runs()
+        .queryContains(
+            mongoChecker(
+                "{\n"
+                    + "  \"$match\": {\n"
+                    + "    \"state\": \"OK\"\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {CITY: '$city', LONGITUDE: '$loc[0]', LATITUDE: '$loc[1]', POP: '$pop', STATE: '$state', ID: '$_id'}}"));
   }
 
   @Test public void testSelectWhere() {
     assertModel(MODEL)
-            .query(
-                    "select * from \"warehouse\" where \"warehouse_state_province\" = 'CA'")
-            .explainContains("PLAN=MongoToEnumerableConverter\n"
-                    + "  MongoProject(warehouse_id=[CAST(ITEM($0, 'warehouse_id')):DOUBLE], warehouse_state_province=[CAST(ITEM($0, 'warehouse_state_province')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-                    + "    MongoFilter(condition=[=(CAST(ITEM($0, 'warehouse_state_province')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
-                    + "      MongoTableScan(table=[[mongo_raw, warehouse]])")
-            .returns(
-                    MongoAssertions.checkResultUnordered(
-                            "warehouse_id=6; warehouse_state_province=CA",
-                            "warehouse_id=7; warehouse_state_province=CA",
-                            "warehouse_id=14; warehouse_state_province=CA",
-                            "warehouse_id=24; warehouse_state_province=CA"))
-            .queryContains(
-                    // Per https://issues.apache.org/jira/browse/CALCITE-164,
-                    // $match must occur before $project for good performance.
-                    mongoChecker(
-                            "{\n"
-                                    + "  \"$match\": {\n"
-                                    + "    \"warehouse_state_province\": \"CA\"\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {warehouse_id: 1, warehouse_state_province: 1}}"));
+        .query(
+            "select * from \"warehouse\" where \"warehouse_state_province\" = 'CA'")
+        .explainContains("PLAN=MongoToEnumerableConverter\n"
+            + "  MongoProject(warehouse_id=[CAST(ITEM($0, 'warehouse_id')):DOUBLE], warehouse_state_province=[CAST(ITEM($0, 'warehouse_state_province')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+            + "    MongoFilter(condition=[=(CAST(ITEM($0, 'warehouse_state_province')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
+            + "      MongoTableScan(table=[[mongo_raw, warehouse]])")
+        .returns(
+            MongoAssertions.checkResultUnordered(
+                "warehouse_id=6; warehouse_state_province=CA",
+                "warehouse_id=7; warehouse_state_province=CA",
+                "warehouse_id=14; warehouse_state_province=CA",
+                "warehouse_id=24; warehouse_state_province=CA"))
+        .queryContains(
+            // Per https://issues.apache.org/jira/browse/CALCITE-164,
+            // $match must occur before $project for good performance.
+            mongoChecker(
+                "{\n"
+                    + "  \"$match\": {\n"
+                    + "    \"warehouse_state_province\": \"CA\"\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {warehouse_id: 1, warehouse_state_province: 1}}"));
   }
 
   @Test public void testInPlan() {
     assertModel(MODEL)
-            .query("select \"store_id\", \"store_name\" from \"store\"\n"
-                    + "where \"store_name\" in ('Store 1', 'Store 10', 'Store 11', 'Store 15', 'Store 16', 'Store 24', 'Store 3', 'Store 7')")
-            .returns(
-                    MongoAssertions.checkResultUnordered(
-                            "store_id=1; store_name=Store 1",
-                            "store_id=3; store_name=Store 3",
-                            "store_id=7; store_name=Store 7",
-                            "store_id=10; store_name=Store 10",
-                            "store_id=11; store_name=Store 11",
-                            "store_id=15; store_name=Store 15",
-                            "store_id=16; store_name=Store 16",
-                            "store_id=24; store_name=Store 24"))
-            .queryContains(
-                    mongoChecker(
-                            "{\n"
-                                    + "  \"$match\": {\n"
-                                    + "    \"$or\": [\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 1\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 10\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 11\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 15\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 16\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 24\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 3\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"store_name\": \"Store 7\"\n"
-                                    + "      }\n"
-                                    + "    ]\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {store_id: 1, store_name: 1}}"));
+        .query("select \"store_id\", \"store_name\" from \"store\"\n"
+            + "where \"store_name\" in ('Store 1', 'Store 10', 'Store 11', 'Store 15', 'Store 16', 'Store 24', 'Store 3', 'Store 7')")
+        .returns(
+            MongoAssertions.checkResultUnordered(
+                "store_id=1; store_name=Store 1",
+                "store_id=3; store_name=Store 3",
+                "store_id=7; store_name=Store 7",
+                "store_id=10; store_name=Store 10",
+                "store_id=11; store_name=Store 11",
+                "store_id=15; store_name=Store 15",
+                "store_id=16; store_name=Store 16",
+                "store_id=24; store_name=Store 24"))
+        .queryContains(
+            mongoChecker(
+                "{\n"
+                    + "  \"$match\": {\n"
+                    + "    \"$or\": [\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 1\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 10\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 11\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 15\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 16\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 24\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 3\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"store_name\": \"Store 7\"\n"
+                    + "      }\n"
+                    + "    ]\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {store_id: 1, store_name: 1}}"));
   }
 
   /** Simple query based on the "mongo-zips" model. */
   @Test public void testZips() {
     assertModel(MODEL)
-            .query("select state, city from zips")
-            .returnsCount(ZIPS_SIZE);
+        .query("select state, city from zips")
+        .returnsCount(ZIPS_SIZE);
   }
 
   @Test public void testCountGroupByEmpty() {
     assertModel(MODEL)
-            .query("select count(*) from zips")
-            .returns(String.format(Locale.getDefault(), "EXPR$0=%d\n", ZIPS_SIZE))
-            .explainContains("PLAN=MongoToEnumerableConverter\n"
-                    + "  MongoAggregate(group=[{}], EXPR$0=[COUNT()])\n"
-                    + "    MongoTableScan(table=[[mongo_raw, zips]])")
-            .queryContains(
-                    mongoChecker(
-                            "{$group: {_id: {}, 'EXPR$0': {$sum: 1}}}"));
+        .query("select count(*) from zips")
+        .returns(String.format(Locale.ROOT, "EXPR$0=%d\n", ZIPS_SIZE))
+        .explainContains("PLAN=MongoToEnumerableConverter\n"
+            + "  MongoAggregate(group=[{}], EXPR$0=[COUNT()])\n"
+            + "    MongoTableScan(table=[[mongo_raw, zips]])")
+        .queryContains(
+            mongoChecker(
+                "{$group: {_id: {}, 'EXPR$0': {$sum: 1}}}"));
   }
 
   @Test public void testCountGroupByEmptyMultiplyBy2() {
@@ -394,197 +394,197 @@ public class MongoAdapterTest implements SchemaFactory {
     MongoAssertions.assumeRealMongoInstance();
 
     assertModel(MODEL)
-            .query("select count(*)*2 from zips")
-            .returns(String.format(Locale.getDefault(), "EXPR$0=%d\n", ZIPS_SIZE * 2))
-            .queryContains(
-                    mongoChecker(
-                            "{$group: {_id: {}, _0: {$sum: 1}}}",
-                            "{$project: {'EXPR$0': {$multiply: ['$_0', {$literal: 2}]}}}"));
+        .query("select count(*)*2 from zips")
+        .returns(String.format(Locale.ROOT, "EXPR$0=%d\n", ZIPS_SIZE * 2))
+        .queryContains(
+            mongoChecker(
+                "{$group: {_id: {}, _0: {$sum: 1}}}",
+                "{$project: {'EXPR$0': {$multiply: ['$_0', {$literal: 2}]}}}"));
   }
 
   @Test public void testGroupByOneColumnNotProjected() {
     assertModel(MODEL)
-            .query("select count(*) from zips group by state order by 1")
-            .limit(2)
-            .returnsUnordered("EXPR$0=2",
-                    "EXPR$0=2")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', 'EXPR$0': {$sum: 1}}}",
-                            "{$project: {STATE: '$_id', 'EXPR$0': '$EXPR$0'}}",
-                            "{$project: {'EXPR$0': 1}}",
-                            "{$sort: {EXPR$0: 1}}"));
+        .query("select count(*) from zips group by state order by 1")
+        .limit(2)
+        .returnsUnordered("EXPR$0=2",
+            "EXPR$0=2")
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state'}}",
+                "{$group: {_id: '$STATE', 'EXPR$0': {$sum: 1}}}",
+                "{$project: {STATE: '$_id', 'EXPR$0': '$EXPR$0'}}",
+                "{$project: {'EXPR$0': 1}}",
+                "{$sort: {EXPR$0: 1}}"));
   }
 
   @Test public void testGroupByOneColumn() {
     assertModel(MODEL)
-            .query(
-                    "select state, count(*) as c from zips group by state order by state")
-            .limit(3)
-            .returns("STATE=AK; C=3\nSTATE=AL; C=3\nSTATE=AR; C=3\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', C: {$sum: 1}}}",
-                            "{$project: {STATE: '$_id', C: '$C'}}",
-                            "{$sort: {STATE: 1}}"));
+        .query(
+            "select state, count(*) as c from zips group by state order by state")
+        .limit(3)
+        .returns("STATE=AK; C=3\nSTATE=AL; C=3\nSTATE=AR; C=3\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state'}}",
+                "{$group: {_id: '$STATE', C: {$sum: 1}}}",
+                "{$project: {STATE: '$_id', C: '$C'}}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Test public void testGroupByOneColumnReversed() {
     // Note extra $project compared to testGroupByOneColumn.
     assertModel(MODEL)
-            .query(
-                    "select count(*) as c, state from zips group by state order by state")
-            .limit(2)
-            .returns("C=3; STATE=AK\nC=3; STATE=AL\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', C: {$sum: 1}}}",
-                            "{$project: {STATE: '$_id', C: '$C'}}",
-                            "{$project: {C: 1, STATE: 1}}",
-                            "{$sort: {STATE: 1}}"));
+        .query(
+            "select count(*) as c, state from zips group by state order by state")
+        .limit(2)
+        .returns("C=3; STATE=AK\nC=3; STATE=AL\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state'}}",
+                "{$group: {_id: '$STATE', C: {$sum: 1}}}",
+                "{$project: {STATE: '$_id', C: '$C'}}",
+                "{$project: {C: 1, STATE: 1}}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Test public void testGroupByAvg() {
     assertModel(MODEL)
-            .query(
-                    "select state, avg(pop) as a from zips group by state order by state")
-            .limit(2)
-            .returns("STATE=AK; A=26856\nSTATE=AL; A=43383\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {POP: '$pop', STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', A: {$avg: '$POP'}}}",
-                            "{$project: {STATE: '$_id', A: '$A'}}",
-                            "{$sort: {STATE: 1}}"));
+        .query(
+            "select state, avg(pop) as a from zips group by state order by state")
+        .limit(2)
+        .returns("STATE=AK; A=26856\nSTATE=AL; A=43383\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {POP: '$pop', STATE: '$state'}}",
+                "{$group: {_id: '$STATE', A: {$avg: '$POP'}}}",
+                "{$project: {STATE: '$_id', A: '$A'}}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Test public void testGroupByAvgSumCount() {
     // This operation not supported by fongo: https://github.com/fakemongo/fongo/issues/152
     MongoAssertions.assumeRealMongoInstance();
     assertModel(MODEL)
-            .query(
-                    "select state, avg(pop) as a, sum(pop) as s, count(pop) as c from zips group by state order by state")
-            .limit(2)
-            .returns("STATE=AK; A=26856; S=80568; C=3\n"
-                    + "STATE=AL; A=43383; S=130151; C=3\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {POP: '$pop', STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', _1: {$sum: '$POP'}, _2: {$sum: {$cond: [ {$eq: ['POP', null]}, 0, 1]}}}}",
-                            "{$project: {STATE: '$_id', _1: '$_1', _2: '$_2'}}",
-                            "{$sort: {STATE: 1}}",
-                            "{$project: {STATE: 1, A: {$divide: [{$cond:[{$eq: ['$_2', {$literal: 0}]},null,'$_1']}, '$_2']}, S: {$cond:[{$eq: ['$_2', {$literal: 0}]},null,'$_1']}, C: '$_2'}}"));
+        .query(
+            "select state, avg(pop) as a, sum(pop) as s, count(pop) as c from zips group by state order by state")
+        .limit(2)
+        .returns("STATE=AK; A=26856; S=80568; C=3\n"
+            + "STATE=AL; A=43383; S=130151; C=3\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {POP: '$pop', STATE: '$state'}}",
+                "{$group: {_id: '$STATE', _1: {$sum: '$POP'}, _2: {$sum: {$cond: [ {$eq: ['POP', null]}, 0, 1]}}}}",
+                "{$project: {STATE: '$_id', _1: '$_1', _2: '$_2'}}",
+                "{$sort: {STATE: 1}}",
+                "{$project: {STATE: 1, A: {$divide: [{$cond:[{$eq: ['$_2', {$literal: 0}]},null,'$_1']}, '$_2']}, S: {$cond:[{$eq: ['$_2', {$literal: 0}]},null,'$_1']}, C: '$_2'}}"));
   }
 
   @Test public void testGroupByHaving() {
     assertModel(MODEL)
-            .query("select state, count(*) as c from zips\n"
-                    + "group by state having count(*) > 2 order by state")
-            .returnsCount(47)
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', C: {$sum: 1}}}",
-                            "{$project: {STATE: '$_id', C: '$C'}}",
-                            "{\n"
-                                    + "  \"$match\": {\n"
-                                    + "    \"C\": {\n"
-                                    + "      \"$gt\": 2\n"
-                                    + "    }\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$sort: {STATE: 1}}"));
+        .query("select state, count(*) as c from zips\n"
+            + "group by state having count(*) > 2 order by state")
+        .returnsCount(47)
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state'}}",
+                "{$group: {_id: '$STATE', C: {$sum: 1}}}",
+                "{$project: {STATE: '$_id', C: '$C'}}",
+                "{\n"
+                    + "  \"$match\": {\n"
+                    + "    \"C\": {\n"
+                    + "      \"$gt\": 2\n"
+                    + "    }\n"
+                    + "  }\n"
+                    + "}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Ignore("https://issues.apache.org/jira/browse/CALCITE-270")
   @Test public void testGroupByHaving2() {
     assertModel(MODEL)
-            .query("select state, count(*) as c from zips\n"
-                    + "group by state having sum(pop) > 12000000")
-            .returns("STATE=NY; C=1596\n"
-                    + "STATE=TX; C=1676\n"
-                    + "STATE=FL; C=826\n"
-                    + "STATE=CA; C=1523\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {STATE: '$state', POP: '$pop'}}",
-                            "{$group: {_id: '$STATE', C: {$sum: 1}, _2: {$sum: '$POP'}}}",
-                            "{$project: {STATE: '$_id', C: '$C', _2: '$_2'}}",
-                            "{\n"
-                                    + "  $match: {\n"
-                                    + "    _2: {\n"
-                                    + "      $gt: 12000000\n"
-                                    + "    }\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {STATE: 1, C: 1}}"));
+        .query("select state, count(*) as c from zips\n"
+            + "group by state having sum(pop) > 12000000")
+        .returns("STATE=NY; C=1596\n"
+            + "STATE=TX; C=1676\n"
+            + "STATE=FL; C=826\n"
+            + "STATE=CA; C=1523\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {STATE: '$state', POP: '$pop'}}",
+                "{$group: {_id: '$STATE', C: {$sum: 1}, _2: {$sum: '$POP'}}}",
+                "{$project: {STATE: '$_id', C: '$C', _2: '$_2'}}",
+                "{\n"
+                    + "  $match: {\n"
+                    + "    _2: {\n"
+                    + "      $gt: 12000000\n"
+                    + "    }\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {STATE: 1, C: 1}}"));
   }
 
   @Test public void testGroupByMinMaxSum() {
     assertModel(MODEL)
-            .query("select count(*) as c, state,\n"
-                    + " min(pop) as min_pop, max(pop) as max_pop, sum(pop) as sum_pop\n"
-                    + "from zips group by state order by state")
-            .limit(2)
-            .returns("C=3; STATE=AK; MIN_POP=23238; MAX_POP=32383; SUM_POP=80568\n"
-                    + "C=3; STATE=AL; MIN_POP=42124; MAX_POP=44165; SUM_POP=130151\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {POP: '$pop', STATE: '$state'}}",
-                            "{$group: {_id: '$STATE', C: {$sum: 1}, MIN_POP: {$min: '$POP'}, MAX_POP: {$max: '$POP'}, SUM_POP: {$sum: '$POP'}}}",
-                            "{$project: {STATE: '$_id', C: '$C', MIN_POP: '$MIN_POP', MAX_POP: '$MAX_POP', SUM_POP: '$SUM_POP'}}",
-                            "{$project: {C: 1, STATE: 1, MIN_POP: 1, MAX_POP: 1, SUM_POP: 1}}",
-                            "{$sort: {STATE: 1}}"));
+        .query("select count(*) as c, state,\n"
+            + " min(pop) as min_pop, max(pop) as max_pop, sum(pop) as sum_pop\n"
+            + "from zips group by state order by state")
+        .limit(2)
+        .returns("C=3; STATE=AK; MIN_POP=23238; MAX_POP=32383; SUM_POP=80568\n"
+            + "C=3; STATE=AL; MIN_POP=42124; MAX_POP=44165; SUM_POP=130151\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {POP: '$pop', STATE: '$state'}}",
+                "{$group: {_id: '$STATE', C: {$sum: 1}, MIN_POP: {$min: '$POP'}, MAX_POP: {$max: '$POP'}, SUM_POP: {$sum: '$POP'}}}",
+                "{$project: {STATE: '$_id', C: '$C', MIN_POP: '$MIN_POP', MAX_POP: '$MAX_POP', SUM_POP: '$SUM_POP'}}",
+                "{$project: {C: 1, STATE: 1, MIN_POP: 1, MAX_POP: 1, SUM_POP: 1}}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Test public void testGroupComposite() {
     assertModel(MODEL)
-            .query("select count(*) as c, state, city from zips\n"
-                    + "group by state, city\n"
-                    + "order by c desc, city\n"
-                    + "limit 2")
-            .returns("C=1; STATE=SD; CITY=ABERDEEN\n"
-                      + "C=1; STATE=SC; CITY=AIKEN\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {CITY: '$city', STATE: '$state'}}",
-                            "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}, C: {$sum: 1}}}",
-                            "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE', C: '$C'}}",
-                            "{$sort: {C: -1, CITY: 1}}",
-                            "{$limit: 2}",
-                            "{$project: {C: 1, STATE: 1, CITY: 1}}"));
+        .query("select count(*) as c, state, city from zips\n"
+            + "group by state, city\n"
+            + "order by c desc, city\n"
+            + "limit 2")
+        .returns("C=1; STATE=SD; CITY=ABERDEEN\n"
+            + "C=1; STATE=SC; CITY=AIKEN\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {CITY: '$city', STATE: '$state'}}",
+                "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}, C: {$sum: 1}}}",
+                "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE', C: '$C'}}",
+                "{$sort: {C: -1, CITY: 1}}",
+                "{$limit: 2}",
+                "{$project: {C: 1, STATE: 1, CITY: 1}}"));
   }
 
   @Ignore("broken; [CALCITE-2115] is logged to fix it")
   @Test public void testDistinctCount() {
     assertModel(MODEL)
-            .query("select state, count(distinct city) as cdc from zips\n"
-                    + "where state in ('CA', 'TX') group by state order by state")
-            .returns("STATE=CA; CDC=1072\n"
-                    + "STATE=TX; CDC=1233\n")
-            .queryContains(
-                    mongoChecker(
-                            "{\n"
-                                    + "  \"$match\": {\n"
-                                    + "    \"$or\": [\n"
-                                    + "      {\n"
-                                    + "        \"state\": \"CA\"\n"
-                                    + "      },\n"
-                                    + "      {\n"
-                                    + "        \"state\": \"TX\"\n"
-                                    + "      }\n"
-                                    + "    ]\n"
-                                    + "  }\n"
-                                    + "}",
-                            "{$project: {CITY: '$city', STATE: '$state'}}",
-                            "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}}}",
-                            "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE'}}",
-                            "{$group: {_id: '$STATE', CDC: {$sum: {$cond: [ {$eq: ['CITY', null]}, 0, 1]}}}}",
-                            "{$project: {STATE: '$_id', CDC: '$CDC'}}",
-                            "{$sort: {STATE: 1}}"));
+        .query("select state, count(distinct city) as cdc from zips\n"
+            + "where state in ('CA', 'TX') group by state order by state")
+        .returns("STATE=CA; CDC=1072\n"
+            + "STATE=TX; CDC=1233\n")
+        .queryContains(
+            mongoChecker(
+                "{\n"
+                    + "  \"$match\": {\n"
+                    + "    \"$or\": [\n"
+                    + "      {\n"
+                    + "        \"state\": \"CA\"\n"
+                    + "      },\n"
+                    + "      {\n"
+                    + "        \"state\": \"TX\"\n"
+                    + "      }\n"
+                    + "    ]\n"
+                    + "  }\n"
+                    + "}",
+                "{$project: {CITY: '$city', STATE: '$state'}}",
+                "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}}}",
+                "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE'}}",
+                "{$group: {_id: '$STATE', CDC: {$sum: {$cond: [ {$eq: ['CITY', null]}, 0, 1]}}}}",
+                "{$project: {STATE: '$_id', CDC: '$CDC'}}",
+                "{$sort: {STATE: 1}}"));
   }
 
   @Test public void testDistinctCountOrderBy() {
@@ -592,52 +592,52 @@ public class MongoAdapterTest implements SchemaFactory {
     // https://github.com/fakemongo/fongo/issues/152
     MongoAssertions.assumeRealMongoInstance();
     assertModel(MODEL)
-            .query("select state, count(distinct city) as cdc\n"
-                    + "from zips\n"
-                    + "group by state\n"
-                    + "order by cdc desc, state\n"
-                    + "limit 5")
-            .returns("STATE=AK; CDC=3\n"
-                    + "STATE=AL; CDC=3\n"
-                    + "STATE=AR; CDC=3\n"
-                    + "STATE=AZ; CDC=3\n"
-                    + "STATE=CA; CDC=3\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {CITY: '$city', STATE: '$state'}}",
-                            "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}}}",
-                            "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE'}}",
-                            "{$group: {_id: '$STATE', CDC: {$sum: {$cond: [ {$eq: ['CITY', null]}, 0, 1]}}}}",
-                            "{$project: {STATE: '$_id', CDC: '$CDC'}}",
-                            "{$sort: {CDC: -1, STATE: 1}}",
-                            "{$limit: 5}"));
+        .query("select state, count(distinct city) as cdc\n"
+            + "from zips\n"
+            + "group by state\n"
+            + "order by cdc desc, state\n"
+            + "limit 5")
+        .returns("STATE=AK; CDC=3\n"
+            + "STATE=AL; CDC=3\n"
+            + "STATE=AR; CDC=3\n"
+            + "STATE=AZ; CDC=3\n"
+            + "STATE=CA; CDC=3\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {CITY: '$city', STATE: '$state'}}",
+                "{$group: {_id: {CITY: '$CITY', STATE: '$STATE'}}}",
+                "{$project: {_id: 0, CITY: '$_id.CITY', STATE: '$_id.STATE'}}",
+                "{$group: {_id: '$STATE', CDC: {$sum: {$cond: [ {$eq: ['CITY', null]}, 0, 1]}}}}",
+                "{$project: {STATE: '$_id', CDC: '$CDC'}}",
+                "{$sort: {CDC: -1, STATE: 1}}",
+                "{$limit: 5}"));
   }
 
   @Ignore("broken; [CALCITE-2115] is logged to fix it")
   @Test public void testProject() {
     assertModel(MODEL)
-            .query("select state, city, 0 as zero from zips order by state, city")
-            .limit(2)
-            .returns("STATE=AK; CITY=AKHIOK; ZERO=0\n"
-                    + "STATE=AK; CITY=AKIACHAK; ZERO=0\n")
-            .queryContains(
-                    mongoChecker(
-                            "{$project: {CITY: '$city', STATE: '$state'}}",
-                            "{$sort: {STATE: 1, CITY: 1}}",
-                            "{$project: {STATE: 1, CITY: 1, ZERO: {$literal: 0}}}"));
+        .query("select state, city, 0 as zero from zips order by state, city")
+        .limit(2)
+        .returns("STATE=AK; CITY=AKHIOK; ZERO=0\n"
+            + "STATE=AK; CITY=AKIACHAK; ZERO=0\n")
+        .queryContains(
+            mongoChecker(
+                "{$project: {CITY: '$city', STATE: '$state'}}",
+                "{$sort: {STATE: 1, CITY: 1}}",
+                "{$project: {STATE: 1, CITY: 1, ZERO: {$literal: 0}}}"));
   }
 
   @Test public void testFilter() {
     assertModel(MODEL)
-            .query("select state, city from zips where state = 'CA'")
-            .limit(3)
-            .returnsUnordered("STATE=CA; CITY=LOS ANGELES",
-                      "STATE=CA; CITY=BELL GARDENS",
-                      "STATE=CA; CITY=NORWALK")
-            .explainContains("PLAN=MongoToEnumerableConverter\n"
-                    + "  MongoProject(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"
-                    + "    MongoFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
-                    + "      MongoTableScan(table=[[mongo_raw, zips]])");
+        .query("select state, city from zips where state = 'CA'")
+        .limit(3)
+        .returnsUnordered("STATE=CA; CITY=LOS ANGELES",
+            "STATE=CA; CITY=BELL GARDENS",
+            "STATE=CA; CITY=NORWALK")
+        .explainContains("PLAN=MongoToEnumerableConverter\n"
+            + "  MongoProject(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"
+            + "    MongoFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
+            + "      MongoTableScan(table=[[mongo_raw, zips]])");
   }
 
   /** MongoDB's predicates are handed (they can only accept literals on the
@@ -645,18 +645,18 @@ public class MongoAdapterTest implements SchemaFactory {
    * ways around. */
   @Test public void testFilterReversed() {
     assertModel(MODEL)
-            .query("select state, city from zips where 'WI' < state order by state, city")
-            .limit(3)
-            .returnsOrdered("STATE=WV; CITY=BECKLEY",
-                            "STATE=WV; CITY=ELM GROVE",
-                            "STATE=WV; CITY=STAR CITY");
+        .query("select state, city from zips where 'WI' < state order by state, city")
+        .limit(3)
+        .returnsOrdered("STATE=WV; CITY=BECKLEY",
+            "STATE=WV; CITY=ELM GROVE",
+            "STATE=WV; CITY=STAR CITY");
 
     assertModel(MODEL)
-            .query("select state, city from zips where state > 'WI' order by state, city")
-            .limit(3)
-            .returnsOrdered("STATE=WV; CITY=BECKLEY",
-                    "STATE=WV; CITY=ELM GROVE",
-                    "STATE=WV; CITY=STAR CITY");
+        .query("select state, city from zips where state > 'WI' order by state, city")
+        .limit(3)
+        .returnsOrdered("STATE=WV; CITY=BECKLEY",
+            "STATE=WV; CITY=ELM GROVE",
+            "STATE=WV; CITY=STAR CITY");
   }
 
   /** MongoDB's predicates are handed (they can only accept literals on the
@@ -684,13 +684,13 @@ public class MongoAdapterTest implements SchemaFactory {
 
   private void checkPredicate(int expected, String q) {
     assertModel(MODEL)
-            .query("select count(*) as c from zips\n"
-                    + q)
-            .returns("C=" + expected + "\n");
+        .query("select count(*) as c from zips\n"
+            + q)
+        .returns("C=" + expected + "\n");
     assertModel(MODEL)
-            .query("select * from zips\n"
-                    + q)
-            .returnsCount(expected);
+        .query("select * from zips\n"
+            + q)
+        .returnsCount(expected);
   }
 
   /** Test case for
@@ -713,22 +713,22 @@ public class MongoAdapterTest implements SchemaFactory {
     //     "ownerId" : "531e7789e4b0853ddb861313"
     //   } )
     assertModel("{\n"
-            + "  version: '1.0',\n"
-            + "  defaultSchema: 'test',\n"
-            + "   schemas: [\n"
-            + "     {\n"
-            + "       type: 'custom',\n"
-            + "       name: 'test',\n"
-            + "       factory: 'org.apache.calcite.adapter.mongodb.MongoSchemaFactory',\n"
-            + "       operand: {\n"
-            + "         host: 'localhost',\n"
-            + "         database: 'test'\n"
-            + "       }\n"
-            + "     }\n"
-            + "   ]\n"
-            + "}")
-            .query("select cast(_MAP['date'] as DATE) from \"datatypes\"")
-            .returnsUnordered("EXPR$0=2012-09-05");
+        + "  version: '1.0',\n"
+        + "  defaultSchema: 'test',\n"
+        + "   schemas: [\n"
+        + "     {\n"
+        + "       type: 'custom',\n"
+        + "       name: 'test',\n"
+        + "       factory: 'org.apache.calcite.adapter.mongodb.MongoSchemaFactory',\n"
+        + "       operand: {\n"
+        + "         host: 'localhost',\n"
+        + "         database: 'test'\n"
+        + "       }\n"
+        + "     }\n"
+        + "   ]\n"
+        + "}")
+        .query("select cast(_MAP['date'] as DATE) from \"datatypes\"")
+        .returnsUnordered("EXPR$0=2012-09-05");
   }
 
   /** Test case for
@@ -762,11 +762,11 @@ public class MongoAdapterTest implements SchemaFactory {
     return new Function<List, Void>() {
       public Void apply(List actual) {
         Object[] actualArray =
-                actual == null || actual.isEmpty()
-                        ? null
-                        : ((List) actual.get(0)).toArray();
+            actual == null || actual.isEmpty()
+                ? null
+                : ((List) actual.get(0)).toArray();
         CalciteAssert.assertArrayEqual("expected MongoDB query not found",
-                strings, actualArray);
+            strings, actualArray);
         return null;
       }
     };

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabasePolicy.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabasePolicy.java b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabasePolicy.java
new file mode 100644
index 0000000..52a0715
--- /dev/null
+++ b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabasePolicy.java
@@ -0,0 +1,84 @@
+/*
+ * 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.mongodb;
+
+import org.apache.calcite.test.MongoAssertions;
+
+import com.github.fakemongo.Fongo;
+
+import com.google.common.base.Preconditions;
+
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoDatabase;
+
+import org.junit.rules.ExternalResource;
+
+/**
+ * Instantiates a new connection to Fongo (or Mongo) database depending on the
+ * current profile (unit or integration tests).
+ *
+ * <p>By default, this rule is executed as part of a unit test and in-memory database
+ * <a href="https://github.com/fakemongo/fongo">Fongo</a> is used.
+ *
+ * <p>However, if the maven profile is set to {@code IT} (eg. via command line
+ * {@code $ mvn -Pit install}) this rule will connect to an existing (external)
+ * Mongo instance ({@code localhost}).
+ */
+class MongoDatabasePolicy extends ExternalResource {
+
+  private static final String DB_NAME = "test";
+
+  private final MongoDatabase database;
+  private final MongoClient client;
+
+  private MongoDatabasePolicy(MongoClient client) {
+    this.client = Preconditions.checkNotNull(client, "client");
+    this.database = client.getDatabase(DB_NAME);
+  }
+
+  /**
+   * Creates an instance based on current maven profile (as defined by {@code -Pit}).
+   *
+   * @return new instance of the policy to be used by unit tests
+   */
+  static MongoDatabasePolicy create() {
+    final MongoClient client;
+    if (MongoAssertions.useMongo()) {
+      // use to real client (connects to mongo)
+      client = new MongoClient();
+    } else if (MongoAssertions.useFongo()) {
+      // in-memory DB (fake Mongo)
+      client = new Fongo(MongoDatabasePolicy.class.getSimpleName()).getMongo();
+    } else {
+      throw new UnsupportedOperationException("I can only connect to Mongo or Fongo instances");
+    }
+
+    return new MongoDatabasePolicy(client);
+  }
+
+
+  MongoDatabase database() {
+    return database;
+  }
+
+  @Override protected void after() {
+    client.close();
+  }
+
+}
+
+// End MongoDatabasePolicy.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java b/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
deleted file mode 100644
index d73f503..0000000
--- a/mongodb/src/test/java/org/apache/calcite/adapter/mongodb/MongoDatabaseRule.java
+++ /dev/null
@@ -1,84 +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.mongodb;
-
-import org.apache.calcite.test.MongoAssertions;
-
-import com.github.fakemongo.Fongo;
-
-import com.google.common.base.Preconditions;
-
-import com.mongodb.MongoClient;
-import com.mongodb.client.MongoDatabase;
-
-import org.junit.rules.ExternalResource;
-
-/**
- * Instantiates new connection to fongo (or mongo) database depending on current profile
- * (unit or integration tests).
- *
- * By default, this rule is executed as part of a unit test and in-memory database
- * <a href="https://github.com/fakemongo/fongo">fongo</a> is used.
- *
- * <p>However, if maven profile is set to {@code IT} (eg. via command line
- * {@code $ mvn -Pit install}) this rule will connect to existing (external)
- * mongo instance ({@code localhost})</p>
- *
- */
-class MongoDatabaseRule extends ExternalResource {
-
-  private static final String DB_NAME = "test";
-
-  private final MongoDatabase database;
-  private final MongoClient client;
-
-  private MongoDatabaseRule(MongoClient client) {
-    this.client = Preconditions.checkNotNull(client, "client");
-    this.database = client.getDatabase(DB_NAME);
-  }
-
-  /**
-   * Create an instance based on current maven profile (as defined by {@code -Pit}).
-   * @return new instance of the rule to be used by unit tests
-   */
-  static MongoDatabaseRule create() {
-    final MongoClient client;
-    if (MongoAssertions.useMongo()) {
-      // use to real client (connects to mongo)
-      client = new MongoClient();
-    } else if (MongoAssertions.useFongo()) {
-      // in-memory DB (fake Mongo)
-      client = new Fongo(MongoDatabaseRule.class.getSimpleName()).getMongo();
-    } else {
-      throw new UnsupportedOperationException("I can only connect to Mongo or Fongo instances");
-    }
-
-    return new MongoDatabaseRule(client);
-  }
-
-
-  MongoDatabase database() {
-    return database;
-  }
-
-  @Override protected void after() {
-    client.close();
-  }
-
-}
-
-// End MongoDatabaseRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
----------------------------------------------------------------------
diff --git a/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java b/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
index 207a3b9..218dba3 100644
--- a/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
+++ b/mongodb/src/test/java/org/apache/calcite/test/MongoAdapterIT.java
@@ -25,10 +25,10 @@ import static org.junit.Assume.assumeTrue;
 /**
  * Used to trigger integration tests from maven (thus class name is suffixed with {@code IT}).
  *
- * If you want to run integration tests from IDE manually set
+ * <p>If you want to run integration tests from the, IDE manually set the
  * {@code -Dcalcite.integrationTest=true} system property.
- * <br>
- * For command line use:
+ *
+ * <p>For command line use:
  * <pre>
  *     $ mvn install -Pit
  * </pre>

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/mongodb/src/test/resources/zips-mini.json
----------------------------------------------------------------------
diff --git a/mongodb/src/test/resources/zips-mini.json b/mongodb/src/test/resources/zips-mini.json
index d70eadc..858117a 100644
--- a/mongodb/src/test/resources/zips-mini.json
+++ b/mongodb/src/test/resources/zips-mini.json
@@ -146,4 +146,4 @@
 { "_id" : "98310", "city" : "BREMERTON", "loc" : [ -122.629913, 47.601916 ], "pop" : 49057, "state" : "WA" }
 { "_id" : "99504", "city" : "ANCHORAGE", "loc" : [ -149.74467, 61.203696 ], "pop" : 32383, "state" : "AK" }
 { "_id" : "99709", "city" : "FAIRBANKS", "loc" : [ -147.846917, 64.85437 ], "pop" : 23238, "state" : "AK" }
-{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }
\ No newline at end of file
+{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }


[3/3] calcite git commit: Fix-up for [CALCITE-2345] and [CALCITE-2347]

Posted by jh...@apache.org.
Fix-up for [CALCITE-2345] and [CALCITE-2347]

Terminology: Standardize on Elasticsearch, not Elastic or ElasticSearch.

Rename MongoDatabaseRule to MongoDatabasePolicy to avoid confusion
with planner rule classes; similarly ElasticsearchPolicy.

Use project standard indentation.

Ensure that files end in newlines.


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

Branch: refs/heads/master
Commit: 6e8bb5a16c9c8c0397b79f3e98c0134ab9a32fb3
Parents: 4f83546
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Jun 14 22:06:27 2018 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Mon Jun 25 21:27:04 2018 -0700

----------------------------------------------------------------------
 .../java/org/apache/calcite/util/UtilTest.java  |   1 +
 .../org/apache/calcite/test/DruidAdapterIT.java |   4 +-
 .../apache/calcite/test/DruidAdapterIT2.java    |   4 +-
 .../Elasticsearch2Enumerator.java               |   2 +-
 .../ElasticSearch2AdapterTest.java              | 397 ---------
 .../Elasticsearch2AdapterTest.java              | 398 +++++++++
 .../elasticsearch2/EmbeddedElasticNode.java     | 154 ----
 .../elasticsearch2/EmbeddedElasticRule.java     | 108 ---
 .../EmbeddedElasticsearchNode.java              | 154 ++++
 .../EmbeddedElasticsearchPolicy.java            | 102 +++
 .../org/apache/calcite/test/ElasticChecker.java |  53 --
 .../calcite/test/ElasticsearchChecker.java      |  53 ++
 .../src/test/resources/zips-mini.json           |   2 +-
 .../ElasticSearch5AdapterTest.java              | 401 ---------
 .../Elasticsearch5AdapterTest.java              | 405 +++++++++
 .../EmbeddedElasticsearchNode.java              |   2 +-
 .../EmbeddedElasticsearchPolicy.java            | 103 +++
 .../calcite/test/ElasticsearchChecker.java      |  53 ++
 elasticsearch5/src/test/resources/log4j2.xml    |   2 +-
 .../src/test/resources/zips-mini.json           |   2 +-
 .../adapter/mongodb/MongoAdapterTest.java       | 812 +++++++++----------
 .../adapter/mongodb/MongoDatabasePolicy.java    |  84 ++
 .../adapter/mongodb/MongoDatabaseRule.java      |  84 --
 .../org/apache/calcite/test/MongoAdapterIT.java |   6 +-
 mongodb/src/test/resources/zips-mini.json       |   2 +-
 25 files changed, 1772 insertions(+), 1616 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/core/src/test/java/org/apache/calcite/util/UtilTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java
index 96f810f..4560fd5 100644
--- a/core/src/test/java/org/apache/calcite/util/UtilTest.java
+++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java
@@ -843,6 +843,7 @@ public class UtilTest {
         Locale.getDefault(),
         Locale.US,
         Locale.TRADITIONAL_CHINESE,
+        Locale.ROOT,
     };
     for (Locale locale : locales) {
       assertEquals(locale, Util.parseLocale(locale.toString()));

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
----------------------------------------------------------------------
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
index 2a57303..36940b8 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT.java
@@ -71,8 +71,8 @@ import static org.junit.Assert.assertTrue;
  *   <li>push HAVING into "groupBy" query</li>
  * </ul>
  *
- * These tests use "timestamp with local time zone" type for the
- * Druid timestamp column, instead of "timestamp" type  as
+ * <p>These tests use TIMESTAMP WITH LOCAL TIME ZONE type for the
+ * Druid timestamp column, instead of TIMESTAMP type as
  * {@link DruidAdapterIT2}.
  */
 public class DruidAdapterIT {

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
----------------------------------------------------------------------
diff --git a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
index 64f26de..c673c7c 100644
--- a/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
+++ b/druid/src/test/java/org/apache/calcite/test/DruidAdapterIT2.java
@@ -71,8 +71,8 @@ import static org.junit.Assert.assertTrue;
  *   <li>push HAVING into "groupBy" query</li>
  * </ul>
  *
- * These tests use "timestamp" type for the Druid timestamp column, instead
- * of "timestamp with local time zone" type as {@link DruidAdapterIT}.
+ * <p>These tests use TIMESTAMP type for the Druid timestamp column, instead
+ * of TIMESTAMP WITH LOCAL TIME ZONE type as {@link DruidAdapterIT}.
  */
 public class DruidAdapterIT2 {
   /** URL of the "druid-foodmart" model. */

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
index 8247957..62aa197 100644
--- a/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
+++ b/elasticsearch2/src/main/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2Enumerator.java
@@ -115,7 +115,7 @@ public class Elasticsearch2Enumerator implements Enumerator<Object> {
             objects[i] = convert(hit.field(name).getValue(), field.getValue());
           } else {
             throw new IllegalStateException(
-                    String.format(Locale.getDefault(), "No result for %s", field));
+                String.format(Locale.ROOT, "No result for %s", field));
           }
         }
         return objects;

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
deleted file mode 100644
index a7eff8f..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/ElasticSearch2AdapterTest.java
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.schema.impl.ViewTable;
-import org.apache.calcite.schema.impl.ViewTableMacro;
-import org.apache.calcite.test.CalciteAssert;
-import org.apache.calcite.test.ElasticChecker;
-
-import com.google.common.io.LineProcessor;
-import com.google.common.io.Resources;
-
-import org.elasticsearch.action.bulk.BulkItemResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Locale;
-
-/**
- * Set of tests for ES adapter. Uses real instance via {@link EmbeddedElasticRule}. Document
- * source is local {@code zips-mini.json} file (located in the classpath).
- */
-public class ElasticSearch2AdapterTest {
-
-  @ClassRule //init once for all tests
-  public static final EmbeddedElasticRule NODE = EmbeddedElasticRule.create();
-
-  private static final String ZIPS = "zips";
-
-  /**
-   * Used to create {@code zips} index and insert some data
-   *
-   * @throws Exception when couldn't create the instance
-   */
-  @BeforeClass
-  public static void setupInstance() throws Exception {
-    // define mapping so fields are searchable (term query)
-    XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
-            .startObject("properties")
-            .startObject("city").field("type", "string")
-                  .field("index", "not_analyzed").endObject()
-            .startObject("state").field("type", "string")
-                  .field("index", "not_analyzed").endObject()
-            .startObject("pop").field("type", "long").endObject()
-            .endObject()
-            .endObject();
-
-    // create index
-    NODE.client().admin().indices()
-            .prepareCreate(ZIPS)
-            .addMapping(ZIPS, mapping)
-            .get();
-
-    BulkRequestBuilder bulk = NODE.client().prepareBulk().setRefresh(true);
-
-    // load records from file
-    Resources.readLines(ElasticSearch2AdapterTest.class.getResource("/zips-mini.json"),
-            StandardCharsets.UTF_8, new LineProcessor<Void>() {
-              @Override public boolean processLine(String line) throws IOException {
-                line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
-                bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS).setSource(line));
-                return true;
-              }
-
-              @Override public Void getResult() {
-                return null;
-              }
-            });
-
-    if (bulk.numberOfActions() == 0) {
-      throw new IllegalStateException("No records to be indexed");
-    }
-
-    BulkResponse response = bulk.execute().get();
-
-    if (response.hasFailures()) {
-      throw new IllegalStateException(
-              String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
-              Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
-                      .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
-    }
-
-  }
-
-  private CalciteAssert.ConnectionFactory newConnectionFactory() {
-    return new CalciteAssert.ConnectionFactory() {
-      @Override public Connection createConnection() throws SQLException {
-        final Connection connection = DriverManager.getConnection("jdbc:calcite:");
-        final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
-
-        root.add("elastic", new Elasticsearch2Schema(NODE.client(), ZIPS));
-
-        // add calcite view programmatically
-        final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
-               + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
-               + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
-              + " cast(_MAP['pop'] AS integer) AS \"pop\", "
-              +  " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
-              +  " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
-              +  "from \"elastic\".\"zips\"";
-
-        ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
-                Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
-        root.add("ZIPS", macro);
-
-        return connection;
-      }
-    };
-  }
-
-  private CalciteAssert.AssertThat calciteAssert() {
-    return CalciteAssert.that()
-            .with(newConnectionFactory());
-  }
-
-  /**
-   * Tests using calcite view
-   */
-  @Test
-  public void view() {
-    calciteAssert()
-          .query("select * from zips where \"city\" = 'BROOKLYN'")
-          .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
-                  + "pop=111396; state=NY; id=11226\n")
-          .returnsCount(1);
-  }
-
-  @Test
-  public void emptyResult() {
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from zips limit 0")
-            .returnsCount(0);
-
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
-            .returnsCount(0);
-  }
-
-  @Test
-  public void basic() throws Exception {
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
-            .returnsCount(1);
-
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where"
-                    + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
-            .returnsCount(2);
-
-    // lower-case
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where "
-                    + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
-            .returnsCount(0);
-
-    // missing field
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
-            .returnsCount(0);
-
-    // limit works
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" limit 42")
-            .returnsCount(42);
-
-  }
-
-  @Test public void testSort() {
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
-            + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "      ElasticsearchTableScan(table=[[elastic, zips]])";
-
-    calciteAssert()
-            .query("select * from zips order by \"state\"")
-            .returnsCount(10)
-            .explainContains(explain);
-  }
-
-  @Test public void testSortLimit() {
-    final String sql = "select \"state\", \"id\" from zips\n"
-            + "order by \"state\", \"id\" offset 2 rows fetch next 3 rows only";
-    calciteAssert()
-            .query(sql)
-            .returnsUnordered("state=AK; id=99801",
-                    "state=AL; id=35215",
-                    "state=AL; id=35401")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"_source\" : [\"state\", \"id\"]",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]",
-                            "\"from\": 2",
-                            "\"size\": 3"));
-  }
-
-
-
-  @Test public void testOffsetLimit() {
-    final String sql = "select \"state\", \"id\" from zips\n"
-            + "offset 2 fetch next 3 rows only";
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"from\": 2",
-                            "\"size\": 3",
-                            "\"_source\" : [\"state\", \"id\"]"));
-  }
-
-  @Test public void testLimit() {
-    final String sql = "select \"state\", \"id\" from zips\n"
-            + "fetch next 3 rows only";
-
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"size\": 3",
-                            "\"_source\" : [\"state\", \"id\"]"));
-  }
-
-  @Test public void testFilterSort() {
-    final String sql = "select * from zips\n"
-            + "where \"state\" = 'CA' and \"id\" >= '70000'\n"
-            + "order by \"state\", \"id\"";
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
-            + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "      ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
-            + "        ElasticsearchTableScan(table=[[elastic, zips]])";
-    calciteAssert()
-            .query(sql)
-            .returnsOrdered("city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; "
-                            + "pop=96074; state=CA; id=90011",
-                    "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; "
-                            + "pop=99568; state=CA; id=90201",
-                    "city=NORWALK; longitude=-118.081767; latitude=33.90564; "
-                            + "pop=94188; state=CA; id=90650")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker("\"query\" : "
-                                    + "{\"constant_score\":{\"filter\":{\"bool\":"
-                                    + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
-                                    + "{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
-                            "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
-                                    + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
-                                    + "\"city\":{\"script\": \"_source.city\"}, "
-                                    + "\"pop\":{\"script\": \"_source.pop\"}, "
-                                    + "\"state\":{\"script\": \"_source.state\"}, "
-                                    + "\"id\":{\"script\": \"_source.id\"}}",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
-            .explainContains(explain);
-  }
-
-  @Test public void testFilterSortDesc() {
-    final String sql = "select * from zips\n"
-            + "where \"pop\" BETWEEN 95000 AND 100000\n"
-            + "order by \"state\" desc, \"pop\"";
-    calciteAssert()
-            .query(sql)
-            .limit(4)
-            .returnsOrdered(
-             "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
-             "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
-  }
-
-  @Test public void testFilterRedundant() {
-    final String sql = "select * from zips\n"
-            + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(""
-                                    + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
-                                    + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
-                            "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
-                                    +  "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
-                                    +   "\"city\":{\"script\": \"_source.city\"}, "
-                                    +   "\"pop\":{\"script\": \"_source.pop\"}, \"state\":{\"script\": \"_source.state\"}, "
-                                    +            "\"id\":{\"script\": \"_source.id\"}}"
-                    ));
-  }
-
-  @Test public void testInPlan() {
-    final String[] searches = {
-        "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
-                 + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
-                 + "{\"pop\":99568}}]}}]}}}}",
-        "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
-                 +  "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
-                 +  "\"city\":{\"script\": \"_source.city\"}, "
-                 +  "\"pop\":{\"script\": \"_source.pop\"}, "
-                 +  "\"state\":{\"script\": \"_source.state\"}, "
-                 +  "\"id\":{\"script\": \"_source.id\"}}"
-    };
-
-    calciteAssert()
-            .query("select * from zips where \"pop\" in (96074, 99568)")
-            .returnsUnordered(
-                    "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
-                    "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011"
-                    )
-            .queryContains(ElasticChecker.elasticsearchChecker(searches));
-  }
-
-  @Test public void testZips() {
-    calciteAssert()
-         .query("select \"state\", \"city\" from zips")
-         .returnsCount(10);
-  }
-
-  @Test public void testProject() {
-    final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
-            + "from zips\n"
-            + "order by \"state\", \"city\"";
-
-    calciteAssert()
-            .query(sql)
-            .limit(2)
-            .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
-                    "state=AK; city=FAIRBANKS; zero=0")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker("\"script_fields\": "
-                                    + "{\"zero\":{\"script\": \"0\"}, "
-                                    + "\"state\":{\"script\": \"_source.state\"}, "
-                                    + "\"city\":{\"script\": \"_source.city\"}}",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
-  }
-
-  @Test public void testFilter() {
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "    ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
-            + "      ElasticsearchTableScan(table=[[elastic, zips]])";
-    calciteAssert()
-            .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
-            .limit(3)
-            .returnsUnordered("state=CA; city=BELL GARDENS",
-                    "state=CA; city=LOS ANGELES",
-                    "state=CA; city=NORWALK")
-            .explainContains(explain);
-  }
-
-  @Test public void testFilterReversed() {
-    calciteAssert()
-          .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
-          .limit(2)
-          .returnsUnordered("state=WV; city=BECKLEY",
-                    "state=WY; city=CHEYENNE");
-    calciteAssert()
-          .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
-          .limit(2)
-          .returnsUnordered("state=WV; city=BECKLEY",
-                    "state=WY; city=CHEYENNE");
-  }
-
-}
-
-// End ElasticSearch2AdapterTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
new file mode 100644
index 0000000..8624ac7
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/Elasticsearch2AdapterTest.java
@@ -0,0 +1,398 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.ViewTable;
+import org.apache.calcite.schema.impl.ViewTableMacro;
+import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.ElasticsearchChecker;
+
+import com.google.common.io.LineProcessor;
+import com.google.common.io.Resources;
+
+import org.elasticsearch.action.bulk.BulkItemResponse;
+import org.elasticsearch.action.bulk.BulkRequestBuilder;
+import org.elasticsearch.action.bulk.BulkResponse;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Locale;
+
+/**
+ * Set of tests for the Elasticsearch 2 adapter.
+ *
+ * <p>Uses a real instance via {@link EmbeddedElasticsearchPolicy}.
+ * The document source is a local {@code zips-mini.json} file
+ * (located in the classpath).
+ */
+public class Elasticsearch2AdapterTest {
+
+  @ClassRule // init once for all tests
+  public static final EmbeddedElasticsearchPolicy NODE =
+      EmbeddedElasticsearchPolicy.create();
+
+  private static final String ZIPS = "zips";
+
+  /**
+   * Used to create {@code zips} index and insert some data
+   *
+   * @throws Exception when couldn't create the instance
+   */
+  @BeforeClass
+  public static void setupInstance() throws Exception {
+    // define mapping so fields are searchable (term query)
+    XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
+        .startObject("properties")
+        .startObject("city").field("type", "string")
+        .field("index", "not_analyzed").endObject()
+        .startObject("state").field("type", "string")
+        .field("index", "not_analyzed").endObject()
+        .startObject("pop").field("type", "long").endObject()
+        .endObject()
+        .endObject();
+
+    // create index
+    NODE.client().admin().indices()
+        .prepareCreate(ZIPS)
+        .addMapping(ZIPS, mapping)
+        .get();
+
+    BulkRequestBuilder bulk = NODE.client().prepareBulk().setRefresh(true);
+
+    // load records from file
+    Resources.readLines(Elasticsearch2AdapterTest.class.getResource("/zips-mini.json"),
+        StandardCharsets.UTF_8, new LineProcessor<Void>() {
+          @Override public boolean processLine(String line) throws IOException {
+            line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
+            bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS).setSource(line));
+            return true;
+          }
+
+          @Override public Void getResult() {
+            return null;
+          }
+        });
+
+    if (bulk.numberOfActions() == 0) {
+      throw new IllegalStateException("No records to be indexed");
+    }
+
+    BulkResponse response = bulk.execute().get();
+
+    if (response.hasFailures()) {
+      throw new IllegalStateException(
+          String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
+              Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
+                  .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
+    }
+
+  }
+
+  private CalciteAssert.ConnectionFactory newConnectionFactory() {
+    return new CalciteAssert.ConnectionFactory() {
+      @Override public Connection createConnection() throws SQLException {
+        final Connection connection = DriverManager.getConnection("jdbc:calcite:");
+        final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
+
+        root.add("elastic", new Elasticsearch2Schema(NODE.client(), ZIPS));
+
+        // add calcite view programmatically
+        final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
+            + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
+            + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
+            + " cast(_MAP['pop'] AS integer) AS \"pop\", "
+            +  " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
+            +  " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
+            +  "from \"elastic\".\"zips\"";
+
+        ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
+            Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
+        root.add("ZIPS", macro);
+
+        return connection;
+      }
+    };
+  }
+
+  private CalciteAssert.AssertThat calciteAssert() {
+    return CalciteAssert.that()
+        .with(newConnectionFactory());
+  }
+
+  /**
+   * Tests using calcite view
+   */
+  @Test
+  public void view() {
+    calciteAssert()
+        .query("select * from zips where \"city\" = 'BROOKLYN'")
+        .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
+            + "pop=111396; state=NY; id=11226\n")
+        .returnsCount(1);
+  }
+
+  @Test
+  public void emptyResult() {
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from zips limit 0")
+        .returnsCount(0);
+
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
+        .returnsCount(0);
+  }
+
+  @Test
+  public void basic() throws Exception {
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
+        .returnsCount(1);
+
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where"
+            + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
+        .returnsCount(2);
+
+    // lower-case
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where "
+            + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
+        .returnsCount(0);
+
+    // missing field
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
+        .returnsCount(0);
+
+    // limit works
+    CalciteAssert.that()
+        .with(newConnectionFactory())
+        .query("select * from \"elastic\".\"zips\" limit 42")
+        .returnsCount(42);
+
+  }
+
+  @Test public void testSort() {
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
+        + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "      ElasticsearchTableScan(table=[[elastic, zips]])";
+
+    calciteAssert()
+        .query("select * from zips order by \"state\"")
+        .returnsCount(10)
+        .explainContains(explain);
+  }
+
+  @Test public void testSortLimit() {
+    final String sql = "select \"state\", \"id\" from zips\n"
+        + "order by \"state\", \"id\" offset 2 rows fetch next 3 rows only";
+    calciteAssert()
+        .query(sql)
+        .returnsUnordered("state=AK; id=99801",
+            "state=AL; id=35215",
+            "state=AL; id=35401")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"_source\" : [\"state\", \"id\"]",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]",
+                "\"from\": 2",
+                "\"size\": 3"));
+  }
+
+
+
+  @Test public void testOffsetLimit() {
+    final String sql = "select \"state\", \"id\" from zips\n"
+        + "offset 2 fetch next 3 rows only";
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"from\": 2",
+                "\"size\": 3",
+                "\"_source\" : [\"state\", \"id\"]"));
+  }
+
+  @Test public void testLimit() {
+    final String sql = "select \"state\", \"id\" from zips\n"
+        + "fetch next 3 rows only";
+
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(
+                "\"size\": 3",
+                "\"_source\" : [\"state\", \"id\"]"));
+  }
+
+  @Test public void testFilterSort() {
+    final String sql = "select * from zips\n"
+        + "where \"state\" = 'CA' and \"id\" >= '70000'\n"
+        + "order by \"state\", \"id\"";
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchSort(sort0=[$4], sort1=[$5], dir0=[ASC], dir1=[ASC])\n"
+        + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "      ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", '70000'))])\n"
+        + "        ElasticsearchTableScan(table=[[elastic, zips]])";
+    calciteAssert()
+        .query(sql)
+        .returnsOrdered("city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; "
+                + "pop=96074; state=CA; id=90011",
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; "
+                + "pop=99568; state=CA; id=90201",
+            "city=NORWALK; longitude=-118.081767; latitude=33.90564; "
+                + "pop=94188; state=CA; id=90650")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker("\"query\" : "
+                    + "{\"constant_score\":{\"filter\":{\"bool\":"
+                    + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
+                    + "{\"range\":{\"id\":{\"gte\":\"70000\"}}}]}}}}",
+                "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+                    + "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+                    + "\"city\":{\"script\": \"_source.city\"}, "
+                    + "\"pop\":{\"script\": \"_source.pop\"}, "
+                    + "\"state\":{\"script\": \"_source.state\"}, "
+                    + "\"id\":{\"script\": \"_source.id\"}}",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"id\": \"asc\"}]"))
+        .explainContains(explain);
+  }
+
+  @Test public void testFilterSortDesc() {
+    final String sql = "select * from zips\n"
+        + "where \"pop\" BETWEEN 95000 AND 100000\n"
+        + "order by \"state\" desc, \"pop\"";
+    calciteAssert()
+        .query(sql)
+        .limit(4)
+        .returnsOrdered(
+            "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
+  }
+
+  @Test public void testFilterRedundant() {
+    final String sql = "select * from zips\n"
+        + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
+    calciteAssert()
+        .query(sql)
+        .runs()
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker(""
+                    + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
+                    + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
+                "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+                    +  "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+                    +   "\"city\":{\"script\": \"_source.city\"}, "
+                    +   "\"pop\":{\"script\": \"_source.pop\"}, \"state\":{\"script\": \"_source.state\"}, "
+                    +            "\"id\":{\"script\": \"_source.id\"}}"));
+  }
+
+  @Test public void testInPlan() {
+    final String[] searches = {
+        "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
+            + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
+            + "{\"pop\":99568}}]}}]}}}}",
+        "\"script_fields\": {\"longitude\":{\"script\":\"_source.loc[0]\"}, "
+            +  "\"latitude\":{\"script\":\"_source.loc[1]\"}, "
+            +  "\"city\":{\"script\": \"_source.city\"}, "
+            +  "\"pop\":{\"script\": \"_source.pop\"}, "
+            +  "\"state\":{\"script\": \"_source.state\"}, "
+            +  "\"id\":{\"script\": \"_source.id\"}}"
+    };
+
+    calciteAssert()
+        .query("select * from zips where \"pop\" in (96074, 99568)")
+        .returnsUnordered(
+            "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
+            "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011")
+        .queryContains(ElasticsearchChecker.elasticsearchChecker(searches));
+  }
+
+  @Test public void testZips() {
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips")
+        .returnsCount(10);
+  }
+
+  @Test public void testProject() {
+    final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
+        + "from zips\n"
+        + "order by \"state\", \"city\"";
+
+    calciteAssert()
+        .query(sql)
+        .limit(2)
+        .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
+            "state=AK; city=FAIRBANKS; zero=0")
+        .queryContains(
+            ElasticsearchChecker.elasticsearchChecker("\"script_fields\": "
+                    + "{\"zero\":{\"script\": \"0\"}, "
+                    + "\"state\":{\"script\": \"_source.state\"}, "
+                    + "\"city\":{\"script\": \"_source.city\"}}",
+                "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
+  }
+
+  @Test public void testFilter() {
+    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
+        + "  ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
+        + "    ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
+        + "      ElasticsearchTableScan(table=[[elastic, zips]])";
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
+        .limit(3)
+        .returnsUnordered("state=CA; city=BELL GARDENS",
+            "state=CA; city=LOS ANGELES",
+            "state=CA; city=NORWALK")
+        .explainContains(explain);
+  }
+
+  @Test public void testFilterReversed() {
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
+        .limit(2)
+        .returnsUnordered("state=WV; city=BECKLEY",
+            "state=WY; city=CHEYENNE");
+    calciteAssert()
+        .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
+        .limit(2)
+        .returnsUnordered("state=WV; city=BECKLEY",
+            "state=WY; city=CHEYENNE");
+  }
+
+}
+
+// End Elasticsearch2AdapterTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
deleted file mode 100644
index 55f83f9..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticNode.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import com.google.common.base.Preconditions;
-import com.google.common.io.Files;
-
-import org.elasticsearch.Version;
-import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
-import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.elasticsearch.node.Node;
-import org.elasticsearch.node.internal.InternalSettingsPreparer;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.script.groovy.GroovyPlugin;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * Represents a single elastic search node which can run embedded in a java application.
- * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
- */
-class EmbeddedElasticNode implements AutoCloseable {
-
-  private final LocalNode node;
-  private volatile boolean  isStarted;
-
-  private EmbeddedElasticNode(LocalNode node) {
-    this.node = Preconditions.checkNotNull(node, "node");
-  }
-
-  /**
-   * Having separate class to expose (protected) constructor which allows to install
-   * different plugins. In our case it is {@code GroovyPlugin} for scripted fields like
-   * {@code loc[0]} or {@code loc[1]['foo']}.
-   */
-  private static class LocalNode extends Node {
-    private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
-      super(InternalSettingsPreparer.prepareEnvironment(settings, null),
-          Version.CURRENT, classpathPlugins);
-    }
-  }
-
-  /**
-   * Creates an instance with existing settings
-   *
-   * @param settings ES settings for the node
-   * @return un-started node; call {@link #start()} to start the instance
-   */
-  private static EmbeddedElasticNode create(Settings settings) {
-    // ensure GroovyPlugin is installed or otherwise scripted fields would not work
-    LocalNode node = new LocalNode(settings, Collections.singleton(GroovyPlugin.class));
-    return new EmbeddedElasticNode(node);
-  }
-
-  /**
-   * Creates elastic node as single member of a cluster. Node will not be started
-   * unless {@link #start()} is explicitly called.
-   *
-   * @return node with default configuration
-   */
-  public static EmbeddedElasticNode create() {
-    File data = Files.createTempDir();
-    data.deleteOnExit();
-    File home = Files.createTempDir();
-    home.deleteOnExit();
-
-    Settings settings = Settings.builder()
-            .put("node.name", "fake-elastic")
-            .put("path.home", home.getAbsolutePath())
-            .put("path.data", data.getAbsolutePath())
-            .put("script.inline", true)  // requires GroovyPlugin
-            .put("script.indexed", true) // requires GroovyPlugin
-            .put("cluster.routing.allocation.disk.threshold_enabled", false)
-            .put("node.local", true)
-            .put("node.data", true)
-            .put("network.host", "localhost")
-            .build();
-
-    return create(settings);
-  }
-
-  /**
-   * Starts current node
-   */
-  public void start() {
-    Preconditions.checkState(!isStarted, "already started");
-    node.start();
-    this.isStarted = true;
-  }
-
-  /**
-   * Returns the current address to connect to with HTTP client.
-   *
-   * @return {@code HTTP} address (hostname / port)
-   */
-  public TransportAddress httpAddress() {
-    Preconditions.checkState(isStarted, "node is not started");
-
-    NodesInfoResponse response =  client().admin().cluster().prepareNodesInfo()
-            .execute().actionGet();
-    if (response.getNodes().length != 1) {
-      throw new IllegalStateException("Expected single node but got "
-              + response.getNodes().length);
-    }
-    NodeInfo node = response.getNodes()[0];
-    return node.getHttp().address().boundAddresses()[0];
-  }
-
-  /**
-   * Exposes elastic
-   * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
-   * (use of HTTP client is preferred).
-   *
-   * @return client API to access ES functionality
-   */
-  public Client client() {
-    Preconditions.checkState(isStarted, "node is not started");
-    return node.client();
-  }
-
-  @Override public void close() throws Exception {
-    node.close();
-    // cleanup data dirs
-    File data = new File(node.settings().get("path.data"));
-    File home = new File(node.settings().get("path.home"));
-    for (File file: Arrays.asList(data, home)) {
-      if (file.exists()) {
-        file.delete();
-      }
-    }
-  }
-}
-
-// End EmbeddedElasticNode.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
deleted file mode 100644
index 4bd9c25..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch2;
-
-import com.google.common.base.Preconditions;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.transport.TransportAddress;
-import org.junit.rules.ExternalResource;
-
-/**
- * Used to initialize a single elastic node. For performance reasons (node startup costs),
- * same instance is usually shared across multiple tests.
- *
- * This rule should be used as follows:
- * <pre>
- *
- *  public class MyTest {
- *    &#64;ClassRule
- *    public static final ElasticSearchRule RULE = ElasticSearchRule.create();
- *
- *    &#64;BeforeClass
- *    public static void setup() {
- *       // ... populate instance
- *    }
- *
- *    &#64;Test
- *    public void myTest() {
- *      TransportAddress address = RULE.httpAddress();
- *      // .... (connect)
- *    }
- * }
- * </pre>
- *
- * @see ExternalResource
- */
-class EmbeddedElasticRule extends ExternalResource {
-
-  private final EmbeddedElasticsearchNode node;
-
-  private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
-    this.node = Preconditions.checkNotNull(resource, "resource");
-  }
-
-  @Override protected void before() throws Throwable {
-    node.start();
-  }
-
-  @Override protected void after() {
-    try {
-      node.close();
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Factory method to create this rule.
-   *
-   * @return new rule instance to be used in unit tests
-   */
-<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
-  public static EmbeddedElasticRule create() {
-    return new EmbeddedElasticRule(EmbeddedElasticNode.create());
-=======
-  public static EmbeddedElasticsearchPolicy create() {
-    return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
->>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
-  }
-
-  /**
-   * Exposes current ES transport client.
-   *
-   * @return initialized instance of ES
-   */
-  Client client() {
-    return node.client();
-  }
-
-  /**
-   * HTTP address for rest clients (can be ES native or any other).
-   *
-<<<<<<< HEAD:elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticRule.java
-   * @return HTTP hostname/port to connect to this ES instance
-=======
-   * @return {@code HTTP} connection parameters
->>>>>>> 54c598206... more 2380:elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/EmbeddedElasticsearchPolicy.java
-   */
-  TransportAddress httpAddress() {
-    return node.httpAddress();
-  }
-}
-
-// End EmbeddedElasticRule.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
new file mode 100644
index 0000000..d7e3464
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchNode.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.Files;
+
+import org.elasticsearch.Version;
+import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
+import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.elasticsearch.node.Node;
+import org.elasticsearch.node.internal.InternalSettingsPreparer;
+import org.elasticsearch.plugins.Plugin;
+import org.elasticsearch.script.groovy.GroovyPlugin;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Represents a single Elasticsearch node that can run embedded in a java application.
+ * Intended for unit and integration tests. Settings and plugins are crafted for Calcite.
+ */
+class EmbeddedElasticsearchNode implements AutoCloseable {
+
+  private final LocalNode node;
+  private volatile boolean  isStarted;
+
+  private EmbeddedElasticsearchNode(LocalNode node) {
+    this.node = Preconditions.checkNotNull(node, "node");
+  }
+
+  /**
+   * Having separate class to expose (protected) constructor which allows to install
+   * different plugins. In our case it is {@code GroovyPlugin} for scripted fields like
+   * {@code loc[0]} or {@code loc[1]['foo']}.
+   */
+  private static class LocalNode extends Node {
+    private LocalNode(Settings settings, Collection<Class<? extends Plugin>> classpathPlugins) {
+      super(InternalSettingsPreparer.prepareEnvironment(settings, null),
+          Version.CURRENT, classpathPlugins);
+    }
+  }
+
+  /**
+   * Creates an instance with existing settings
+   *
+   * @param settings ES settings for the node
+   * @return un-started node; call {@link #start()} to start the instance
+   */
+  private static EmbeddedElasticsearchNode create(Settings settings) {
+    // ensure GroovyPlugin is installed or otherwise scripted fields would not work
+    LocalNode node = new LocalNode(settings, Collections.singleton(GroovyPlugin.class));
+    return new EmbeddedElasticsearchNode(node);
+  }
+
+  /**
+   * Creates elastic node as single member of a cluster. Node will not be started
+   * unless {@link #start()} is explicitly called.
+   *
+   * @return node with default configuration
+   */
+  public static EmbeddedElasticsearchNode create() {
+    File data = Files.createTempDir();
+    data.deleteOnExit();
+    File home = Files.createTempDir();
+    home.deleteOnExit();
+
+    Settings settings = Settings.builder()
+            .put("node.name", "fake-elastic")
+            .put("path.home", home.getAbsolutePath())
+            .put("path.data", data.getAbsolutePath())
+            .put("script.inline", true)  // requires GroovyPlugin
+            .put("script.indexed", true) // requires GroovyPlugin
+            .put("cluster.routing.allocation.disk.threshold_enabled", false)
+            .put("node.local", true)
+            .put("node.data", true)
+            .put("network.host", "localhost")
+            .build();
+
+    return create(settings);
+  }
+
+  /**
+   * Starts current node
+   */
+  public void start() {
+    Preconditions.checkState(!isStarted, "already started");
+    node.start();
+    this.isStarted = true;
+  }
+
+  /**
+   * Returns the current address to connect to with HTTP client.
+   *
+   * @return {@code HTTP} address (hostname / port)
+   */
+  public TransportAddress httpAddress() {
+    Preconditions.checkState(isStarted, "node is not started");
+
+    NodesInfoResponse response =  client().admin().cluster().prepareNodesInfo()
+            .execute().actionGet();
+    if (response.getNodes().length != 1) {
+      throw new IllegalStateException("Expected single node but got "
+              + response.getNodes().length);
+    }
+    NodeInfo node = response.getNodes()[0];
+    return node.getHttp().address().boundAddresses()[0];
+  }
+
+  /**
+   * Exposes an Elasticsearch
+   * <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/transport-client.html">transport client</a>
+   * (use of HTTP client is preferred).
+   *
+   * @return client API to access ES functionality
+   */
+  public Client client() {
+    Preconditions.checkState(isStarted, "node is not started");
+    return node.client();
+  }
+
+  @Override public void close() throws Exception {
+    node.close();
+    // cleanup data dirs
+    File data = new File(node.settings().get("path.data"));
+    File home = new File(node.settings().get("path.home"));
+    for (File file: Arrays.asList(data, home)) {
+      if (file.exists()) {
+        file.delete();
+      }
+    }
+  }
+}
+
+// End EmbeddedElasticsearchNode.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
new file mode 100644
index 0000000..6b25ecf
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/adapter/elasticsearch2/EmbeddedElasticsearchPolicy.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.adapter.elasticsearch2;
+
+import com.google.common.base.Preconditions;
+
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.transport.TransportAddress;
+import org.junit.rules.ExternalResource;
+
+/**
+ * Junit rule that is used to initialize a single Elasticsearch node for tests.
+ *
+ * <p>For performance reasons (node startup costs),
+ * the same instance is usually shared across multiple tests.
+ *
+ * <p>This rule should be used as follows:
+ * <pre>
+ *
+ *  public class MyTest {
+ *    &#64;ClassRule
+ *    public static final EmbeddedElasticsearchPolicy POLICY =
+ *        EmbeddedElasticsearchPolicy.create();
+ *
+ *    &#64;BeforeClass
+ *    public static void setup() {
+ *       // ... populate instance
+ *    }
+ *
+ *    &#64;Test
+ *    public void myTest() {
+ *      TransportAddress address = POLICY.httpAddress();
+ *      // .... (connect)
+ *    }
+ * }
+ * </pre>
+ *
+ * @see ExternalResource
+ */
+class EmbeddedElasticsearchPolicy extends ExternalResource {
+
+  private final EmbeddedElasticsearchNode node;
+
+  private EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode resource) {
+    this.node = Preconditions.checkNotNull(resource, "resource");
+  }
+
+  @Override protected void before() throws Throwable {
+    node.start();
+  }
+
+  @Override protected void after() {
+    try {
+      node.close();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  /**
+   * Factory method to create this rule.
+   *
+   * @return new rule instance to be used in unit tests
+   */
+  public static EmbeddedElasticsearchPolicy create() {
+    return new EmbeddedElasticsearchPolicy(EmbeddedElasticsearchNode.create());
+  }
+
+  /**
+   * Exposes current ES transport client.
+   *
+   * @return initialized instance of ES
+   */
+  Client client() {
+    return node.client();
+  }
+
+  /**
+   * HTTP address for rest clients (can be ES native or any other).
+   *
+   * @return HTTP hostname/port to connect to this ES instance
+   */
+  TransportAddress httpAddress() {
+    return node.httpAddress();
+  }
+}
+
+// End EmbeddedElasticsearchPolicy.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
deleted file mode 100644
index 86e9d9f..0000000
--- a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticChecker.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.test;
-
-import com.google.common.base.Function;
-
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-/**
- * Internal util methods for ElasticSearch tests
- */
-public class ElasticChecker {
-
-  private ElasticChecker() {}
-
-
-  /** Returns a function that checks that a particular Elasticsearch pipeline is
-   * generated to implement a query.
-   *
-   * @param strings list of expected queries
-   * @return function to perform the check
-   */
-  public static Function<List, Void> elasticsearchChecker(final String... strings) {
-    return new Function<List, Void>() {
-      @Nullable
-      @Override public Void apply(@Nullable List actual) {
-        Object[] actualArray = actual == null || actual.isEmpty() ? null
-            : ((List) actual.get(0)).toArray();
-        CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
-            actualArray);
-        return null;
-      }
-    };
-  }
-}
-
-// End ElasticChecker.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
new file mode 100644
index 0000000..d897dfb
--- /dev/null
+++ b/elasticsearch2/src/test/java/org/apache/calcite/test/ElasticsearchChecker.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.test;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for Elasticsearch tests.
+ */
+public class ElasticsearchChecker {
+
+  private ElasticsearchChecker() {}
+
+
+  /** Returns a function that checks that a particular Elasticsearch pipeline is
+   * generated to implement a query.
+   *
+   * @param strings list of expected queries
+   * @return function to perform the check
+   */
+  public static Function<List, Void> elasticsearchChecker(final String... strings) {
+    return new Function<List, Void>() {
+      @Nullable
+      @Override public Void apply(@Nullable List actual) {
+        Object[] actualArray = actual == null || actual.isEmpty() ? null
+            : ((List) actual.get(0)).toArray();
+        CalciteAssert.assertArrayEqual("expected Elasticsearch query not found", strings,
+            actualArray);
+        return null;
+      }
+    };
+  }
+}
+
+// End ElasticsearchChecker.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch2/src/test/resources/zips-mini.json
----------------------------------------------------------------------
diff --git a/elasticsearch2/src/test/resources/zips-mini.json b/elasticsearch2/src/test/resources/zips-mini.json
index d70eadc..858117a 100644
--- a/elasticsearch2/src/test/resources/zips-mini.json
+++ b/elasticsearch2/src/test/resources/zips-mini.json
@@ -146,4 +146,4 @@
 { "_id" : "98310", "city" : "BREMERTON", "loc" : [ -122.629913, 47.601916 ], "pop" : 49057, "state" : "WA" }
 { "_id" : "99504", "city" : "ANCHORAGE", "loc" : [ -149.74467, 61.203696 ], "pop" : 32383, "state" : "AK" }
 { "_id" : "99709", "city" : "FAIRBANKS", "loc" : [ -147.846917, 64.85437 ], "pop" : 23238, "state" : "AK" }
-{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }
\ No newline at end of file
+{ "_id" : "99801", "city" : "JUNEAU", "loc" : [ -134.529429, 58.362767 ], "pop" : 24947, "state" : "AK" }

http://git-wip-us.apache.org/repos/asf/calcite/blob/6e8bb5a1/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
----------------------------------------------------------------------
diff --git a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java b/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
deleted file mode 100644
index 438e048..0000000
--- a/elasticsearch5/src/test/java/org/apache/calcite/adapter/elasticsearch5/ElasticSearch5AdapterTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.adapter.elasticsearch5;
-
-import org.apache.calcite.jdbc.CalciteConnection;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.schema.impl.ViewTable;
-import org.apache.calcite.schema.impl.ViewTableMacro;
-import org.apache.calcite.test.CalciteAssert;
-import org.apache.calcite.test.ElasticChecker;
-
-import com.google.common.io.LineProcessor;
-import com.google.common.io.Resources;
-
-import org.elasticsearch.action.bulk.BulkItemResponse;
-import org.elasticsearch.action.bulk.BulkRequestBuilder;
-import org.elasticsearch.action.bulk.BulkResponse;
-import org.elasticsearch.action.support.WriteRequest;
-import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.common.xcontent.XContentFactory;
-import org.elasticsearch.common.xcontent.XContentType;
-
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Locale;
-
-/**
- * Set of tests for ES adapter. Uses real instance via {@link EmbeddedElasticRule}. Document
- * source is local {@code zips-mini.json} file (located in the classpath).
- */
-public class ElasticSearch5AdapterTest {
-
-  @ClassRule //init once for all tests
-  public static final EmbeddedElasticRule NODE = EmbeddedElasticRule.create();
-
-  private static final String ZIPS = "zips";
-
-  /**
-   * Used to create {@code zips} index and insert some data
-   *
-   * @throws Exception when ES instance setup failed
-   */
-  @BeforeClass
-  public static void setupInstance() throws Exception {
-    // define mapping so fields are searchable (term query)
-    XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
-            .startObject("properties")
-            .startObject("city").field("type", "string")
-                  .field("index", "not_analyzed").endObject()
-            .startObject("state").field("type", "string")
-                  .field("index", "not_analyzed").endObject()
-            .startObject("pop").field("type", "long").endObject()
-            .endObject()
-            .endObject();
-
-    // create index
-    NODE.client().admin().indices()
-            .prepareCreate(ZIPS)
-            .addMapping(ZIPS, mapping)
-            .get();
-
-    BulkRequestBuilder bulk = NODE.client().prepareBulk()
-            .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
-
-    // load records from file
-    Resources.readLines(ElasticSearch5AdapterTest.class.getResource("/zips-mini.json"),
-            StandardCharsets.UTF_8, new LineProcessor<Void>() {
-              @Override public boolean processLine(String line) throws IOException {
-                line = line.replaceAll("_id", "id"); // _id is a reserved attribute in ES
-                bulk.add(NODE.client().prepareIndex(ZIPS, ZIPS)
-                        .setSource(line.getBytes(StandardCharsets.UTF_8), XContentType.JSON));
-                return true;
-              }
-
-              @Override public Void getResult() {
-                return null;
-              }
-            });
-
-    if (bulk.numberOfActions() == 0) {
-      throw new IllegalStateException("No records to be indexed");
-    }
-
-    BulkResponse response = bulk.execute().get();
-
-    if (response.hasFailures()) {
-      throw new IllegalStateException(
-              String.format(Locale.getDefault(), "Failed to populate %s:\n%s", NODE.httpAddress(),
-              Arrays.stream(response.getItems()).filter(BulkItemResponse::isFailed)
-                      .map(BulkItemResponse::getFailureMessage).findFirst().orElse("<unknown>")));
-    }
-
-  }
-
-  private CalciteAssert.ConnectionFactory newConnectionFactory() {
-    return new CalciteAssert.ConnectionFactory() {
-      @Override public Connection createConnection() throws SQLException {
-        final Connection connection = DriverManager.getConnection("jdbc:calcite:");
-        final SchemaPlus root = connection.unwrap(CalciteConnection.class).getRootSchema();
-
-        root.add("elastic", new Elasticsearch5Schema(NODE.client(), ZIPS));
-
-        // add calcite view programmatically
-        final String viewSql = "select cast(_MAP['city'] AS varchar(20)) AS \"city\", "
-               + " cast(_MAP['loc'][0] AS float) AS \"longitude\",\n"
-               + " cast(_MAP['loc'][1] AS float) AS \"latitude\",\n"
-              + " cast(_MAP['pop'] AS integer) AS \"pop\", "
-              +  " cast(_MAP['state'] AS varchar(2)) AS \"state\", "
-              +  " cast(_MAP['id'] AS varchar(5)) AS \"id\" "
-              +  "from \"elastic\".\"zips\"";
-
-        ViewTableMacro macro = ViewTable.viewMacro(root, viewSql,
-                Collections.singletonList("elastic"), Arrays.asList("elastic", "view"), false);
-        root.add("ZIPS", macro);
-
-        return connection;
-      }
-    };
-  }
-
-  private CalciteAssert.AssertThat calciteAssert() {
-    return CalciteAssert.that()
-            .with(newConnectionFactory());
-  }
-
-  /**
-   * Tests using calcite view
-   */
-  @Test
-  public void view() {
-    calciteAssert()
-          .query("select * from zips where \"city\" = 'BROOKLYN'")
-          .returns("city=BROOKLYN; longitude=-73.956985; latitude=40.646694; "
-                  + "pop=111396; state=NY; id=11226\n")
-          .returnsCount(1);
-  }
-
-  @Test
-  public void emptyResult() {
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from zips limit 0")
-            .returnsCount(0);
-
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['Foo'] = '_MISSING_'")
-            .returnsCount(0);
-  }
-
-  @Test
-  public void basic() throws Exception {
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['city'] = 'BROOKLYN'")
-            .returnsCount(1);
-
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where"
-                    + " _MAP['city'] in ('BROOKLYN', 'WASHINGTON')")
-            .returnsCount(2);
-
-    // lower-case
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where "
-                    + "_MAP['city'] in ('brooklyn', 'Brooklyn', 'BROOK') ")
-            .returnsCount(0);
-
-    // missing field
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" where _MAP['CITY'] = 'BROOKLYN'")
-            .returnsCount(0);
-
-    // limit works
-    CalciteAssert.that()
-            .with(newConnectionFactory())
-            .query("select * from \"elastic\".\"zips\" limit 42")
-            .returnsCount(42);
-
-  }
-
-  @Test public void testSort() {
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchSort(sort0=[$4], dir0=[ASC])\n"
-            + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "      ElasticsearchTableScan(table=[[elastic, zips]])";
-
-    calciteAssert()
-            .query("select * from zips order by \"state\"")
-            .returnsCount(10)
-            .explainContains(explain);
-  }
-
-  @Test public void testSortLimit() {
-    final String sql = "select \"state\", \"pop\" from zips\n"
-            + "order by \"state\", \"pop\" offset 2 rows fetch next 3 rows only";
-    calciteAssert()
-            .query(sql)
-            .returnsUnordered("state=AK; pop=32383",
-                    "state=AL; pop=42124",
-                    "state=AL; pop=43862")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"_source\" : [\"state\", \"pop\"]",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]",
-                            "\"from\": 2",
-                            "\"size\": 3"));
-  }
-
-
-
-  @Test public void testOffsetLimit() {
-    final String sql = "select \"state\", \"id\" from zips\n"
-            + "offset 2 fetch next 3 rows only";
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"from\": 2",
-                            "\"size\": 3",
-                            "\"_source\" : [\"state\", \"id\"]"));
-  }
-
-  @Test public void testLimit() {
-    final String sql = "select \"state\", \"id\" from zips\n"
-            + "fetch next 3 rows only";
-
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(
-                            "\"size\": 3",
-                            "\"_source\" : [\"state\", \"id\"]"));
-  }
-
-  @Test public void testFilterSort() {
-    final String sql = "select * from zips\n"
-            + "where \"state\" = 'CA' and \"pop\" >= 94000\n"
-            + "order by \"state\", \"pop\"";
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchSort(sort0=[$4], sort1=[$3], dir0=[ASC], dir1=[ASC])\n"
-            + "    ElasticsearchProject(city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], longitude=[CAST(ITEM(ITEM($0, 'loc'), 0)):FLOAT], latitude=[CAST(ITEM(ITEM($0, 'loc'), 1)):FLOAT], pop=[CAST(ITEM($0, 'pop')):INTEGER], state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], id=[CAST(ITEM($0, 'id')):VARCHAR(5) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "      ElasticsearchFilter(condition=[AND(=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA'), >=(CAST(ITEM($0, 'pop')):INTEGER, 94000))])\n"
-            + "        ElasticsearchTableScan(table=[[elastic, zips]])\n\n";
-    calciteAssert()
-            .query(sql)
-            .returnsOrdered("city=NORWALK; longitude=-118.081767; latitude=33.90564;"
-                            + " pop=94188; state=CA; id=90650",
-                    "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856;"
-                            + " pop=96074; state=CA; id=90011",
-                    "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177;"
-                            + " pop=99568; state=CA; id=90201")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker("\"query\" : "
-                                    + "{\"constant_score\":{\"filter\":{\"bool\":"
-                                    + "{\"must\":[{\"term\":{\"state\":\"CA\"}},"
-                                    + "{\"range\":{\"pop\":{\"gte\":94000}}}]}}}}",
-                            "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
-                                    + "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
-                                    + "\"city\":{\"script\": \"params._source.city\"}, "
-                                    + "\"pop\":{\"script\": \"params._source.pop\"}, "
-                                    + "\"state\":{\"script\": \"params._source.state\"}, "
-                                    + "\"id\":{\"script\": \"params._source.id\"}}",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"pop\": \"asc\"}]"))
-            .explainContains(explain);
-  }
-
-  @Test public void testFilterSortDesc() {
-    final String sql = "select * from zips\n"
-            + "where \"pop\" BETWEEN 95000 AND 100000\n"
-            + "order by \"state\" desc, \"pop\"";
-    calciteAssert()
-            .query(sql)
-            .limit(4)
-            .returnsOrdered(
-             "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011",
-             "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201");
-  }
-
-  @Test public void testFilterRedundant() {
-    final String sql = "select * from zips\n"
-            + "where \"state\" > 'CA' and \"state\" < 'AZ' and \"state\" = 'OK'";
-    calciteAssert()
-            .query(sql)
-            .runs()
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker(""
-                                    + "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":"
-                                    + "{\"must\":[{\"term\":{\"state\":\"OK\"}}]}}}}",
-                            "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
-                                    +  "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
-                                    +   "\"city\":{\"script\": \"params._source.city\"}, "
-                                    +   "\"pop\":{\"script\": \"params._source.pop\"}, \"state\":{\"script\": \"params._source.state\"}, "
-                                    +            "\"id\":{\"script\": \"params._source.id\"}}"
-                    ));
-  }
-
-  @Test public void testInPlan() {
-    final String[] searches = {
-        "\"query\" : {\"constant_score\":{\"filter\":{\"bool\":{\"should\":"
-                 + "[{\"bool\":{\"must\":[{\"term\":{\"pop\":96074}}]}},{\"bool\":{\"must\":[{\"term\":"
-                 + "{\"pop\":99568}}]}}]}}}}",
-        "\"script_fields\": {\"longitude\":{\"script\":\"params._source.loc[0]\"}, "
-                 +  "\"latitude\":{\"script\":\"params._source.loc[1]\"}, "
-                 +  "\"city\":{\"script\": \"params._source.city\"}, "
-                 +  "\"pop\":{\"script\": \"params._source.pop\"}, "
-                 +  "\"state\":{\"script\": \"params._source.state\"}, "
-                 +  "\"id\":{\"script\": \"params._source.id\"}}"
-    };
-
-    calciteAssert()
-            .query("select * from zips where \"pop\" in (96074, 99568)")
-            .returnsUnordered(
-                    "city=BELL GARDENS; longitude=-118.17205; latitude=33.969177; pop=99568; state=CA; id=90201",
-                    "city=LOS ANGELES; longitude=-118.258189; latitude=34.007856; pop=96074; state=CA; id=90011"
-                    )
-            .queryContains(ElasticChecker.elasticsearchChecker(searches));
-  }
-
-  @Test public void testZips() {
-    calciteAssert()
-         .query("select \"state\", \"city\" from zips")
-         .returnsCount(10);
-  }
-
-  @Test public void testProject() {
-    final String sql = "select \"state\", \"city\", 0 as \"zero\"\n"
-            + "from zips\n"
-            + "order by \"state\", \"city\"";
-
-    calciteAssert()
-            .query(sql)
-            .limit(2)
-            .returnsUnordered("state=AK; city=ANCHORAGE; zero=0",
-                    "state=AK; city=FAIRBANKS; zero=0")
-            .queryContains(
-                    ElasticChecker.elasticsearchChecker("\"script_fields\": "
-                                    + "{\"zero\":{\"script\": \"0\"}, "
-                                    + "\"state\":{\"script\": \"params._source.state\"}, "
-                                    + "\"city\":{\"script\": \"params._source.city\"}}",
-                            "\"sort\": [ {\"state\": \"asc\"}, {\"city\": \"asc\"}]"));
-  }
-
-  @Test public void testFilter() {
-    final String explain = "PLAN=ElasticsearchToEnumerableConverter\n"
-            + "  ElasticsearchProject(state=[CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"], city=[CAST(ITEM($0, 'city')):VARCHAR(20) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\"])\n"
-            + "    ElasticsearchFilter(condition=[=(CAST(ITEM($0, 'state')):VARCHAR(2) CHARACTER SET \"ISO-8859-1\" COLLATE \"ISO-8859-1$en_US$primary\", 'CA')])\n"
-            + "      ElasticsearchTableScan(table=[[elastic, zips]])";
-    calciteAssert()
-            .query("select \"state\", \"city\" from zips where \"state\" = 'CA'")
-            .limit(3)
-            .returnsUnordered("state=CA; city=BELL GARDENS",
-                    "state=CA; city=LOS ANGELES",
-                    "state=CA; city=NORWALK")
-            .explainContains(explain);
-  }
-
-  @Test public void testFilterReversed() {
-    calciteAssert()
-          .query("select \"state\", \"city\" from zips where 'WI' < \"state\" order by \"city\"")
-          .limit(2)
-          .returnsUnordered("state=WV; city=BECKLEY",
-                    "state=WY; city=CHEYENNE");
-    calciteAssert()
-          .query("select \"state\", \"city\" from zips where \"state\" > 'WI' order by \"city\"")
-          .limit(2)
-          .returnsUnordered("state=WV; city=BECKLEY",
-                    "state=WY; city=CHEYENNE");
-  }
-
-}
-
-// End ElasticSearch5AdapterTest.java