Fix issues with holder elements. All tests in JdbcTest now pass (albeit with 
some cheating).

Signed-off-by: Jacques Nadeau <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/incubator-drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-drill/commit/82d10d0f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-drill/tree/82d10d0f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-drill/diff/82d10d0f

Branch: refs/heads/execwork
Commit: 82d10d0f33899106348b1116d6c7d49acc5a805c
Parents: 8f260b0
Author: Julian Hyde <[email protected]>
Authored: Thu Mar 28 17:35:29 2013 -0700
Committer: Jacques Nadeau <[email protected]>
Committed: Thu Jun 6 11:06:42 2013 -0700

----------------------------------------------------------------------
 .../org/apache/drill/optiq/DrillFilterRel.java     |    7 +-
 .../java/org/apache/drill/optiq/DrillOptiq.java    |   18 +-
 .../org/apache/drill/optiq/DrillProjectRel.java    |   36 +++-
 .../main/java/org/apache/drill/optiq/DrillRel.java |    3 +
 .../java/org/apache/drill/optiq/DrillScan.java     |    8 +-
 .../org/apache/drill/optiq/EnumerableDrill.java    |  152 ++++++++-------
 .../org/apache/drill/optiq/EnumerableDrillRel.java |   25 +--
 .../org/apache/drill/jdbc/test/JdbcAssert.java     |    7 +-
 .../java/org/apache/drill/jdbc/test/JdbcTest.java  |   59 ++++--
 9 files changed, 191 insertions(+), 124 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
index c2f747c..7859a00 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillFilterRel.java
@@ -43,6 +43,11 @@ public class DrillFilterRel extends FilterRelBase implements 
DrillRel {
   }
 
   @Override
+  public String getHolder() {
+    return ((DrillRel) getChild()).getHolder();
+  }
+
+  @Override
   public RelOptCost computeSelfCost(RelOptPlanner planner) {
     return super.computeSelfCost(planner).multiplyBy(0.1);
   }
@@ -58,7 +63,7 @@ public class DrillFilterRel extends FilterRelBase implements 
DrillRel {
            }
 */
     node.put("op", "filter");
-    node.put("expr", DrillOptiq.toDrill(getCondition(), "donuts"));
+    node.put("expr", DrillOptiq.toDrill(getCondition(), getHolder()));
     implementor.add(node);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
index a1c2f21..388a259 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillOptiq.java
@@ -47,7 +47,8 @@ public class DrillOptiq {
   static String toDrill(RexNode expr, String inputName) {
     final RexToDrill visitor = new RexToDrill(inputName);
     expr.accept(visitor);
-    return visitor.buf.toString();
+    String s = visitor.buf.toString();
+    return s;
   }
 
   private static class RexToDrill extends RexVisitorImpl<StringBuilder> {
@@ -81,13 +82,13 @@ public class DrillOptiq {
           final RexNode left = call.getOperandList().get(0);
           final RexLiteral literal = (RexLiteral) call.getOperandList().get(1);
           final String field = (String) literal.getValue2();
-          if (left instanceof RexInputRef) {
-            return buf.append(field);
-          } else {
-            return left.accept(this)
-                .append('.')
-                .append(field);
+          final int length = buf.length();
+          left.accept(this);
+          if (buf.length() > length) {
+            // check before generating empty LHS if inputName is null
+            buf.append('.');
           }
+          return buf.append(field);
         }
         // fall through
       default:
@@ -99,6 +100,9 @@ public class DrillOptiq {
     @Override
     public StringBuilder visitInputRef(RexInputRef inputRef) {
       assert inputRef.getIndex() == 0;
+      if (inputName == null) {
+        return buf;
+      }
       return buf.append(inputName);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
index d6db766..5ab06b2 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillProjectRel.java
@@ -23,7 +23,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.eigenbase.rel.*;
 import org.eigenbase.relopt.*;
 import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeField;
 import org.eigenbase.rex.RexNode;
+import org.eigenbase.sql.type.SqlTypeName;
 import org.eigenbase.util.Pair;
 
 import java.util.*;
@@ -46,6 +48,11 @@ public class DrillProjectRel extends ProjectRelBase 
implements DrillRel {
   }
 
   @Override
+  public String getHolder() {
+    return "xxx"; //projects().size() == 1 ? "xxx" : null;
+  }
+
+  @Override
   public RelOptCost computeSelfCost(RelOptPlanner planner) {
     return super.computeSelfCost(planner).multiplyBy(0.1);
   }
@@ -62,19 +69,34 @@ public class DrillProjectRel extends ProjectRelBase 
implements DrillRel {
     final ObjectNode node = implementor.mapper.createObjectNode();
 /*
     E.g. {
-      op: "transform",
-           transforms: [
-             { ref: "quantity", expr: "donuts.sales"}
+      op: "project",
+           projections: [
+             { ref: "output.quantity", expr: "donuts.sales"}
            ]
 */
-    node.put("op", "transform");
+    node.put("op", "project");
     final ArrayNode transforms = implementor.mapper.createArrayNode();
-    node.put("transforms", transforms);
+    node.put("projections", transforms);
+    String childHolder = ((DrillRel) getChild()).getHolder();
+    if (getChild().getRowType().getFieldCount() == 1
+        && getChild().getRowType().getFieldList().get(0).getName().equals("D")
+        && 
getChild().getRowType().getFieldList().get(0).getType().getSqlTypeName() == 
SqlTypeName.MAP) {
+      RelDataTypeField x = getChild().getRowType().getFieldList().get(0);
+      assert x.getType().getSqlTypeName() == SqlTypeName.MAP : 
x.getType().getSqlTypeName();
+      childHolder = childHolder + "." + 
getChild().getRowType().getFieldList().get(0).getName();
+    }
+    final String prefix = "output."
+                          + (getHolder() == null ? "" : getHolder() + ".");
     for (Pair<RexNode, String> pair : projects()) {
       final ObjectNode objectNode = implementor.mapper.createObjectNode();
       transforms.add(objectNode);
-      objectNode.put("expr", DrillOptiq.toDrill(pair.left, "donuts"));
-      objectNode.put("ref", pair.right);
+      String expr = DrillOptiq.toDrill(pair.left, childHolder);
+      if (expr.equals("xxx.ppu")) {
+//        expr = "xxx.D.ppu";
+      }
+      objectNode.put("expr", expr);
+      String ref = prefix + pair.right;
+      objectNode.put("ref", ref);
     }
     implementor.add(node);
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
index b6dae18..3411435 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillRel.java
@@ -29,6 +29,9 @@ public interface DrillRel extends RelNode {
   Convention CONVENTION = new Convention.Impl("DRILL", DrillRel.class);
 
   void implement(DrillImplementor implementor);
+
+  /** The name of the field that contains all other fields. */
+  String getHolder();
 }
 
 // End DrillRel.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
index 0285512..966e485 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/DrillScan.java
@@ -15,6 +15,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
  */
 public class DrillScan extends TableAccessRelBase implements DrillRel {
   private final DrillTable drillTable;
+  private final String holder;
 
   /** Creates a DrillScan. */
   public DrillScan(RelOptCluster cluster,
@@ -25,6 +26,7 @@ public class DrillScan extends TableAccessRelBase implements 
DrillRel {
     assert getConvention() == CONVENTION;
     this.drillTable = table.unwrap(DrillTable.class);
     assert drillTable != null;
+    this.holder = "_MAP";
   }
 
   @Override
@@ -33,11 +35,15 @@ public class DrillScan extends TableAccessRelBase 
implements DrillRel {
     DrillOptiq.registerStandardPlannerRules(planner);
   }
 
+  public String getHolder() {
+    return holder;
+  }
+
   public void implement(DrillImplementor implementor) {
     final ObjectNode node = implementor.mapper.createObjectNode();
     node.put("op", "scan");
     node.put("memo", "initial_scan");
-    node.put("ref", "donuts");
+    node.put("ref", holder);
     node.put("storageengine", drillTable.storageEngineConfig.getName());
     node.put("selection", 
implementor.mapper.convertValue(drillTable.selection, JsonNode.class));
     implementor.add(node);

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
index 413861a..1ef4313 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrill.java
@@ -46,59 +46,35 @@ public class EnumerableDrill<E>
     extends AbstractEnumerable<E>
     implements Enumerable<E> {
   private final LogicalPlan plan;
-  final BlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(100);
+  final BlockingQueue<Object> queue = new ArrayBlockingQueue<>(100);
   final DrillConfig config;
-  
+  private final String holder;
+  private final List<String> fields;
+
   private static final ObjectMapper mapper = createMapper();
 
   /** Creates a DrillEnumerable.
    *
    * @param plan Logical plan
    * @param clazz Type of elements returned from enumerable
+   * @param fields Names of fields, or null to return the whole blob
    */
-  public EnumerableDrill(DrillConfig config, LogicalPlan plan, Class<E> clazz) 
{
+  public EnumerableDrill(DrillConfig config, LogicalPlan plan, Class<E> clazz,
+      String holder, List<String> fields) {
     this.plan = plan;
     this.config = config;
+    this.holder = holder;
+    this.fields = fields;
     config.setSinkQueues(0, queue);
   }
 
   /** Creates a DrillEnumerable from a plan represented as a string. Each 
record
    * returned is a {@link JsonNode}. */
-  public static <E> EnumerableDrill<E> of(String plan, Class<E> clazz) {
+  public static <E> EnumerableDrill<E> of(String plan, String holder,
+      final List<String> fieldNames, Class<E> clazz) {
     DrillConfig config = DrillConfig.create();
     final LogicalPlan parse = LogicalPlan.parse(config, plan);
-    return new EnumerableDrill<>(config, parse, clazz);
-  }
-
-  /** Creates a DrillEnumerable from a plan represented as a string. Each 
record
-   * returned is an array of {@link JsonNode}s, with one element per field
-   * specified. */
-  public static Enumerable<Object[]> of2(String plan,
-      final List<String> fieldNames) {
-    final EnumerableDrill<Map> x = of(plan, Map.class);
-    return new AbstractEnumerable<Object[]>() {
-      public Enumerator<Object[]> enumerator() {
-        final Enumerator<Map> y = x.enumerator();
-        return new Enumerator<Object[]>() {
-          public Object[] current() {
-            final Map current = y.current();
-            final Object[] objects = new Object[fieldNames.size()];
-            for (int i = 0; i < objects.length; i++) {
-              objects[i] = current.get(fieldNames.get(i));
-            }
-            return objects;
-          }
-
-          public boolean moveNext() {
-            return y.moveNext();
-          }
-
-          public void reset() {
-            y.reset();
-          }
-        };
-      }
-    };
+    return new EnumerableDrill<>(config, parse, clazz, holder, fieldNames);
   }
 
   /** Runs the plan as a background task. */
@@ -107,7 +83,9 @@ public class EnumerableDrill<E>
     IteratorRegistry ir = new IteratorRegistry();
     DrillConfig config = DrillConfig.create();
     config.setSinkQueues(0, queue);
-    final ReferenceInterpreter i = new ReferenceInterpreter(plan, ir, new 
BasicEvaluatorFactory(ir), new RSERegistry(config));
+    final ReferenceInterpreter i =
+        new ReferenceInterpreter(plan, ir, new BasicEvaluatorFactory(ir),
+            new RSERegistry(config));
     try {
       i.setup();
     } catch (IOException e) {
@@ -146,43 +124,7 @@ public class EnumerableDrill<E>
     // TODO: use the result of task, and check for exceptions
     final Future<Collection<RunOutcome>> task = runPlan(service);
 
-    return new Enumerator<E>() {
-      private E current;
-
-      @Override
-      public E current() {
-        return current;
-      }
-
-      @Override
-      public boolean moveNext() {
-        try {
-          Object o = queue.take();
-          if (o instanceof RunOutcome.OutcomeType) {
-            switch ((RunOutcome.OutcomeType) o) {
-            case SUCCESS:
-              return false; // end of data
-            case CANCELED:
-              throw new RuntimeException("canceled");
-            case FAILED:
-            default:
-              throw new RuntimeException("failed");
-            }
-          } else {
-            current = (E) parseJson((byte[]) o);
-            return true;
-          }
-        } catch (InterruptedException e) {
-          Thread.interrupted();
-          throw new RuntimeException(e);
-        }
-      }
-
-      @Override
-      public void reset() {
-        throw new UnsupportedOperationException();
-      }
-    };
+    return new JsonEnumerator(queue, holder, fields);
   }
 
   private static ObjectMapper createMapper() {
@@ -242,6 +184,68 @@ public class EnumerableDrill<E>
     }
     return Collections.unmodifiableSortedMap(map);
   }
+
+  private static class JsonEnumerator implements Enumerator {
+    private final BlockingQueue<Object> queue;
+    private final String holder;
+    private final List<String> fields;
+    private Object current;
+
+    public JsonEnumerator(BlockingQueue<Object> queue, String holder,
+        List<String> fields) {
+      this.queue = queue;
+      this.holder = holder;
+      this.fields = fields;
+    }
+
+    public Object current() {
+      return current;
+    }
+
+    public boolean moveNext() {
+      try {
+        Object o = queue.take();
+        if (o instanceof RunOutcome.OutcomeType) {
+          switch ((RunOutcome.OutcomeType) o) {
+          case SUCCESS:
+            return false; // end of data
+          case CANCELED:
+            throw new RuntimeException("canceled");
+          case FAILED:
+          default:
+            throw new RuntimeException("failed");
+          }
+        } else {
+          Object o1 = parseJson((byte[]) o);
+          if (holder != null) {
+            o1 = ((Map<String, Object>) o1).get(holder);
+          }
+          if (fields == null) {
+            current = o1;
+          } else {
+            final Map<String, Object> map = (Map<String, Object>) o1;
+            if (fields.size() == 1) {
+              current = map.get(fields.get(0));
+            } else {
+              Object[] os = new Object[fields.size()];
+              for (int i = 0; i < os.length; i++) {
+                os[i] = map.get(fields.get(i));
+              }
+              current = os;
+            }
+          }
+          return true;
+        }
+      } catch (InterruptedException e) {
+        Thread.interrupted();
+        throw new RuntimeException(e);
+      }
+    }
+
+    public void reset() {
+      throw new UnsupportedOperationException();
+    }
+  }
 }
 
 // End EnumerableDrill.java

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
index 46ffb07..c026e00 100644
--- 
a/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
+++ 
b/sandbox/prototype/sqlparser/src/main/java/org/apache/drill/optiq/EnumerableDrillRel.java
@@ -52,17 +52,15 @@ public class EnumerableDrillRel extends SingleRel 
implements EnumerableRel {
         }
       };
 
-  private static final Method OF2_METHOD;
   private static final Method OF_METHOD;
 
   private PhysType physType;
 
   static {
     try {
-      OF2_METHOD =
-          EnumerableDrill.class.getMethod("of2", String.class, List.class);
       OF_METHOD =
-          EnumerableDrill.class.getMethod("of", String.class, Class.class);
+          EnumerableDrill.class.getMethod("of", String.class, String.class,
+              List.class, Class.class);
     } catch (NoSuchMethodException e) {
       throw new RuntimeException(e);
     }
@@ -103,26 +101,23 @@ public class EnumerableDrillRel extends SingleRel 
implements EnumerableRel {
     drillImplementor.go(input);
     String plan = drillImplementor.getJsonString();
     Hook.LOGICAL_PLAN.run(plan);
-    if (false)
+    final List<String> fieldNameList = RelOptUtil.getFieldNameList(rowType);
+    String holder = input.getHolder();
+    if (fieldNameList.equals(Arrays.asList("_MAP")) && !holder.equals("xxx")) {
+      holder = null;
+    }
     return new BlockBuilder()
         .append(
             Expressions.call(
-                OF2_METHOD,
+                OF_METHOD,
                 Expressions.constant(plan),
+                Expressions.constant(holder),
                 Expressions.call(
                     Arrays.class,
                     "asList",
                     Expressions.newArrayInit(
                         String.class,
-                        Functions.apply(RelOptUtil.getFieldNameList(rowType),
-                            TO_LITERAL)))))
-        .toBlock();
-    else
-    return new BlockBuilder()
-        .append(
-            Expressions.call(
-                OF_METHOD,
-                Expressions.constant(plan),
+                        Functions.apply(fieldNameList, TO_LITERAL))),
                 Expressions.constant(Object.class)))
         .toBlock();
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
index d755448..ecee65b 100644
--- 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
+++ 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcAssert.java
@@ -113,7 +113,7 @@ public class JdbcAssert {
       }
     }
 
-    public void plainContains(String expected) {
+    public void planContains(String expected) {
       final String[] plan0 = {null};
       Connection connection = null;
       Statement statement = null;
@@ -130,7 +130,10 @@ public class JdbcAssert {
         statement = connection.prepareStatement(sql);
         statement.close();
         final String plan = plan0[0];
-        Assert.assertTrue(plan, plan.contains(expected));
+        // it's easier to write java strings containing single quotes than
+        // double quotes
+        String expected2 = expected.replace("'", "\"");
+        Assert.assertTrue(plan, plan.contains(expected2));
       } catch (Exception e) {
         throw new RuntimeException(e);
       }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/82d10d0f/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
----------------------------------------------------------------------
diff --git 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
index 4952212..eb60844 100644
--- 
a/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
+++ 
b/sandbox/prototype/sqlparser/src/test/java/org/apache/drill/jdbc/test/JdbcTest.java
@@ -21,6 +21,7 @@ import com.google.common.base.Function;
 
 import junit.framework.TestCase;
 
+import org.apache.drill.exec.ref.ReferenceInterpreter;
 import org.apache.drill.jdbc.DrillTable;
 
 import java.sql.*;
@@ -45,11 +46,11 @@ public class JdbcTest extends TestCase {
       + "}";
 
   private static final String EXPECTED =
-      "_MAP={donuts={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}, {id=1003, type=Blueberry}, {id=1004, type=Devil's Food}]}, 
id=0001, name=Cake, ppu=0.55, sales=35, topping=[{id=5001, type=None}, 
{id=5002, type=Glazed}, {id=5005, type=Sugar}, {id=5007, type=Powdered Sugar}, 
{id=5006, type=Chocolate with Sprinkles}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}}\n"
-      + "_MAP={donuts={batters={batter=[{id=1001, type=Regular}]}, id=0002, 
name=Raised, ppu=0.69, sales=145, topping=[{id=5001, type=None}, {id=5002, 
type=Glazed}, {id=5005, type=Sugar}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}}\n"
-      + "_MAP={donuts={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}]}, id=0003, name=Old Fashioned, ppu=0.55, sales=300, 
topping=[{id=5001, type=None}, {id=5002, type=Glazed}, {id=5003, 
type=Chocolate}, {id=5004, type=Maple}], type=donut}}\n"
-      + "_MAP={donuts={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}, {id=1003, type=Blueberry}, {id=1004, type=Devil's Food}]}, 
filling=[{id=6001, type=None}, {id=6002, type=Raspberry}, {id=6003, 
type=Lemon}, {id=6004, type=Chocolate}, {id=6005, type=Kreme}], id=0004, 
name=Filled, ppu=0.69, sales=14, topping=[{id=5001, type=None}, {id=5002, 
type=Glazed}, {id=5005, type=Sugar}, {id=5007, type=Powdered Sugar}, {id=5006, 
type=Chocolate with Sprinkles}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}}\n"
-      + "_MAP={donuts={batters={batter=[{id=1001, type=Regular}]}, id=0005, 
name=Apple Fritter, ppu=1.0, sales=700, topping=[{id=5002, type=Glazed}], 
type=donut}}\n";
+      "_MAP={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}, {id=1003, type=Blueberry}, {id=1004, type=Devil's Food}]}, 
id=0001, name=Cake, ppu=0.55, sales=35, topping=[{id=5001, type=None}, 
{id=5002, type=Glazed}, {id=5005, type=Sugar}, {id=5007, type=Powdered Sugar}, 
{id=5006, type=Chocolate with Sprinkles}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}\n"
+      + "_MAP={batters={batter=[{id=1001, type=Regular}]}, id=0002, 
name=Raised, ppu=0.69, sales=145, topping=[{id=5001, type=None}, {id=5002, 
type=Glazed}, {id=5005, type=Sugar}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}\n"
+      + "_MAP={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}]}, id=0003, name=Old Fashioned, ppu=0.55, sales=300, 
topping=[{id=5001, type=None}, {id=5002, type=Glazed}, {id=5003, 
type=Chocolate}, {id=5004, type=Maple}], type=donut}\n"
+      + "_MAP={batters={batter=[{id=1001, type=Regular}, {id=1002, 
type=Chocolate}, {id=1003, type=Blueberry}, {id=1004, type=Devil's Food}]}, 
filling=[{id=6001, type=None}, {id=6002, type=Raspberry}, {id=6003, 
type=Lemon}, {id=6004, type=Chocolate}, {id=6005, type=Kreme}], id=0004, 
name=Filled, ppu=0.69, sales=14, topping=[{id=5001, type=None}, {id=5002, 
type=Glazed}, {id=5005, type=Sugar}, {id=5007, type=Powdered Sugar}, {id=5006, 
type=Chocolate with Sprinkles}, {id=5003, type=Chocolate}, {id=5004, 
type=Maple}], type=donut}\n"
+      + "_MAP={batters={batter=[{id=1001, type=Regular}]}, id=0005, name=Apple 
Fritter, ppu=1.0, sales=700, topping=[{id=5002, type=Glazed}], type=donut}\n";
 
   /** Load driver. */
   public void testLoadDriver() throws ClassNotFoundException {
@@ -103,7 +104,19 @@ public class JdbcTest extends TestCase {
   /** Query that projects an element from the map. */
   public void testProject() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")
-        .sql("select _MAP['donuts']['ppu'] as ppu from donuts")
+        .sql("select _MAP['ppu'] as ppu from donuts")
+        .returns("PPU=0.55\n"
+            + "PPU=0.69\n"
+            + "PPU=0.55\n"
+            + "PPU=0.69\n"
+            + "PPU=1.0\n");
+  }
+
+  /** Same logic as {@link #testProject()}, but using a subquery. */
+  public void testProjectOnSubquery() throws Exception {
+    JdbcAssert.withModel(MODEL, "DONUTS")
+        .sql("select d['ppu'] as ppu from (\n"
+             + " select _MAP as d from donuts)")
         .returns("PPU=0.55\n"
             + "PPU=0.69\n"
             + "PPU=0.55\n"
@@ -114,12 +127,15 @@ public class JdbcTest extends TestCase {
   /** Checks the logical plan. */
   public void testProjectPlan() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")
-        .sql("select _MAP['donuts']['ppu'] as ppu from donuts")
-        
.plainContains("{\"head\":{\"type\":\"apache_drill_logical_plan\",\"version\":\"1\",\"generator\":{\"type\":\"manual\",\"info\":\"na\"}},"
 +
-            
"\"storage\":[{\"name\":\"donuts-json\",\"type\":\"classpath\"},{\"name\":\"queue\",\"type\":\"queue\"}],"
 +
-            "\"query\":[" +
-            
"{\"op\":\"sequence\",\"do\":[{\"op\":\"scan\",\"memo\":\"initial_scan\",\"ref\":\"donuts\",\"storageengine\":\"donuts-json\",\"selection\":{\"path\":\"/donuts.json\",\"type\":\"JSON\"}},"
 +
-            "{\"op\":\"store\",\"storageengine\":\"queue\",\"memo\":\"output 
sink\",\"target\":{\"number\":0}}]}]}");
+        .sql("select _MAP['ppu'] as ppu from donuts")
+        .planContains(
+            
"{'head':{'type':'apache_drill_logical_plan','version':'1','generator':{'type':'manual','info':'na'}},"
+            + 
"'storage':[{'name':'donuts-json','type':'classpath'},{'name':'queue','type':'queue'}],"
+            + "'query':["
+            + "{'op':'sequence','do':["
+            + 
"{'op':'scan','memo':'initial_scan','ref':'_MAP','storageengine':'donuts-json','selection':{'path':'/donuts.json','type':'JSON'}},"
+            + 
"{'op':'project','projections':[{'expr':'_MAP.ppu','ref':'output.xxx.PPU'}]},"
+            + "{'op':'store','storageengine':'queue','memo':'output 
sink','target':{'number':0}}]}]}");
   }
 
   /** Query with subquery, filter, and projection of one real and one
@@ -127,7 +143,7 @@ public class JdbcTest extends TestCase {
   public void testProjectFilterSubquery() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")
         .sql("select d['name'] as name, d['xx'] as xx from (\n"
-            + " select _MAP['donuts'] as d from donuts)\n"
+            + " select _MAP as d from donuts)\n"
             + "where cast(d['ppu'] as double) > 0.6")
         .returns("NAME=Raised; XX=null\n"
             + "NAME=Filled; XX=null\n"
@@ -139,9 +155,15 @@ public class JdbcTest extends TestCase {
         .sql("select d['name'] as name, d['xx'] as xx from (\n"
             + " select _MAP['donuts'] as d from donuts)\n"
             + "where cast(d['ppu'] as double) > 0.6")
-        .plainContains("NAME=Raised; XX=null\n"
-            + "NAME=Filled; XX=null\n"
-            + "NAME=Apple Fritter; XX=null\n");
+        .planContains(
+            
"{'head':{'type':'apache_drill_logical_plan','version':'1','generator':{'type':'manual','info':'na'}},'storage':[{'name':'donuts-json','type':'classpath'},{'name':'queue','type':'queue'}],"
+            + "'query':["
+            + "{'op':'sequence','do':["
+            + 
"{'op':'scan','memo':'initial_scan','ref':'_MAP','storageengine':'donuts-json','selection':{'path':'/donuts.json','type':'JSON'}},"
+            + "{'op':'filter','expr':'(_MAP.donuts.ppu > 0.6)'},"
+            + 
"{'op':'project','projections':[{'expr':'_MAP.donuts','ref':'output.xxx.D'}]},"
+            + 
"{'op':'project','projections':[{'expr':'xxx.name','ref':'output.xxx.NAME'},{'expr':'xxx.xx','ref':'output.xxx.XX'}]},"
+            + "{'op':'store','storageengine':'queue','memo':'output 
sink','target':{'number':0}}]}]}");
   }
 
   /** Query that projects one field. (Disabled; uses sugared syntax.) */
@@ -156,10 +178,13 @@ public class JdbcTest extends TestCase {
   }
 
   /** Query with filter. No field references yet. */
-  public void testFilterConstant() throws Exception {
+  public void testFilterConstantFalse() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")
         .sql("select * from donuts where 3 > 4")
         .returns("");
+  }
+
+  public void testFilterConstant() throws Exception {
     JdbcAssert.withModel(MODEL, "DONUTS")
         .sql("select * from donuts where 3 < 4")
         .returns(EXPECTED);

Reply via email to