[CALCITE-2588] Run Geode Adapter tests with an Embedded Instance

Part of the effort to increase test coverage for adapters. Enables execution of 
all Geode adapter tests during CI build (instead of manual run).

Create special JUnit Rule (`GeodeEmbeddedPolicy`) which starts / stops embedded 
Geode instance once for all the tests.

Modify GeodeSchema and GeodeTable to accept exising geode instance in the 
constructor instance of connection parameters.

Ignore two tests which currently fail for both embedded and external 
instance(s). These bugs will be addressed separately

Local test dataset is taken from `calcite-test-dataset` project (the one which 
is used for integration testing). Re-use `zips-mini.json` from mongo/elastic 
adapters.

Closes apache/calcite#857


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

Branch: refs/heads/master
Commit: ed424ed81d0de66fcfd6a5352f00fb99cc514882
Parents: 9ba9bdc
Author: Andrei Sereda <25229979+asereda...@users.noreply.github.com>
Authored: Thu Sep 13 11:37:20 2018 -0400
Committer: Andrei Sereda <25229979+asereda...@users.noreply.github.com>
Committed: Tue Sep 25 14:04:36 2018 -0400

----------------------------------------------------------------------
 geode/pom.xml                                   |   5 +
 .../adapter/geode/rel/GeodeAggregate.java       |  17 +-
 .../calcite/adapter/geode/rel/GeodeFilter.java  |   4 +-
 .../calcite/adapter/geode/rel/GeodeProject.java |   5 +-
 .../calcite/adapter/geode/rel/GeodeRel.java     |   8 +-
 .../calcite/adapter/geode/rel/GeodeRules.java   |   7 +-
 .../calcite/adapter/geode/rel/GeodeSchema.java  |  47 +-
 .../adapter/geode/rel/GeodeSchemaFactory.java   |   5 +-
 .../calcite/adapter/geode/rel/GeodeSort.java    |   9 +-
 .../calcite/adapter/geode/rel/GeodeTable.java   |  68 +--
 .../adapter/geode/rel/GeodeTableScan.java       |   2 +-
 .../geode/rel/GeodeToEnumerableConverter.java   |  13 +-
 .../adapter/geode/simple/GeodeSimpleSchema.java |   9 +-
 .../calcite/adapter/geode/util/GeodeUtils.java  |  60 ++-
 .../adapter/geode/rel/AbstractGeodeTest.java    |  33 ++
 .../adapter/geode/rel/BaseGeodeAdapterIT.java   | 159 ------
 .../geode/rel/GeodeAdapterBookshopIT.java       | 469 ------------------
 .../adapter/geode/rel/GeodeAdapterIT.java       |  99 ----
 .../adapter/geode/rel/GeodeAssertions.java      |  44 ++
 .../adapter/geode/rel/GeodeBookstoreTest.java   | 483 +++++++++++++++++++
 .../adapter/geode/rel/GeodeEmbeddedPolicy.java  | 154 ++++++
 .../calcite/adapter/geode/rel/GeodeZipsIT.java  | 200 --------
 .../adapter/geode/rel/GeodeZipsTest.java        | 191 ++++++++
 .../calcite/adapter/geode/rel/JsonLoader.java   |  91 ++++
 geode/src/test/resources/book_customer.json     |   3 +
 geode/src/test/resources/book_master.json       |   3 +
 geode/src/test/resources/log4j.properties       |  26 +
 .../src/test/resources/model-bookshop-all.json  |  35 --
 geode/src/test/resources/model-bookshop.json    |  35 --
 .../resources/model-geode-pg-federation.json    |  54 ---
 .../src/test/resources/model-with-classes.json  |  39 --
 geode/src/test/resources/model-zips.json        |  47 --
 geode/src/test/resources/model.json             |  35 --
 geode/src/test/resources/model2.json            |  35 --
 geode/src/test/resources/zips-mini.json         | 149 ++++++
 35 files changed, 1323 insertions(+), 1320 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/pom.xml
----------------------------------------------------------------------
diff --git a/geode/pom.xml b/geode/pom.xml
index 698ca72..a9e24de 100644
--- a/geode/pom.xml
+++ b/geode/pom.xml
@@ -89,6 +89,11 @@ limitations under the License.
       <artifactId>slf4j-log4j12</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <profiles>

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeAggregate.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeAggregate.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeAggregate.java
index faab698..19bbe63 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeAggregate.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeAggregate.java
@@ -76,21 +76,14 @@ public class GeodeAggregate extends Aggregate implements 
GeodeRel {
   }
 
   @Override public void implement(GeodeImplementContext geodeImplementContext) 
{
-
-    ((GeodeRel) getInput()).implement(geodeImplementContext);
+    geodeImplementContext.visitChild(getInput());
 
     List<String> inputFields = fieldNames(getInput().getRowType());
 
     List<String> groupByFields = new ArrayList<>();
 
-    // GROUP BY field == cardinality of 1, GROUP BY field1, field2 => 
cardinality of 2 ...
-    if (groupSet.cardinality() == 1) {
-      final String groupByFieldName = inputFields.get(groupSet.nth(0));
-      groupByFields.add(groupByFieldName);
-    } else {
-      for (int group : groupSet) {
-        groupByFields.add(inputFields.get(group));
-      }
+    for (int group : groupSet) {
+      groupByFields.add(inputFields.get(group));
     }
 
     geodeImplementContext.addGroupBy(groupByFields);
@@ -99,7 +92,7 @@ public class GeodeAggregate extends Aggregate implements 
GeodeRel {
     Builder<String, String> aggregateFunctionMap = ImmutableMap.builder();
     for (AggregateCall aggCall : aggCalls) {
 
-      ArrayList<Object> aggCallFieldNames = new ArrayList<>();
+      List<String> aggCallFieldNames = new ArrayList<>();
       for (int i : aggCall.getArgList()) {
         aggCallFieldNames.add(inputFields.get(i));
       }
@@ -112,7 +105,7 @@ public class GeodeAggregate extends Aggregate implements 
GeodeRel {
         aggCallFieldNames.add(inputFields.get(0));
       }
 
-      String oqlAggregateCall = Util.toString(aggCallFieldNames, " " + 
functionName + "(", ", ",
+      String oqlAggregateCall = Util.toString(aggCallFieldNames, functionName 
+ "(", ", ",
           ")");
 
       aggregateFunctionMap.put(aggCall.getName(), oqlAggregateCall);

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
index e69a0db..203e5fe 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeFilter.java
@@ -48,7 +48,7 @@ public class GeodeFilter extends Filter implements GeodeRel {
 
   private final String match;
 
-  public GeodeFilter(RelOptCluster cluster, RelTraitSet traitSet,
+  GeodeFilter(RelOptCluster cluster, RelTraitSet traitSet,
       RelNode input, RexNode condition) {
 
     super(cluster, traitSet, input, condition);
@@ -70,7 +70,7 @@ public class GeodeFilter extends Filter implements GeodeRel {
 
   @Override public void implement(GeodeImplementContext geodeImplementContext) 
{
     // first call the input down the tree.
-    ((GeodeRel) getInput()).implement(geodeImplementContext);
+    geodeImplementContext.visitChild(getInput());
     geodeImplementContext.addPredicates(Collections.singletonList(match));
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeProject.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeProject.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeProject.java
index c8f328c..990a70c 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeProject.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeProject.java
@@ -39,7 +39,7 @@ import java.util.Map;
  */
 public class GeodeProject extends Project implements GeodeRel {
 
-  public GeodeProject(RelOptCluster cluster, RelTraitSet traitSet,
+  GeodeProject(RelOptCluster cluster, RelTraitSet traitSet,
       RelNode input, List<? extends RexNode> projects, RelDataType rowType) {
     super(cluster, traitSet, input, projects, rowType);
     assert getConvention() == GeodeRel.CONVENTION;
@@ -56,8 +56,7 @@ public class GeodeProject extends Project implements GeodeRel 
{
   }
 
   @Override public void implement(GeodeImplementContext geodeImplementContext) 
{
-
-    ((GeodeRel) getInput()).implement(geodeImplementContext);
+    geodeImplementContext.visitChild(getInput());
 
     final RexToGeodeTranslator translator =
         new RexToGeodeTranslator(

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRel.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRel.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRel.java
index ebf1d0d..30a150e 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRel.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRel.java
@@ -61,7 +61,7 @@ public interface GeodeRel extends RelNode {
 
     final Map<String, String> oqlAggregateFunctions = new LinkedHashMap<>();
 
-    String limitValue = null;
+    Long limitValue;
 
     RelOptTable table;
 
@@ -93,7 +93,7 @@ public interface GeodeRel extends RelNode {
       orderByFields.addAll(orderByFieldLists);
     }
 
-    public void setLimit(String limit) {
+    public void setLimit(long limit) {
       limitValue = limit;
     }
 
@@ -105,6 +105,10 @@ public interface GeodeRel extends RelNode {
       this.oqlAggregateFunctions.putAll(oqlAggregateFunctions);
     }
 
+    void visitChild(RelNode input) {
+      ((GeodeRel) input).implement(this);
+    }
+
     @Override public String toString() {
       return "GeodeImplementContext{"
           + "selectFields=" + selectFields

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
index 0e006eb..a0e7b0a 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeRules.java
@@ -49,13 +49,14 @@ import java.util.function.Predicate;
  */
 public class GeodeRules {
 
-  public static final RelOptRule[] RULES = {
+  static final RelOptRule[] RULES = {
+      GeodeSortLimitRule.INSTANCE,
       GeodeFilterRule.INSTANCE,
       GeodeProjectRule.INSTANCE,
-      GeodeSortLimitRule.INSTANCE,
-      GeodeAggregateRule.INSTANCE
+      GeodeAggregateRule.INSTANCE,
   };
 
+
   private GeodeRules() {
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchema.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchema.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchema.java
index 2e38741..0a099a2 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchema.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchema.java
@@ -17,45 +17,40 @@
 package org.apache.calcite.adapter.geode.rel;
 
 import org.apache.calcite.adapter.geode.util.GeodeUtils;
-import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.schema.Table;
 import org.apache.calcite.schema.impl.AbstractSchema;
-import org.apache.calcite.util.trace.CalciteTrace;
 
+import org.apache.geode.cache.GemFireCache;
 import org.apache.geode.cache.Region;
-import org.apache.geode.cache.client.ClientCache;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-import org.slf4j.Logger;
-
-import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import static 
org.apache.calcite.adapter.geode.util.GeodeUtils.createClientCache;
-import static 
org.apache.calcite.adapter.geode.util.GeodeUtils.createRelDataType;
 
 /**
  * Schema mapped onto a Geode Region.
  */
 public class GeodeSchema extends AbstractSchema {
 
-  protected static final Logger LOGGER = CalciteTrace.getPlannerTracer();
-
-  final ClientCache clientCache;
-  private final SchemaPlus parentSchema;
-  private String[] regionNames;
+  final GemFireCache cache;
+  private final List<String> regionNames;
   private ImmutableMap<String, Table> tableMap;
 
-  public GeodeSchema(String locatorHost, int locatorPort,
-      String[] regionNames, String pdxAutoSerializerPackageExp,
-      SchemaPlus parentSchema) {
-    super();
-    this.regionNames = regionNames;
-    this.parentSchema = parentSchema;
+  GeodeSchema(String locatorHost, int locatorPort,
+      Iterable<String> regionNames, String pdxAutoSerializerPackageExp) {
+    this(createClientCache(locatorHost, locatorPort, 
pdxAutoSerializerPackageExp, true),
+        regionNames);
+  }
 
-    this.clientCache = createClientCache(locatorHost, locatorPort,
-        pdxAutoSerializerPackageExp, true);
+  GeodeSchema(final GemFireCache cache, final Iterable<String> regionNames) {
+    super();
+    this.cache = Objects.requireNonNull(cache, "clientCache");
+    this.regionNames = 
ImmutableList.copyOf(Objects.requireNonNull(regionNames, "regionNames"));
   }
 
   @Override protected Map<String, Table> getTableMap() {
@@ -64,17 +59,9 @@ public class GeodeSchema extends AbstractSchema {
 
       final ImmutableMap.Builder<String, Table> builder = 
ImmutableMap.builder();
 
-      // Extract the first entity of each Regions and use it to build a table 
types
       for (String regionName : regionNames) {
-        Region region = GeodeUtils.createRegionProxy(clientCache, regionName);
-
-        Iterator regionIterator = region.keySetOnServer().iterator();
-
-        Object firstRegionEntry = region.get(regionIterator.next());
-        // TODO: how to handle empty Regions? JMX?
-        Table table = new GeodeTable(this, regionName, 
createRelDataType(firstRegionEntry),
-            clientCache);
-
+        Region region = GeodeUtils.createRegion(cache, regionName);
+        Table table = new GeodeTable(region);
         builder.put(regionName, table);
       }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchemaFactory.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchemaFactory.java
 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchemaFactory.java
index 0348a0d..e436ff1 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchemaFactory.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSchemaFactory.java
@@ -24,6 +24,7 @@ import org.apache.calcite.schema.SchemaPlus;
 
 import com.google.common.collect.ImmutableList;
 
+import java.util.Arrays;
 import java.util.Map;
 
 /**
@@ -61,8 +62,8 @@ public class GeodeSchemaFactory implements SchemaFactory {
           GeoFunctions.class.getName(), "*", true);
     }
 
-    return new GeodeSchema(locatorHost, locatorPort, regionNames,
-        pbxSerializablePackagePath, parentSchema);
+    return new GeodeSchema(locatorHost, locatorPort, 
Arrays.asList(regionNames),
+        pbxSerializablePackagePath);
   }
 }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSort.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSort.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSort.java
index 02e7b72..cebe5f7 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSort.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeSort.java
@@ -42,7 +42,7 @@ public class GeodeSort extends Sort implements GeodeRel {
   public static final String DESC = "DESC";
 
   /** Creates a GeodeSort. */
-  public GeodeSort(RelOptCluster cluster, RelTraitSet traitSet,
+  GeodeSort(RelOptCluster cluster, RelTraitSet traitSet,
       RelNode input, RelCollation collation, RexNode fetch) {
     super(cluster, traitSet, input, collation, null, fetch);
 
@@ -68,9 +68,7 @@ public class GeodeSort extends Sort implements GeodeRel {
   }
 
   @Override public void implement(GeodeImplementContext geodeImplementContext) 
{
-
-    ((GeodeRel) getInput()).implement(geodeImplementContext);
-
+    geodeImplementContext.visitChild(getInput());
 
     List<RelFieldCollation> sortCollations = collation.getFieldCollations();
 
@@ -85,9 +83,8 @@ public class GeodeSort extends Sort implements GeodeRel {
       geodeImplementContext.addOrderByFields(orderByFields);
     }
 
-
     if (fetch != null) {
-      geodeImplementContext.setLimit(((RexLiteral) 
fetch).getValue().toString());
+      geodeImplementContext.setLimit(((RexLiteral) 
fetch).getValueAs(Long.class));
     }
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTable.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTable.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTable.java
index c39b94c..342effc 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTable.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTable.java
@@ -16,6 +16,7 @@
  */
 package org.apache.calcite.adapter.geode.rel;
 
+import org.apache.calcite.adapter.geode.util.GeodeUtils;
 import org.apache.calcite.adapter.geode.util.JavaTypeFactoryExtImpl;
 import org.apache.calcite.adapter.java.AbstractQueryableTable;
 import org.apache.calcite.linq4j.AbstractEnumerable;
@@ -30,13 +31,15 @@ import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rel.type.RelDataTypeImpl;
 import org.apache.calcite.rel.type.RelProtoDataType;
+import org.apache.calcite.runtime.Hook;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.schema.TranslatableTable;
 import org.apache.calcite.schema.impl.AbstractTableQueryable;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.Util;
 
-import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.GemFireCache;
+import org.apache.geode.cache.Region;
 import org.apache.geode.cache.query.QueryService;
 import org.apache.geode.cache.query.SelectResults;
 
@@ -48,6 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 /**
@@ -55,25 +59,15 @@ import java.util.Map;
  */
 public class GeodeTable extends AbstractQueryableTable implements 
TranslatableTable {
 
-  protected static final Logger LOGGER = 
LoggerFactory.getLogger(GeodeTable.class.getName());
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(GeodeTable.class.getName());
 
-  private GeodeSchema schema;
+  private final String regionName;
+  private final RelDataType rowType;
 
-  private String regionName;
-
-  private RelDataType relDataType;
-
-  private ClientCache clientCache;
-
-  public GeodeTable(GeodeSchema schema,
-      String regionName,
-      RelDataType relDataType,
-      ClientCache clientCache) {
+  GeodeTable(Region<?, ?> region) {
     super(Object[].class);
-    this.schema = schema;
-    this.regionName = regionName;
-    this.relDataType = relDataType;
-    this.clientCache = clientCache;
+    this.regionName = region.getName();
+    this.rowType = GeodeUtils.autodetectRelTypeFromRegion(region);
   }
 
   public String toString() {
@@ -91,14 +85,14 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
    * @param predicates  A list of predicates which should be used in the query
    * @return Enumerator of results
    */
-  public Enumerable<Object> query(final ClientCache clientCache,
+  public Enumerable<Object> query(final GemFireCache clientCache,
       final List<Map.Entry<String, Class>> fields,
       final List<Map.Entry<String, String>> selectFields,
       final List<Map.Entry<String, String>> aggregateFunctions,
       final List<String> groupByFields,
       List<String> predicates,
       List<String> orderByFields,
-      String limit) {
+      Long limit) {
 
     final RelDataTypeFactory typeFactory = new JavaTypeFactoryExtImpl();
     final RelDataTypeFactory.Builder fieldInfo = typeFactory.builder();
@@ -122,9 +116,11 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
     // Construct the list of fields to project
     Builder<String> selectBuilder = ImmutableList.builder();
     if (!groupByFields.isEmpty()) {
+      // manually add GROUP BY to select clause (GeodeProjection was not 
visited)
       for (String groupByField : groupByFields) {
         selectBuilder.add(groupByField + " AS " + groupByField);
       }
+
       if (!aggFuncMap.isEmpty()) {
         for (Map.Entry<String, String> e : aggFuncMap.entrySet()) {
           selectBuilder.add(e.getValue() + " AS " + e.getKey());
@@ -140,13 +136,19 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
           selectBuilder.add("*");
         }
       } else {
-        for (Map.Entry<String, String> field : selectFields) {
-          selectBuilder.add(field.getKey() + " AS " + field.getValue());
+        if (!aggFuncMap.isEmpty()) {
+          for (Map.Entry<String, String> e : aggFuncMap.entrySet()) {
+            selectBuilder.add(e.getValue() + " AS " + e.getKey());
+          }
+        } else {
+          for (Map.Entry<String, String> field : selectFields) {
+            selectBuilder.add(field.getKey() + " AS " + field.getValue());
+          }
         }
       }
     }
 
-    final String oqlSelectStatement = Util.toString(selectBuilder.build(), " 
", ", ", "");
+    final String oqlSelectStatement = Util.toString(selectBuilder.build(), "", 
", ", "");
 
     // Combine all predicates conjunctively
     String whereClause = "";
@@ -174,20 +176,20 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
 
     final String oqlQuery = queryBuilder.toString();
 
+    Hook.QUERY_PLAN.run(oqlQuery);
     LOGGER.info("OQL: " + oqlQuery);
 
     return new AbstractEnumerable<Object>() {
       public Enumerator<Object> enumerator() {
-        SelectResults results = null;
-        QueryService queryService = clientCache.getQueryService();
-
+        final QueryService queryService = clientCache.getQueryService();
         try {
-          results = (SelectResults) queryService.newQuery(oqlQuery).execute();
+          SelectResults results = (SelectResults) 
queryService.newQuery(oqlQuery).execute();
+          return new GeodeEnumerator(results, resultRowType);
         } catch (Exception e) {
-          e.printStackTrace();
+          String message = String.format(Locale.ROOT, "Failed to execute query 
[%s] on %s",
+              oqlQuery, clientCache.getName());
+          throw new RuntimeException(message, e);
         }
-
-        return new GeodeEnumerator(results, resultRowType);
       }
     };
   }
@@ -207,7 +209,7 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
   }
 
   @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
-    return relDataType;
+    return rowType;
   }
 
   /**
@@ -231,8 +233,8 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
       return (GeodeTable) table;
     }
 
-    private ClientCache getClientCache() {
-      return schema.unwrap(GeodeSchema.class).clientCache;
+    private GemFireCache getClientCache() {
+      return schema.unwrap(GeodeSchema.class).cache;
     }
 
     /**
@@ -246,7 +248,7 @@ public class GeodeTable extends AbstractQueryableTable 
implements TranslatableTa
         List<String> groupByFields,
         List<String> predicates,
         List<String> order,
-        String limit) {
+        Long limit) {
       return getTable().query(getClientCache(), fields, selectFields,
           aggregateFunctions, groupByFields, predicates, order, limit);
     }

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTableScan.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTableScan.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTableScan.java
index b83838f..766902d 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTableScan.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeTableScan.java
@@ -44,7 +44,7 @@ public class GeodeTableScan extends TableScan implements 
GeodeRel {
    * @param geodeTable     Geode table
    * @param projectRowType Fields and types to project; null to project raw row
    */
-  protected GeodeTableScan(RelOptCluster cluster, RelTraitSet traitSet,
+  GeodeTableScan(RelOptCluster cluster, RelTraitSet traitSet,
       RelOptTable table, GeodeTable geodeTable, RelDataType projectRowType) {
     super(cluster, traitSet, table);
     this.geodeTable = geodeTable;

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeToEnumerableConverter.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeToEnumerableConverter.java
 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeToEnumerableConverter.java
index 4b44573..1ba3ff7 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeToEnumerableConverter.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/rel/GeodeToEnumerableConverter.java
@@ -35,7 +35,7 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.convert.ConverterImpl;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
-import org.apache.calcite.runtime.Hook;
+import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.util.BuiltInMethod;
 import org.apache.calcite.util.Pair;
 
@@ -76,7 +76,7 @@ public class GeodeToEnumerableConverter extends ConverterImpl 
implements Enumera
   private static final Method GEODE_QUERY_METHOD =
       Types.lookupMethod(GeodeTable.GeodeQueryable.class, "query", List.class,
           List.class, List.class, List.class, List.class, List.class,
-          String.class);
+          Long.class);
 
   /**
    * {@inheritDoc}
@@ -89,6 +89,8 @@ public class GeodeToEnumerableConverter extends ConverterImpl 
implements Enumera
     final GeodeImplementContext geodeImplementContext = new 
GeodeImplementContext();
     ((GeodeRel) getInput()).implement(geodeImplementContext);
 
+    final RelDataType rowType = getRowType();
+
     // PhysType is Enumerable Adapter class that maps SQL types (getRowType)
     // with physical Java types (getJavaTypes())
     final PhysType physType = PhysTypeImpl.of(
@@ -112,10 +114,11 @@ public class GeodeToEnumerableConverter extends 
ConverterImpl implements Enumera
         Expressions.call(
             
geodeImplementContext.table.getExpression(GeodeTable.GeodeQueryable.class),
             GEODE_QUERY_METHOD,
+            // fields
             constantArrayList(Pair.zip(geodeFieldNames(rowType), 
physFieldClasses), Pair.class),
-            // physical fields
-            
constantArrayList(toListMapPairs(geodeImplementContext.selectFields), 
Pair.class),
             // selected fields
+            
constantArrayList(toListMapPairs(geodeImplementContext.selectFields), 
Pair.class),
+            // aggregate functions
             constantArrayList(
                 toListMapPairs(geodeImplementContext.oqlAggregateFunctions), 
Pair.class),
             constantArrayList(geodeImplementContext.groupByFields, 
String.class),
@@ -123,8 +126,6 @@ public class GeodeToEnumerableConverter extends 
ConverterImpl implements Enumera
             constantArrayList(geodeImplementContext.orderByFields, 
String.class),
             Expressions.constant(geodeImplementContext.limitValue)));
 
-    Hook.QUERY_PLAN.run(geodeImplementContext);
-
     return implementor.result(physType, blockBuilder.toBlock());
   }
 

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleSchema.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleSchema.java
 
b/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleSchema.java
index bb98e60..14f2b8c 100644
--- 
a/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleSchema.java
+++ 
b/geode/src/main/java/org/apache/calcite/adapter/geode/simple/GeodeSimpleSchema.java
@@ -27,7 +27,7 @@ import com.google.common.collect.ImmutableMap;
 
 import java.util.Map;
 
-import static 
org.apache.calcite.adapter.geode.util.GeodeUtils.createRelDataType;
+import static 
org.apache.calcite.adapter.geode.util.GeodeUtils.autodetectRelTypeFromRegion;
 
 /**
  * Geode Simple Schema.
@@ -64,12 +64,9 @@ public class GeodeSimpleSchema extends AbstractSchema {
 
       for (String regionName : regionNames) {
 
-        Region region = GeodeUtils.createRegionProxy(clientCache, regionName);
+        Region region = GeodeUtils.createRegion(clientCache, regionName);
 
-        // TODO: What if the region is empty
-        Object regionEntry = 
region.get(region.keySetOnServer().iterator().next());
-
-        Table table = new GeodeSimpleScannableTable(regionName, 
createRelDataType(regionEntry),
+        Table table = new GeodeSimpleScannableTable(regionName, 
autodetectRelTypeFromRegion(region),
             clientCache);
 
         builder.put(regionName, table);

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/main/java/org/apache/calcite/adapter/geode/util/GeodeUtils.java
----------------------------------------------------------------------
diff --git 
a/geode/src/main/java/org/apache/calcite/adapter/geode/util/GeodeUtils.java 
b/geode/src/main/java/org/apache/calcite/adapter/geode/util/GeodeUtils.java
index 9f1648f..e49be07 100644
--- a/geode/src/main/java/org/apache/calcite/adapter/geode/util/GeodeUtils.java
+++ b/geode/src/main/java/org/apache/calcite/adapter/geode/util/GeodeUtils.java
@@ -24,6 +24,7 @@ import org.apache.calcite.util.Util;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.geode.cache.CacheClosedException;
+import org.apache.geode.cache.GemFireCache;
 import org.apache.geode.cache.Region;
 import org.apache.geode.cache.client.ClientCache;
 import org.apache.geode.cache.client.ClientCacheFactory;
@@ -38,8 +39,11 @@ import org.slf4j.LoggerFactory;
 import java.lang.reflect.Field;
 import java.lang.reflect.Type;
 import java.util.Date;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -114,19 +118,27 @@ public class GeodeUtils {
   /**
    * Obtains a proxy pointing to an existing Region on the server
    *
-   * @param clientCache {@link ClientCache} instance to interact with the 
Geode server
+   * @param cache {@link GemFireCache} instance to interact with the Geode 
server
    * @param regionName  Name of the region to create proxy for.
    * @return Returns a Region proxy to a remote (on the Server) regions.
    */
-  public static synchronized Region createRegionProxy(ClientCache clientCache,
-      String regionName) {
+  public static synchronized Region createRegion(GemFireCache cache, String 
regionName) {
+    Objects.requireNonNull(cache, "cache");
+    Objects.requireNonNull(regionName, "regionName");
     Region region = REGION_MAP.get(regionName);
     if (region == null) {
-      region = clientCache
-          .createClientRegionFactory(ClientRegionShortcut.PROXY)
-          .create(regionName);
+      try {
+        region = ((ClientCache) cache)
+            .createClientRegionFactory(ClientRegionShortcut.PROXY)
+            .create(regionName);
+      } catch (IllegalStateException e) {
+        // means this is a server cache (probably part of embedded testing)
+        region = cache.getRegion(regionName);
+      }
+
       REGION_MAP.put(regionName, region);
     }
+
     return region;
   }
 
@@ -262,8 +274,42 @@ public class GeodeUtils {
     return o;
   }
 
+  /**
+   * Extract the first entity of each Regions and use it to build a table 
types.
+   *
+   * @param region existing region
+   * @return derived data type.
+   */
+  public static RelDataType autodetectRelTypeFromRegion(Region<?, ?> region) {
+    Objects.requireNonNull(region, "region");
+
+    // try to detect type using value constraints (if they exists)
+    final Class<?> constraint = region.getAttributes().getValueConstraint();
+    if (constraint != null && !PdxInstance.class.isAssignableFrom(constraint)) 
{
+      return new JavaTypeFactoryExtImpl().createStructType(constraint);
+    }
+
+    final Iterator<?> iter;
+    if (region.getAttributes().getPoolName() == null) {
+      // means current cache is server (not ClientCache)
+      iter = region.keySet().iterator();
+    } else {
+      // for ClientCache
+      iter = region.keySetOnServer().iterator();
+    }
+
+    if (!iter.hasNext()) {
+      String message = String.format(Locale.ROOT, "Region %s is empty, can't "
+          + "autodetect type(s)", region.getName());
+      throw new IllegalStateException(message);
+    }
+
+    final Object entry = region.get(iter.next());
+    return createRelDataType(entry);
+  }
+
   // Create Relational Type by inferring a Geode entry or response instance.
-  public static RelDataType createRelDataType(Object regionEntry) {
+  private static RelDataType createRelDataType(Object regionEntry) {
     JavaTypeFactoryExtImpl typeFactory = new JavaTypeFactoryExtImpl();
     if (regionEntry instanceof PdxInstance) {
       return typeFactory.createPdxType((PdxInstance) regionEntry);

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/AbstractGeodeTest.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/AbstractGeodeTest.java
 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/AbstractGeodeTest.java
new file mode 100644
index 0000000..3f7b7f2
--- /dev/null
+++ 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/AbstractGeodeTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.geode.rel;
+
+import org.junit.ClassRule;
+
+/**
+ * Base class which allows sharing same geode instance across all tests. Also 
due to legacy
+ * reasons there can't be more than one Geode instance (running in parallel) 
for a single JVM.
+ */
+public abstract class AbstractGeodeTest {
+
+  @ClassRule
+  public static final GeodeEmbeddedPolicy POLICY = 
GeodeEmbeddedPolicy.create().share();
+
+}
+
+// End AbstractGeodeTest.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/BaseGeodeAdapterIT.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/BaseGeodeAdapterIT.java
 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/BaseGeodeAdapterIT.java
deleted file mode 100644
index 6c9c765..0000000
--- 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/BaseGeodeAdapterIT.java
+++ /dev/null
@@ -1,159 +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.geode.rel;
-
-import org.apache.calcite.linq4j.function.Function1;
-import org.apache.calcite.util.Sources;
-
-import org.junit.Assert;
-
-import java.io.PrintStream;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Properties;
-
-/**
- * Geode Adapter IT Test
- */
-public class BaseGeodeAdapterIT {
-
-  /**
-   * Returns a function that checks the contents of a result set against an
-   * expected string.
-   */
-  private static Function1<ResultSet, Void> expect(final String... expected) {
-    return resultSet -> {
-      try {
-        final List<String> lines = new ArrayList<>();
-        BaseGeodeAdapterIT.collect(lines, resultSet);
-        Assert.assertEquals(Arrays.asList(expected), lines);
-      } catch (SQLException e) {
-        throw new RuntimeException(e);
-      }
-      return null;
-    };
-  }
-
-  private static void collect(List<String> result, ResultSet resultSet)
-      throws SQLException {
-    final StringBuilder buf = new StringBuilder();
-    while (resultSet.next()) {
-      buf.setLength(0);
-      int n = resultSet.getMetaData().getColumnCount();
-      String sep = "";
-      for (int i = 1; i <= n; i++) {
-        buf.append(sep)
-            .append(resultSet.getMetaData().getColumnLabel(i))
-            .append("=")
-            .append(resultSet.getString(i));
-        sep = "; ";
-      }
-      result.add(toLinux(buf.toString()));
-    }
-  }
-
-  public static String toLinux(String s) {
-    return s.replaceAll("\r\n", "\n");
-  }
-
-  protected void checkSql(String model, String sql) throws SQLException {
-    checkSql(sql, model, output());
-  }
-
-  protected Function1<ResultSet, Void> output() {
-    return resultSet -> {
-      try {
-        output(resultSet, System.out);
-      } catch (SQLException e) {
-        throw new RuntimeException(e);
-      }
-      return null;
-    };
-  }
-
-  protected void checkSql(String model, String sql, final String... expected)
-      throws SQLException {
-    checkSql(sql, model, expect(expected));
-  }
-
-  protected void checkSql(String sql, String model, Function1<ResultSet, Void> 
fn)
-      throws SQLException {
-    Connection connection = null;
-    Statement statement = null;
-    try {
-      Properties info = new Properties();
-      info.put("model", jsonPath(model));
-      connection = DriverManager.getConnection("jdbc:calcite:", info);
-      statement = connection.createStatement();
-      final ResultSet resultSet = statement.executeQuery(sql);
-      fn.apply(resultSet);
-    } finally {
-      close(connection, statement);
-    }
-  }
-
-  private String jsonPath(String model) {
-    return resourcePath(model + ".json");
-  }
-
-  private String resourcePath(String path) {
-    return Sources.of(GeodeAdapterIT.class.getResource("/" + 
path)).file().getAbsolutePath();
-  }
-
-  private void output(ResultSet resultSet, PrintStream out)
-      throws SQLException {
-    final ResultSetMetaData metaData = resultSet.getMetaData();
-    final int columnCount = metaData.getColumnCount();
-    while (resultSet.next()) {
-      for (int i = 1; true; i++) {
-        out.print(resultSet.getString(i));
-        if (i < columnCount) {
-          out.print(", ");
-        } else {
-          out.println();
-          break;
-        }
-      }
-    }
-  }
-
-  private void close(Connection connection, Statement statement) {
-    if (statement != null) {
-      try {
-        statement.close();
-      } catch (SQLException e) {
-        // ignore
-      }
-    }
-    if (connection != null) {
-      try {
-        connection.close();
-      } catch (SQLException e) {
-        // ignore
-      }
-    }
-  }
-}
-
-// End BaseGeodeAdapterIT.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterBookshopIT.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterBookshopIT.java
 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterBookshopIT.java
deleted file mode 100644
index cd38841..0000000
--- 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterBookshopIT.java
+++ /dev/null
@@ -1,469 +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.geode.rel;
-
-import org.apache.calcite.test.CalciteAssert;
-import org.apache.calcite.util.Sources;
-import org.apache.calcite.util.Util;
-
-import com.google.common.collect.ImmutableMap;
-
-import org.junit.Test;
-
-/**
- * Tests for the {@code org.apache.calcite.adapter.geode} package.
- *
- * <p>Before calling this rel, you need to populate Geode, as follows:
- *
- * <blockquote><code>
- * git clone https://github.com/vlsi/calcite-test-dataset<br>
- * cd calcite-rel-dataset<br>
- * mvn install
- * </code></blockquote>
- *
- * <p>This will create a virtual machine with Geode and the "bookshop"
- * and "zips" rel dataset.
- */
-public class GeodeAdapterBookshopIT {
-  /**
-   * Connection factory based on the "geode relational " model.
-   */
-  public static final ImmutableMap<String, String> GEODE =
-      ImmutableMap.of("model",
-          
Sources.of(GeodeAdapterBookshopIT.class.getResource("/model-bookshop.json"))
-              .file().getAbsolutePath());
-
-
-  /**
-   * Whether to run Geode tests. Enabled by default, however rel is only
-   * included if "it" profile is activated ({@code -Pit}). To disable,
-   * specify {@code -Dcalcite.rel.geode=false} on the Java command line.
-   */
-  public static final boolean ENABLED = 
Util.getBooleanProperty("calcite.rel.geode", true);
-
-  /**
-   * Whether to run this rel.
-   */
-  protected boolean enabled() {
-    return ENABLED;
-  }
-
-  @Test
-  public void testSelect() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select * from \"BookMaster\"")
-        .returnsCount(3);
-  }
-
-  @Test
-  public void testWhereEqual() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select * from \"BookMaster\" WHERE \"itemNumber\" = 123")
-        .returnsCount(1)
-        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane;"
-            + " retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
-            + "Treatises\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeFilter(condition=[=(CAST($0):INTEGER, 123)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  @Test
-  public void testWhereWithAnd() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select * from \"BookMaster\" WHERE \"itemNumber\" > 122 "
-            + "AND \"itemNumber\" <= 123")
-        .returnsCount(1)
-        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane; "
-            + "retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
-            + "Treatises\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeFilter(condition=[AND(>($0, 122), <=($0, 123))])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  @Test
-  public void testWhereWithOr() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"author\" from \"BookMaster\" "
-            + "WHERE \"itemNumber\" = 123 OR \"itemNumber\" = 789")
-        .returnsCount(2)
-        .returnsUnordered("author=Jim Heavisides", "author=Daisy Mae West")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(author=[$4])\n"
-            + "    GeodeFilter(condition=[OR(=(CAST($0):INTEGER, 123), "
-            + "=(CAST($0):INTEGER, 789))])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testWhereWithAndOr() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("SELECT \"author\" from \"BookMaster\" "
-            + "WHERE (\"itemNumber\" > 123 AND \"itemNumber\" = 789) "
-            + "OR \"author\"='Daisy Mae West'")
-        .returnsCount(2)
-        .returnsUnordered("author=Jim Heavisides", "author=Daisy Mae West")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(author=[$4])\n"
-            + "    GeodeFilter(condition=[OR(AND(>($0, 123), 
=(CAST($0):INTEGER, 789)), "
-            + "=(CAST($4):VARCHAR CHARACTER SET \"ISO-8859-1\" "
-            + "COLLATE \"ISO-8859-1$en_US$primary\", 'Daisy Mae West'))])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n"
-            + "\n");
-  }
-
-  // TODO: Not supported YET
-  @Test
-  public void testWhereWithOrAnd() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("SELECT \"author\" from \"BookMaster\" "
-            + "WHERE (\"itemNumber\" > 100 OR \"itemNumber\" = 789) "
-            + "AND \"author\"='Daisy Mae West'")
-        .returnsCount(1)
-        .returnsUnordered("author=Daisy Mae West")
-        .explainContains("");
-  }
-
-  @Test
-  public void testProjectionsAndWhereGreatThan() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"author\" from \"BookMaster\" WHERE \"itemNumber\" > 
123")
-        .returnsCount(2)
-        .returns("author=Clarence Meeks\n"
-            + "author=Jim Heavisides\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(author=[$4])\n"
-            + "    GeodeFilter(condition=[>($0, 123)])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  @Test
-  public void testLimit() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select * from \"BookMaster\" LIMIT 1")
-        .returnsCount(1)
-        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane; "
-            + "retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
-            + "Treatises\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeSort(fetch=[1])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  @Test
-  public void testSortWithProjection() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\" from \"BookMaster\" ORDER BY 
\"yearPublished\" ASC")
-        .returnsCount(3)
-        .returns("yearPublished=1971\n"
-            + "yearPublished=2011\n"
-            + "yearPublished=2011\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeSort(sort0=[$0], dir0=[ASC])\n"
-            + "    GeodeProject(yearPublished=[$3])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testSortWithProjectionAndLimit() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\" from \"BookMaster\" ORDER BY 
\"yearPublished\" "
-            + "LIMIT 2")
-        .returnsCount(2)
-        .returns("yearPublished=1971\n"
-            + "yearPublished=2011\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(yearPublished=[$3])\n"
-            + "    GeodeSort(sort0=[$3], dir0=[ASC], fetch=[2])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testSortBy2Columns() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\", \"itemNumber\" from \"BookMaster\" 
ORDER BY "
-            + "\"yearPublished\" ASC, \"itemNumber\" DESC")
-        .returnsCount(3)
-        .returns("yearPublished=1971; itemNumber=456\n"
-            + "yearPublished=2011; itemNumber=789\n"
-            + "yearPublished=2011; itemNumber=123\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(yearPublished=[$3], itemNumber=[$0])\n"
-            + "    GeodeSort(sort0=[$3], sort1=[$0], dir0=[ASC], 
dir1=[DESC])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  //
-  // TEST Group By and Aggregation Function Support
-  //
-
-  /**
-   * OQL Error: Query contains group by columns not present in projected fields
-   * Solution: Automatically expand the projections to include all missing 
GROUP By columns.
-   */
-  @Test
-  public void testAddMissingGroupByColumnToProjectedFields() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\" from \"BookMaster\" GROUP BY  
\"yearPublished\", "
-            + "\"author\"")
-        .returnsCount(3)
-        .returns("yearPublished=1971\n"
-            + "yearPublished=2011\n"
-            + "yearPublished=2011\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(yearPublished=[$0])\n"
-            + "    GeodeAggregate(group=[{3, 4}])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  /**
-   * When the group by columns match the projected fields, the optimizers 
removes the projected
-   * relation.
-   */
-  @Test
-  public void 
testMissingProjectRelationOnGroupByColumnMatchingProjectedFields() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\" from \"BookMaster\" GROUP BY 
\"yearPublished\"")
-        .returnsCount(2)
-        .returns("yearPublished=1971\n"
-            + "yearPublished=2011\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{3}])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  /**
-   * When the group by columns match the projected fields, the optimizers 
removes the projected
-   * relation.
-   */
-  @Test
-  public void 
testMissingProjectRelationOnGroupByColumnMatchingProjectedFields2() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\", MAX(\"retailCost\") from 
\"BookMaster\" GROUP BY "
-            + "\"yearPublished\"")
-        .returnsCount(2)
-        .returns("yearPublished=1971; EXPR$1=11.99\n"
-            + "yearPublished=2011; EXPR$1=59.99\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{3}], EXPR$1=[MAX($2)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])");
-  }
-
-  @Test
-  public void testCount() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select COUNT(\"retailCost\") from \"BookMaster\"")
-        .returnsCount(1)
-        .returns("EXPR$0=3\n")
-        .returnsValue("3")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{}], EXPR$0=[COUNT($2)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testCountStar() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select COUNT(*) from \"BookMaster\"")
-        .returnsCount(1)
-        .returns("EXPR$0=3\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{}], EXPR$0=[COUNT()])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testCountInGroupBy() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\", COUNT(\"retailCost\") from 
\"BookMaster\" GROUP BY "
-            + "\"yearPublished\"")
-        .returnsCount(2)
-        .returns("yearPublished=1971; EXPR$1=1\n"
-            + "yearPublished=2011; EXPR$1=2\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{3}], EXPR$1=[COUNT($2)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testMaxMinSumAvg() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select MAX(\"retailCost\"), MIN(\"retailCost\"), 
SUM(\"retailCost\"), AVG"
-            + "(\"retailCost\") from \"BookMaster\"")
-        .returnsCount(1)
-        .returns("EXPR$0=59.99; EXPR$1=11.99; EXPR$2=106.97000122070312; "
-            + "EXPR$3=35.65666580200195\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{}], EXPR$0=[MAX($2)], 
EXPR$1=[MIN($2)], EXPR$2=[SUM($2)"
-            + "], EXPR$3=[AVG($2)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testMaxMinSumAvgInGroupBy() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\", MAX(\"retailCost\"), 
MIN(\"retailCost\"), SUM"
-            + "(\"retailCost\"), AVG(\"retailCost\") from \"BookMaster\" "
-            + "GROUP BY  \"yearPublished\"")
-        .returnsCount(2)
-        .returns("yearPublished=2011; EXPR$1=59.99; EXPR$2=34.99; 
EXPR$3=94.9800033569336; "
-            + "EXPR$4=47.4900016784668\n"
-            + "yearPublished=1971; EXPR$1=11.99; EXPR$2=11.99; 
EXPR$3=11.989999771118164; "
-            + "EXPR$4=11.989999771118164\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeAggregate(group=[{3}], EXPR$1=[MAX($2)], 
EXPR$2=[MIN($2)], EXPR$3=[SUM($2)"
-            + "], EXPR$4=[AVG($2)])\n"
-            + "    GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testGroupBy() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"yearPublished\", MAX(\"retailCost\") AS MAXCOST, 
\"author\" from "
-            + "\"BookMaster\" GROUP BY \"yearPublished\", \"author\"")
-        .returnsCount(3)
-        .returns("yearPublished=2011; MAXCOST=59.99; author=Jim Heavisides\n"
-            + "yearPublished=1971; MAXCOST=11.99; author=Clarence Meeks\n"
-            + "yearPublished=2011; MAXCOST=34.99; author=Daisy Mae West\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(yearPublished=[$0], MAXCOST=[$2], author=[$1])\n"
-            + "    GeodeAggregate(group=[{3, 4}], MAXCOST=[MAX($2)])\n"
-            + "      GeodeTableScan(table=[[TEST, BookMaster]])\n");
-  }
-
-  @Test
-  public void testSelectWithNestedPdx() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select * from \"BookCustomer\" limit 2")
-        .returnsCount(2)
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeSort(fetch=[2])\n"
-            + "    GeodeTableScan(table=[[TEST, BookCustomer]])\n");
-  }
-
-  @Test
-  public void testSelectWithNestedPdx2() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"primaryAddress\" from \"BookCustomer\" limit 2")
-        .returnsCount(2)
-        
.returns("primaryAddress=PDX[addressLine1,addressLine2,addressLine3,city,state,"
-            + "postalCode,country,phoneNumber,addressTag]\n"
-            + 
"primaryAddress=PDX[addressLine1,addressLine2,addressLine3,city,state,postalCode,"
-            + "country,phoneNumber,addressTag]\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(primaryAddress=[$3])\n"
-            + "    GeodeSort(fetch=[2])\n"
-            + "      GeodeTableScan(table=[[TEST, BookCustomer]])\n");
-  }
-
-  @Test
-  public void testSelectWithNestedPdxFieldAccess() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"primaryAddress\"['city'] as \"city\" from 
\"BookCustomer\" limit 2")
-        .returnsCount(2)
-        .returns("city=Topeka\n"
-            + "city=San Francisco\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(city=[ITEM($3, 'city')])\n"
-            + "    GeodeSort(fetch=[2])\n"
-            + "      GeodeTableScan(table=[[TEST, BookCustomer]])\n");
-  }
-
-  @Test
-  public void testSelectWithNullFieldValue() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("select \"primaryAddress\"['addressLine2'] from 
\"BookCustomer\" limit"
-            + " 2")
-        .returnsCount(2)
-        .returns("EXPR$0=null\n"
-            + "EXPR$0=null\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(EXPR$0=[ITEM($3, 'addressLine2')])\n"
-            + "    GeodeSort(fetch=[2])\n"
-            + "      GeodeTableScan(table=[[TEST, BookCustomer]])\n");
-  }
-
-  @Test
-  public void testFilterWithNestedField() {
-    CalciteAssert.that()
-        .enable(enabled())
-        .with(GEODE)
-        .query("SELECT \"primaryAddress\"['postalCode'] AS \"postalCode\"\n"
-            + "FROM \"TEST\".\"BookCustomer\"\n"
-            + "WHERE \"primaryAddress\"['postalCode'] > '0'\n")
-        .returnsCount(3)
-        .returns("postalCode=50505\n"
-            + "postalCode=50505\n"
-            + "postalCode=50505\n")
-        .explainContains("PLAN=GeodeToEnumerableConverter\n"
-            + "  GeodeProject(postalCode=[ITEM($3, 'postalCode')])\n"
-            + "    GeodeFilter(condition=[>(ITEM($3, 'postalCode'), '0')])\n"
-            + "      GeodeTableScan(table=[[TEST, BookCustomer]])\n");
-  }
-
-}
-
-// End GeodeAdapterBookshopIT.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterIT.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterIT.java 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterIT.java
deleted file mode 100644
index f416d5e..0000000
--- 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAdapterIT.java
+++ /dev/null
@@ -1,99 +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.geode.rel;
-
-import org.junit.Test;
-
-import java.sql.SQLException;
-
-/**
- * Tests for the {@code org.apache.calcite.adapter.geode} package.
- *
- * <p>Before calling this rel, you need to populate Geode, as follows:
- *
- * <blockquote><code>
- * git clone https://github.com/vlsi/calcite-test-dataset<br>
- * cd calcite-rel-dataset<br>
- * mvn install
- * </code></blockquote>
- *
- * <p>This will create a virtual machine with Geode and the "bookshop" and 
"zips" rel dataset.
- */
-public class GeodeAdapterIT extends BaseGeodeAdapterIT {
-
-  @Test
-  public void testSqlSimple() throws SQLException {
-    checkSql("model-bookshop", "SELECT \"itemNumber\" "
-        + "FROM \"BookMaster\" WHERE \"itemNumber\" > 123");
-  }
-
-  @Test
-  public void testSqlSingleNumberWhereFilter() throws SQLException {
-    checkSql("model-bookshop", "SELECT * FROM \"BookMaster\" "
-        + "WHERE \"itemNumber\" = 123");
-  }
-
-  @Test
-  public void testSqlDistinctSort() throws SQLException {
-    checkSql("model-bookshop", "SELECT DISTINCT \"itemNumber\", \"author\" "
-        + "FROM \"BookMaster\" ORDER BY \"itemNumber\", \"author\"");
-  }
-
-  @Test
-  public void testSqlDistinctSort2() throws SQLException {
-    checkSql("model-bookshop", "SELECT \"itemNumber\", \"author\" "
-        + "FROM \"BookMaster\" GROUP BY \"itemNumber\", \"author\" ORDER BY 
\"itemNumber\", "
-        + "\"author\"");
-  }
-
-  @Test
-  public void testSqlDistinctSort3() throws SQLException {
-    checkSql("model-bookshop", "SELECT DISTINCT * FROM \"BookMaster\"");
-  }
-
-
-  @Test
-  public void testSqlLimit2() throws SQLException {
-    checkSql("model-bookshop", "SELECT DISTINCT * FROM \"BookMaster\" LIMIT 
2");
-  }
-
-
-  @Test
-  public void testSqlDisjunciton() throws SQLException {
-    checkSql("model-bookshop", "SELECT \"author\" FROM \"BookMaster\" "
-        + "WHERE \"itemNumber\" = 789 OR \"itemNumber\" = 123");
-  }
-
-  @Test
-  public void testSqlConjunciton() throws SQLException {
-    checkSql("model-bookshop", "SELECT \"author\" FROM \"BookMaster\" "
-        + "WHERE \"itemNumber\" = 789 AND \"author\" = 'Jim Heavisides'");
-  }
-
-  @Test
-  public void testSqlBookMasterWhere() throws SQLException {
-    checkSql("model-bookshop", "select \"author\", \"title\" from 
\"BookMaster\" "
-        + "WHERE \"author\" = \'Jim Heavisides\' LIMIT 2");
-  }
-
-  @Test
-  public void testSqlBookMasterCount() throws SQLException {
-    checkSql("model-bookshop", "select count(*) from \"BookMaster\"");
-  }
-}
-
-// End GeodeAdapterIT.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAssertions.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAssertions.java 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAssertions.java
new file mode 100644
index 0000000..037f7ba
--- /dev/null
+++ 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeAssertions.java
@@ -0,0 +1,44 @@
+/*
+ * 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.geode.rel;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Various validations for geode tests.
+ */
+class GeodeAssertions {
+
+  private GeodeAssertions() {}
+
+  static Consumer<List> query(final String query) {
+    return actual -> {
+      String actualString =
+          actual == null || actual.isEmpty()
+              ? null
+              : ((String) actual.get(0));
+
+      assertEquals(query, actualString);
+    };
+  }
+
+}
+
+// End GeodeAssertions.java

http://git-wip-us.apache.org/repos/asf/calcite/blob/ed424ed8/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeBookstoreTest.java
----------------------------------------------------------------------
diff --git 
a/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeBookstoreTest.java
 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeBookstoreTest.java
new file mode 100644
index 0000000..12cc34e
--- /dev/null
+++ 
b/geode/src/test/java/org/apache/calcite/adapter/geode/rel/GeodeBookstoreTest.java
@@ -0,0 +1,483 @@
+/*
+ * 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.geode.rel;
+
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.test.CalciteAssert;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+/**
+ * Tests using {@code Bookshop} schema.
+ */
+public class GeodeBookstoreTest extends AbstractGeodeTest {
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    Cache cache = POLICY.cache();
+    Region<?, ?> bookMaster =  cache.<String, 
Object>createRegionFactory().create("BookMaster");
+    new JsonLoader(bookMaster).loadClasspathResource("/book_master.json");
+
+    Region<?, ?> bookCustomer =  cache.<String, 
Object>createRegionFactory().create("BookCustomer");
+    new JsonLoader(bookCustomer).loadClasspathResource("/book_customer.json");
+
+  }
+
+  private CalciteAssert.ConnectionFactory newConnectionFactory() {
+    return new CalciteAssert.ConnectionFactory() {
+      @Override public Connection createConnection() throws SQLException {
+        final Connection connection = 
DriverManager.getConnection("jdbc:calcite:lex=JAVA");
+        final SchemaPlus root = 
connection.unwrap(CalciteConnection.class).getRootSchema();
+        root.add("geode",
+            new GeodeSchema(POLICY.cache(), Arrays.asList("BookMaster", 
"BookCustomer")));
+        return connection;
+      }
+    };
+  }
+
+  private CalciteAssert.AssertThat calciteAssert() {
+    return CalciteAssert.that()
+        .with(newConnectionFactory());
+  }
+
+  @Test
+  public void testSelect() {
+    calciteAssert()
+        .query("select * from geode.BookMaster")
+        .returnsCount(3);
+  }
+
+  @Test
+  public void testWhereEqual() {
+    calciteAssert()
+        .query("select * from geode.BookMaster WHERE itemNumber = 123")
+        .returnsCount(1)
+        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane;"
+            + " retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
+            + "Treatises\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeFilter(condition=[=(CAST($0):INTEGER, 123)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  @Test
+  public void testWhereWithAnd() {
+    calciteAssert()
+        .query("select * from geode.BookMaster WHERE itemNumber > 122 "
+            + "AND itemNumber <= 123")
+        .returnsCount(1)
+        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane; "
+            + "retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
+            + "Treatises\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeFilter(condition=[AND(>($0, 122), <=($0, 123))])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  @Test
+  public void testWhereWithOr() {
+    calciteAssert()
+        .query("select author from geode.BookMaster "
+            + "WHERE itemNumber = 123 OR itemNumber = 789")
+        .returnsCount(2)
+        .returnsUnordered("author=Jim Heavisides", "author=Daisy Mae West")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(author=[$4])\n"
+            + "    GeodeFilter(condition=[OR(=(CAST($0):INTEGER, 123), "
+            + "=(CAST($0):INTEGER, 789))])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testWhereWithAndOr() {
+    calciteAssert()
+        .query("SELECT author from geode.BookMaster "
+            + "WHERE (itemNumber > 123 AND itemNumber = 789) "
+            + "OR author='Daisy Mae West'")
+        .returnsCount(2)
+        .returnsUnordered("author=Jim Heavisides", "author=Daisy Mae West")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(author=[$4])\n"
+            + "    GeodeFilter(condition=[OR(AND(>($0, 123), 
=(CAST($0):INTEGER, 789)), "
+            + "=(CAST($4):VARCHAR CHARACTER SET \"ISO-8859-1\" "
+            + "COLLATE \"ISO-8859-1$en_US$primary\", 'Daisy Mae West'))])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])\n"
+            + "\n");
+  }
+
+  // TODO: Not supported YET
+  @Test
+  public void testWhereWithOrAnd() {
+    calciteAssert()
+        .query("SELECT author from geode.BookMaster "
+            + "WHERE (itemNumber > 100 OR itemNumber = 789) "
+            + "AND author='Daisy Mae West'")
+        .returnsCount(1)
+        .returnsUnordered("author=Daisy Mae West")
+        .explainContains("");
+  }
+
+  @Test
+  public void testProjectionsAndWhereGreatThan() {
+    calciteAssert()
+        .query("select author from geode.BookMaster WHERE itemNumber > 123")
+        .returnsCount(2)
+        .returns("author=Clarence Meeks\n"
+            + "author=Jim Heavisides\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(author=[$4])\n"
+            + "    GeodeFilter(condition=[>($0, 123)])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  @Test
+  public void testLimit() {
+    calciteAssert()
+        .query("select * from geode.BookMaster LIMIT 1")
+        .returnsCount(1)
+        .returns("itemNumber=123; description=Run on sentences and drivel on 
all things mundane; "
+            + "retailCost=34.99; yearPublished=2011; author=Daisy Mae West; 
title=A Treatise of "
+            + "Treatises\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeSort(fetch=[1])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  @Test
+  public void testSortWithProjection() {
+    calciteAssert()
+        .query("select yearPublished from geode.BookMaster ORDER BY 
yearPublished ASC")
+        .returnsCount(3)
+        .returns("yearPublished=1971\n"
+            + "yearPublished=2011\n"
+            + "yearPublished=2011\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeSort(sort0=[$0], dir0=[ASC])\n"
+            + "    GeodeProject(yearPublished=[$3])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testSortWithProjectionAndLimit() {
+    calciteAssert()
+        .query("select yearPublished from geode.BookMaster ORDER BY 
yearPublished "
+            + "LIMIT 2")
+        .returnsCount(2)
+        .returns("yearPublished=1971\n"
+            + "yearPublished=2011\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(yearPublished=[$3])\n"
+            + "    GeodeSort(sort0=[$3], dir0=[ASC], fetch=[2])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testSortBy2Columns() {
+    calciteAssert()
+        .query("select yearPublished, itemNumber from geode.BookMaster ORDER 
BY "
+            + "yearPublished ASC, itemNumber DESC")
+        .returnsCount(3)
+        .returns("yearPublished=1971; itemNumber=456\n"
+            + "yearPublished=2011; itemNumber=789\n"
+            + "yearPublished=2011; itemNumber=123\n")
+        .queryContains(
+            GeodeAssertions.query("SELECT yearPublished AS yearPublished, "
+              + "itemNumber AS itemNumber "
+              + "FROM /BookMaster ORDER BY yearPublished ASC, itemNumber 
DESC"));
+  }
+
+  //
+  // geode Group By and Aggregation Function Support
+  //
+
+  /**
+   * OQL Error: Query contains group by columns not present in projected fields
+   * Solution: Automatically expand the projections to include all missing 
GROUP By columns.
+   */
+  @Test
+  public void testAddMissingGroupByColumnToProjectedFields() {
+    calciteAssert()
+        .query("select yearPublished from geode.BookMaster GROUP BY  
yearPublished, "
+            + "author")
+        .returnsCount(3)
+        .returns("yearPublished=1971\n"
+            + "yearPublished=2011\n"
+            + "yearPublished=2011\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(yearPublished=[$0])\n"
+            + "    GeodeAggregate(group=[{3, 4}])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  /**
+   * When the group by columns match the projected fields, the optimizers 
removes the projected
+   * relation.
+   */
+  @Test
+  public void 
testMissingProjectRelationOnGroupByColumnMatchingProjectedFields() {
+    calciteAssert()
+        .query("select yearPublished from geode.BookMaster GROUP BY 
yearPublished")
+        .returnsCount(2)
+        .returns("yearPublished=1971\n"
+            + "yearPublished=2011\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{3}])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  /**
+   * When the group by columns match the projected fields, the optimizers 
removes the projected
+   * relation.
+   */
+  @Test
+  public void 
testMissingProjectRelationOnGroupByColumnMatchingProjectedFields2() {
+    calciteAssert()
+        .query("select yearPublished, MAX(retailCost) from geode.BookMaster 
GROUP BY "
+            + "yearPublished")
+        .returnsCount(2)
+        .returns("yearPublished=1971; EXPR$1=11.99\n"
+            + "yearPublished=2011; EXPR$1=59.99\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{3}], EXPR$1=[MAX($2)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])");
+  }
+
+  @Test
+  public void testCount() {
+    calciteAssert()
+        .query("select COUNT(retailCost) from geode.BookMaster")
+        .returnsCount(1)
+        .returns("EXPR$0=3\n")
+        .returnsValue("3")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{}], EXPR$0=[COUNT($2)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testCountStar() {
+    calciteAssert()
+        .query("select COUNT(*) from geode.BookMaster")
+        .returnsCount(1)
+        .returns("EXPR$0=3\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{}], EXPR$0=[COUNT()])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testCountInGroupBy() {
+    calciteAssert()
+        .query("select yearPublished, COUNT(retailCost) from geode.BookMaster 
GROUP BY "
+            + "yearPublished")
+        .returnsCount(2)
+        .returns("yearPublished=1971; EXPR$1=1\n"
+            + "yearPublished=2011; EXPR$1=2\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{3}], EXPR$1=[COUNT($2)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testMaxMinSumAvg() {
+    calciteAssert()
+        .query("select MAX(retailCost), MIN(retailCost), SUM(retailCost), AVG"
+            + "(retailCost) from geode.BookMaster")
+        .returnsCount(1)
+        .returns("EXPR$0=59.99; EXPR$1=11.99; EXPR$2=106.97000122070312; "
+            + "EXPR$3=35.65666580200195\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{}], EXPR$0=[MAX($2)], 
EXPR$1=[MIN($2)], EXPR$2=[SUM($2)"
+            + "], EXPR$3=[AVG($2)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testMaxMinSumAvgInGroupBy() {
+    calciteAssert()
+        .query("select yearPublished, MAX(retailCost), MIN(retailCost), SUM"
+            + "(retailCost), AVG(retailCost) from geode.BookMaster "
+            + "GROUP BY  yearPublished")
+        .returnsCount(2)
+        .returns("yearPublished=2011; EXPR$1=59.99; EXPR$2=34.99; 
EXPR$3=94.9800033569336; "
+            + "EXPR$4=47.4900016784668\n"
+            + "yearPublished=1971; EXPR$1=11.99; EXPR$2=11.99; 
EXPR$3=11.989999771118164; "
+            + "EXPR$4=11.989999771118164\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeAggregate(group=[{3}], EXPR$1=[MAX($2)], 
EXPR$2=[MIN($2)], EXPR$3=[SUM($2)"
+            + "], EXPR$4=[AVG($2)])\n"
+            + "    GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testGroupBy() {
+    calciteAssert()
+        .query("select yearPublished, MAX(retailCost) AS MAXCOST, author from "
+            + "geode.BookMaster GROUP BY yearPublished, author")
+        .returnsCount(3)
+        .returnsUnordered("yearPublished=2011; MAXCOST=59.99; author=Jim 
Heavisides",
+            "yearPublished=1971; MAXCOST=11.99; author=Clarence Meeks",
+            "yearPublished=2011; MAXCOST=34.99; author=Daisy Mae West")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(yearPublished=[$0], MAXCOST=[$2], author=[$1])\n"
+            + "    GeodeAggregate(group=[{3, 4}], MAXCOST=[MAX($2)])\n"
+            + "      GeodeTableScan(table=[[geode, BookMaster]])\n");
+  }
+
+  @Test
+  public void testSelectWithNestedPdx() {
+    calciteAssert()
+        .query("select * from geode.BookCustomer limit 2")
+        .returnsCount(2)
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeSort(fetch=[2])\n"
+            + "    GeodeTableScan(table=[[geode, BookCustomer]])\n");
+  }
+
+  @Test
+  public void testSelectWithNestedPdx2() {
+    calciteAssert()
+        .query("select primaryAddress from geode.BookCustomer limit 2")
+        .returnsCount(2)
+        
.returns("primaryAddress=PDX[addressLine1,addressLine2,addressLine3,city,state,"
+            + "postalCode,country,phoneNumber,addressTag]\n"
+            + 
"primaryAddress=PDX[addressLine1,addressLine2,addressLine3,city,state,postalCode,"
+            + "country,phoneNumber,addressTag]\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(primaryAddress=[$3])\n"
+            + "    GeodeSort(fetch=[2])\n"
+            + "      GeodeTableScan(table=[[geode, BookCustomer]])\n");
+  }
+
+  @Test
+  public void testSelectWithNestedPdxFieldAccess() {
+    calciteAssert()
+        .query("select primaryAddress['city'] as city from geode.BookCustomer 
limit 2")
+        .returnsCount(2)
+        .returns("city=Topeka\n"
+            + "city=San Francisco\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(city=[ITEM($3, 'city')])\n"
+            + "    GeodeSort(fetch=[2])\n"
+            + "      GeodeTableScan(table=[[geode, BookCustomer]])\n");
+  }
+
+  @Test
+  public void testSelectWithNullFieldValue() {
+    calciteAssert()
+        .query("select primaryAddress['addressLine2'] from geode.BookCustomer 
limit"
+            + " 2")
+        .returnsCount(2)
+        .returns("EXPR$0=null\n"
+            + "EXPR$0=null\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(EXPR$0=[ITEM($3, 'addressLine2')])\n"
+            + "    GeodeSort(fetch=[2])\n"
+            + "      GeodeTableScan(table=[[geode, BookCustomer]])\n");
+  }
+
+  @Test
+  public void testFilterWithNestedField() {
+    calciteAssert()
+        .query("SELECT primaryAddress['postalCode'] AS postalCode\n"
+            + "FROM geode.BookCustomer\n"
+            + "WHERE primaryAddress['postalCode'] > '0'\n")
+        .returnsCount(3)
+        .returns("postalCode=50505\n"
+            + "postalCode=50505\n"
+            + "postalCode=50505\n")
+        .explainContains("PLAN=GeodeToEnumerableConverter\n"
+            + "  GeodeProject(postalCode=[ITEM($3, 'postalCode')])\n"
+            + "    GeodeFilter(condition=[>(ITEM($3, 'postalCode'), '0')])\n"
+            + "      GeodeTableScan(table=[[geode, BookCustomer]])\n");
+  }
+
+  @Test
+  public void testSqlSimple() throws SQLException {
+    calciteAssert()
+        .query("SELECT itemNumber FROM geode.BookMaster WHERE itemNumber > 
123")
+        .runs();
+  }
+
+  @Test
+  public void testSqlSingleNumberWhereFilter() throws SQLException {
+    calciteAssert().query("SELECT * FROM geode.BookMaster "
+        + "WHERE itemNumber = 123").runs();
+  }
+
+  @Test
+  public void testSqlDistinctSort() throws SQLException {
+    calciteAssert().query("SELECT DISTINCT itemNumber, author "
+        + "FROM geode.BookMaster ORDER BY itemNumber, author").runs();
+  }
+
+  @Test
+  public void testSqlDistinctSort2() throws SQLException {
+    calciteAssert().query("SELECT itemNumber, author "
+        + "FROM geode.BookMaster GROUP BY itemNumber, author ORDER BY 
itemNumber, "
+        + "author").runs();
+  }
+
+  @Test
+  public void testSqlDistinctSort3() throws SQLException {
+    calciteAssert().query("SELECT DISTINCT * FROM geode.BookMaster").runs();
+  }
+
+
+  @Test
+  public void testSqlLimit2() throws SQLException {
+    calciteAssert().query("SELECT DISTINCT * FROM geode.BookMaster LIMIT 
2").runs();
+  }
+
+
+  @Test
+  public void testSqlDisjunciton() throws SQLException {
+    calciteAssert().query("SELECT author FROM geode.BookMaster "
+        + "WHERE itemNumber = 789 OR itemNumber = 123").runs();
+  }
+
+  @Test
+  public void testSqlConjunciton() throws SQLException {
+    calciteAssert().query("SELECT author FROM geode.BookMaster "
+        + "WHERE itemNumber = 789 AND author = 'Jim Heavisides'").runs();
+  }
+
+  @Test
+  public void testSqlBookMasterWhere() throws SQLException {
+    calciteAssert().query("select author, title from geode.BookMaster "
+        + "WHERE author = 'Jim Heavisides' LIMIT 2")
+        .runs();
+  }
+
+  @Test
+  public void testSqlBookMasterCount() throws SQLException {
+    calciteAssert().query("select count(*) from geode.BookMaster").runs();
+  }
+
+}
+
+// End GeodeBookstoreTest.java

Reply via email to