You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by ja...@apache.org on 2014/05/08 04:50:44 UTC

[1/5] git commit: DRILL-627: Fix memory leaks in hash join and hash aggregate

Repository: incubator-drill
Updated Branches:
  refs/heads/master 85d52c744 -> b7bf00cbb


DRILL-627: Fix memory leaks in hash join and hash aggregate


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

Branch: refs/heads/master
Commit: d870b6e0ccd5765ca0738b3642ee459a1d15cceb
Parents: 85d52c7
Author: Mehant Baid <me...@gmail.com>
Authored: Sun May 4 13:52:08 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Wed May 7 18:43:08 2014 -0700

----------------------------------------------------------------------
 .../impl/aggregate/HashAggTemplate.java         |   4 +
 .../exec/physical/impl/join/HashJoinBatch.java  |  71 ++++---
 .../impl/join/HashJoinProbeTemplate.java        |  16 +-
 .../exec/physical/impl/join/TestHashJoin.java   |  33 +++-
 .../src/test/resources/join/hj_exchanges1.json  | 197 +++++++++++++++++++
 5 files changed, 287 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/d870b6e0/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java
index d7abcd2..c50a86a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/aggregate/HashAggTemplate.java
@@ -229,6 +229,10 @@ public abstract class HashAggTemplate implements HashAggregator {
         try{
 
           while(true){
+            // Cleanup the previous batch since we are done processing it.
+            for (VectorWrapper<?> v : incoming) {
+              v.getValueVector().clear();
+            }
             IterOutcome out = incoming.next();
             if(EXTRA_DEBUG_1) logger.debug("Received IterOutcome of {}", out);
             switch(out){

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/d870b6e0/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinBatch.java
index b624b30..883052a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinBatch.java
@@ -159,35 +159,52 @@ public class HashJoinBatch extends AbstractRecordBatch<HashJoinPOP> {
                 hashJoinProbe = setupHashJoinProbe();
             }
 
-            // Allocate the memory for the vectors in the output container
-            allocateVectors();
-
             // Store the number of records projected
-            outputRecords = hashJoinProbe.probeAndProject();
+            if (hashTable != null) {
 
-            /* We are here because of one the following
-             * 1. Completed processing of all the records and we are done
-             * 2. We've filled up the outgoing batch to the maximum and we need to return upstream
-             * Either case build the output container's schema and return
-             */
-            if (outputRecords > 0) {
+                // Allocate the memory for the vectors in the output container
+                allocateVectors();
+
+                outputRecords = hashJoinProbe.probeAndProject();
+
+                /* We are here because of one the following
+                 * 1. Completed processing of all the records and we are done
+                 * 2. We've filled up the outgoing batch to the maximum and we need to return upstream
+                 * Either case build the output container's schema and return
+                 */
+                if (outputRecords > 0) {
 
-                // Build the container schema and set the counts
-                container.buildSchema(BatchSchema.SelectionVectorMode.NONE);
-                container.setRecordCount(outputRecords);
+                  // Build the container schema and set the counts
+                  container.buildSchema(BatchSchema.SelectionVectorMode.NONE);
+                  container.setRecordCount(outputRecords);
 
-                for (VectorWrapper<?> v : container) {
+                  for (VectorWrapper<?> v : container) {
                     v.getValueVector().getMutator().setValueCount(outputRecords);
-                }
+                  }
 
-                // First output batch, return OK_NEW_SCHEMA
-                if (firstOutputBatch == true) {
+                  // First output batch, return OK_NEW_SCHEMA
+                  if (firstOutputBatch == true) {
                     firstOutputBatch = false;
                     return IterOutcome.OK_NEW_SCHEMA;
-                }
+                  }
 
-                // Not the first output batch
-                return IterOutcome.OK;
+                  // Not the first output batch
+                  return IterOutcome.OK;
+                }
+            } else {
+                // Our build side is empty, we won't have any matches, clear the probe side
+                if (leftUpstream == IterOutcome.OK_NEW_SCHEMA || leftUpstream == IterOutcome.OK) {
+                    for (VectorWrapper<?> wrapper : left) {
+                      wrapper.getValueVector().clear();
+                    }
+                    leftUpstream = left.next();
+                    while (leftUpstream == IterOutcome.OK_NEW_SCHEMA || leftUpstream == IterOutcome.OK) {
+                      for (VectorWrapper<?> wrapper : left) {
+                        wrapper.getValueVector().clear();
+                      }
+                      leftUpstream = left.next();
+                    }
+                }
             }
 
             // No more output records, clean up and return
@@ -220,11 +237,14 @@ public class HashJoinBatch extends AbstractRecordBatch<HashJoinPOP> {
         // Set the left named expression to be null if the probe batch is empty.
         if (leftUpstream != IterOutcome.OK_NEW_SCHEMA && leftUpstream != IterOutcome.OK) {
             leftExpr = null;
+        } else {
+          if (left.getSchema().getSelectionVectorMode() != BatchSchema.SelectionVectorMode.NONE) {
+            throw new SchemaChangeException("Hash join does not support probe batch with selection vectors");
+          }
         }
 
         HashTableConfig htConfig = new HashTableConfig(HashTable.DEFAULT_INITIAL_CAPACITY, HashTable.DEFAULT_LOAD_FACTOR, rightExpr, leftExpr);
 
-
         // Create the chained hash table
         ChainedHashTable ht  = new ChainedHashTable(htConfig, context, oContext.getAllocator(), this.right, this.left, null);
         hashTable = ht.createAndSetupHashTable(null);
@@ -250,6 +270,10 @@ public class HashJoinBatch extends AbstractRecordBatch<HashJoinPOP> {
                 case OK_NEW_SCHEMA:
                     if (rightSchema == null) {
                         rightSchema = right.getSchema();
+
+                        if (rightSchema.getSelectionVectorMode() != BatchSchema.SelectionVectorMode.NONE) {
+                          throw new SchemaChangeException("Hash join does not support build batch with selection vectors");
+                        }
                         setupHashTable();
                     } else {
                         throw new SchemaChangeException("Hash join does not support schema changes");
@@ -395,13 +419,14 @@ public class HashJoinBatch extends AbstractRecordBatch<HashJoinPOP> {
 
     @Override
     public void cleanup() {
-        hyperContainer.clear();
         hjHelper.clear();
-        container.clear();
 
         // If we didn't receive any data, hyperContainer may be null, check before clearing
         if (hyperContainer != null) {
             hyperContainer.clear();
+        }
+
+        if (hashTable != null) {
             hashTable.clear();
         }
         super.cleanup();

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/d870b6e0/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinProbeTemplate.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinProbeTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinProbeTemplate.java
index 0abf678..a3e3b74 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinProbeTemplate.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/HashJoinProbeTemplate.java
@@ -22,19 +22,13 @@ import javax.inject.Named;
 import org.apache.drill.exec.exception.ClassTransformationException;
 import org.apache.drill.exec.exception.SchemaChangeException;
 import org.apache.drill.exec.ops.FragmentContext;
-import org.apache.drill.exec.physical.impl.common.ChainedHashTable;
 import org.apache.drill.exec.physical.impl.common.HashTable;
-import org.apache.drill.exec.physical.impl.common.HashTableConfig;
-import org.apache.drill.exec.physical.impl.sort.RecordBatchData;
-import org.apache.drill.exec.record.BatchSchema;
-import org.apache.drill.exec.record.ExpandableHyperContainer;
+import org.apache.drill.exec.record.VectorWrapper;
 import org.apache.drill.exec.record.RecordBatch;
 import org.apache.drill.exec.record.RecordBatch.IterOutcome;
 import org.apache.drill.exec.record.VectorContainer;
-import org.apache.drill.exec.vector.allocator.VectorAllocator;
-import org.apache.drill.exec.expr.holders.IntHolder;
+
 import org.eigenbase.rel.JoinRelType;
-import org.eigenbase.sql2rel.StandardConvertletTable;
 
 import java.io.IOException;
 import java.util.List;
@@ -104,6 +98,12 @@ public abstract class HashJoinProbeTemplate implements HashJoinProbe {
 
             // Check if we have processed all records in this batch we need to invoke next
             if (recordsProcessed == recordsToProcess) {
+
+                // Done processing all records in the previous batch, clean up!
+                for (VectorWrapper<?> wrapper : probeBatch) {
+                    wrapper.getValueVector().clear();
+                }
+
                 IterOutcome leftUpstream = probeBatch.next();
 
                 switch (leftUpstream) {

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/d870b6e0/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestHashJoin.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestHashJoin.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestHashJoin.java
index 722d54f..ea83534 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestHashJoin.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestHashJoin.java
@@ -119,7 +119,7 @@ public class TestHashJoin extends PopUnitTestBase{
     @Test
     public void simpleEqualityJoin() throws Throwable {
 
-        // Function checks for casting from Float, Double to Decimal data types
+        // Function checks hash join with single equality condition
         try (RemoteServiceSet serviceSet = RemoteServiceSet.getLocalServiceSet();
              Drillbit bit = new Drillbit(CONFIG, serviceSet);
              DrillClient client = new DrillClient(CONFIG, serviceSet.getCoordinator())) {
@@ -157,7 +157,7 @@ public class TestHashJoin extends PopUnitTestBase{
     public void hjWithExchange(@Injectable final DrillbitContext bitContext,
                                @Injectable UserServer.UserClientConnection connection) throws Throwable {
 
-        // Function checks for casting from Float, Double to Decimal data types
+        // Function tests with hash join with exchanges
         try (RemoteServiceSet serviceSet = RemoteServiceSet.getLocalServiceSet();
              Drillbit bit = new Drillbit(CONFIG, serviceSet);
              DrillClient client = new DrillClient(CONFIG, serviceSet.getCoordinator())) {
@@ -183,7 +183,7 @@ public class TestHashJoin extends PopUnitTestBase{
     public void multipleConditionJoin(@Injectable final DrillbitContext bitContext,
                                       @Injectable UserServer.UserClientConnection connection) throws Throwable {
 
-        // Function checks for casting from Float, Double to Decimal data types
+        // Function tests hash join with multiple join conditions
         try (RemoteServiceSet serviceSet = RemoteServiceSet.getLocalServiceSet();
              Drillbit bit = new Drillbit(CONFIG, serviceSet);
              DrillClient client = new DrillClient(CONFIG, serviceSet.getCoordinator())) {
@@ -219,4 +219,31 @@ public class TestHashJoin extends PopUnitTestBase{
             assertEquals(3, intAccessor1.getValueCount());
         }
     }
+
+
+  @Test
+  public void hjWithExchange1(@Injectable final DrillbitContext bitContext,
+                              @Injectable UserServer.UserClientConnection connection) throws Throwable {
+
+    // Another test for hash join with exchanges
+    try (RemoteServiceSet serviceSet = RemoteServiceSet.getLocalServiceSet();
+         Drillbit bit = new Drillbit(CONFIG, serviceSet);
+         DrillClient client = new DrillClient(CONFIG, serviceSet.getCoordinator())) {
+
+      // run query.
+      bit.run();
+      client.connect();
+      List<QueryResultBatch> results = client.runQuery(UserProtos.QueryType.PHYSICAL,
+          Files.toString(FileUtils.getResourceAsFile("/join/hj_exchanges1.json"), Charsets.UTF_8));
+
+      int count = 0;
+      for(QueryResultBatch b : results) {
+        if (b.getHeader().getRowCount() != 0)
+          count += b.getHeader().getRowCount();
+      }
+
+      System.out.println("Total records: " + count);
+      assertEquals(272, count);
+    }
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/d870b6e0/exec/java-exec/src/test/resources/join/hj_exchanges1.json
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/join/hj_exchanges1.json b/exec/java-exec/src/test/resources/join/hj_exchanges1.json
new file mode 100644
index 0000000..7ccc324
--- /dev/null
+++ b/exec/java-exec/src/test/resources/join/hj_exchanges1.json
@@ -0,0 +1,197 @@
+{
+  "head" : {
+    "version" : 1,
+    "generator" : {
+      "type" : "DefaultSqlHandler",
+      "info" : ""
+    },
+    "type" : "APACHE_DRILL_PHYSICAL",
+    "resultMode" : "EXEC"
+  },
+  "graph" : [ {
+    "pop" : "parquet-scan",
+    "@id" : 1,
+    "entries" : [ {
+      "path" : "/tpch/customer.parquet"
+    } ],
+    "storage" : {
+      "type" : "file",
+      "connection" : "classpath:///",
+      "workspaces" : null,
+      "formats" : {
+        "json" : {
+          "type" : "json"
+        },
+        "parquet" : {
+          "type" : "parquet"
+        }
+      }
+    },
+    "format" : {
+      "type" : "parquet"
+    },
+    "selectionRoot" : "/tpch/customer.parquet"
+  }, {
+    "pop" : "filter",
+    "@id" : 2,
+    "child" : 1,
+    "expr" : "equal(cast( (`c_mktsegment` ) as VARCHAR(9) ), 'HOUSEHOLD') "
+  }, {
+    "pop" : "selection-vector-remover",
+    "@id" : 3,
+    "child" : 2
+  }, {
+    "pop" : "hash-to-random-exchange",
+    "@id" : 4,
+    "child" : 3,
+    "expr" : "hash(`c_custkey`) "
+  }, {
+    "pop" : "parquet-scan",
+    "@id" : 5,
+    "entries" : [ {
+      "path" : "/tpch/lineitem.parquet"
+    } ],
+    "storage" : {
+      "type" : "file",
+      "connection" : "classpath:///",
+      "workspaces" : null,
+      "formats" : {
+        "json" : {
+          "type" : "json"
+        },
+        "parquet" : {
+          "type" : "parquet"
+        }
+      }
+    },
+    "format" : {
+      "type" : "parquet"
+    },
+    "selectionRoot" : "/tpch/lineitem.parquet"
+  }, {
+    "pop" : "filter",
+    "@id" : 6,
+    "child" : 5,
+    "expr" : "greater_than(`l_shipdate`, cast( 796089600000 as DATE)) "
+  }, {
+    "pop" : "selection-vector-remover",
+    "@id" : 7,
+    "child" : 6
+  }, {
+    "pop" : "hash-to-random-exchange",
+    "@id" : 8,
+    "child" : 7,
+    "expr" : "hash(`l_orderkey`) "
+  }, {
+    "pop" : "project",
+    "@id" : 9,
+    "exprs" : [ {
+      "ref" : "`*1`",
+      "expr" : "`*`"
+    }, {
+      "ref" : "`l_orderkey`",
+      "expr" : "`l_orderkey`"
+    }, {
+      "ref" : "`l_shipdate`",
+      "expr" : "`l_shipdate`"
+    } ],
+    "child" : 8
+  }, {
+    "pop" : "parquet-scan",
+    "@id" : 10,
+    "entries" : [ {
+      "path" : "/tpch/orders.parquet"
+    } ],
+    "storage" : {
+      "type" : "file",
+      "connection" : "classpath:///",
+      "workspaces" : null,
+      "formats" : {
+        "json" : {
+          "type" : "json"
+        },
+        "parquet" : {
+          "type" : "parquet"
+        }
+      }
+    },
+    "format" : {
+      "type" : "parquet"
+    },
+    "selectionRoot" : "/tpch/orders.parquet"
+  }, {
+    "pop" : "filter",
+    "@id" : 11,
+    "child" : 10,
+    "expr" : "less_than(`o_orderdate`, cast( 796089600000 as DATE)) "
+  }, {
+    "pop" : "selection-vector-remover",
+    "@id" : 12,
+    "child" : 11
+  }, {
+    "pop" : "hash-to-random-exchange",
+    "@id" : 13,
+    "child" : 12,
+    "expr" : "hash(`o_custkey`) "
+  }, {
+    "pop" : "project",
+    "@id" : 14,
+    "exprs" : [ {
+      "ref" : "`*0`",
+      "expr" : "`*`"
+    }, {
+      "ref" : "`o_orderdate`",
+      "expr" : "`o_orderdate`"
+    }, {
+      "ref" : "`o_custkey`",
+      "expr" : "`o_custkey`"
+    }, {
+      "ref" : "`o_orderkey`",
+      "expr" : "`o_orderkey`"
+    } ],
+    "child" : 13
+  }, {
+    "pop" : "hash-join",
+    "@id" : 15,
+    "left" : 4,
+    "right" : 14,
+    "conditions" : [ {
+      "relationship" : "==",
+      "left" : "`c_custkey`",
+      "right" : "`o_custkey`"
+    } ],
+    "joinType" : "INNER"
+  }, {
+    "pop" : "hash-to-random-exchange",
+    "@id" : 16,
+    "child" : 15,
+    "expr" : "hash(`o_orderkey`) "
+  }, {
+    "pop" : "hash-join",
+    "@id" : 17,
+    "left" : 16,
+    "right" : 9,
+    "conditions" : [ {
+      "relationship" : "==",
+      "left" : "`o_orderkey`",
+      "right" : "`l_orderkey`"
+    } ],
+    "joinType" : "INNER"
+  }, {
+    "pop" : "project",
+    "@id" : 18,
+    "exprs" : [ {
+      "ref" : "`EXPR$0`",
+      "expr" : "1"
+    } ],
+    "child" : 17
+  }, {
+    "pop" : "union-exchange",
+    "@id" : 19,
+    "child" : 18
+  }, {
+    "pop" : "screen",
+    "@id" : 20,
+    "child" : 19
+  } ]
+}


[3/5] git commit: DRILL-577: Two way implicit casts

Posted by ja...@apache.org.
DRILL-577: Two way implicit casts


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

Branch: refs/heads/master
Commit: cd4f281e0c41707f79ccf3777d6245a13befeb18
Parents: f2ff2c9
Author: Mehant Baid <me...@gmail.com>
Authored: Wed May 7 12:25:39 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Wed May 7 18:43:18 2014 -0700

----------------------------------------------------------------------
 .../exec/expr/ExpressionTreeMaterializer.java   | 10 ++-
 .../exec/resolver/ResolverTypePrecedence.java   | 55 +++++++++++++-
 .../drill/exec/resolver/TypeCastRules.java      | 45 +++++++++--
 .../physical/impl/TestReverseImplicitCast.java  | 78 ++++++++++++++++++++
 .../functions/cast/two_way_implicit_cast.json   | 36 +++++++++
 5 files changed, 217 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/cd4f281e/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
index a602d82..95d341b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
@@ -156,7 +156,15 @@ public class ExpressionTreeMaterializer {
             List<LogicalExpression> castArgs = Lists.newArrayList();
             castArgs.add(call.args.get(i));  //input_expr
 
-            if (parmType.getMinorType().name().startsWith("DECIMAL")) {
+            if (!Types.isFixedWidthType(parmType)) {
+
+              /* We are implicitly casting to VARCHAR so we don't have a max length,
+               * using an arbitrary value. We trim down the size of the stored bytes
+               * to the actual size so this size doesn't really matter.
+               */
+              castArgs.add(new ValueExpressions.LongExpression(65536, null));
+            }
+            else if (parmType.getMinorType().name().startsWith("DECIMAL")) {
               // Add the scale and precision to the arguments of the implicit cast
               castArgs.add(new ValueExpressions.LongExpression(currentArg.getMajorType().getPrecision(), null));
               castArgs.add(new ValueExpressions.LongExpression(currentArg.getMajorType().getScale(), null));

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/cd4f281e/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
index f6d83e2..71bf616 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
@@ -19,7 +19,9 @@
 package org.apache.drill.exec.resolver;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.drill.common.types.TypeProtos.DataMode;
 import org.apache.drill.common.types.TypeProtos.MinorType;
@@ -27,7 +29,9 @@ import org.apache.drill.common.types.TypeProtos.MinorType;
 public class ResolverTypePrecedence {
 	
 
-public static final Map<MinorType, Integer> precedenceMap;
+  public static final Map<MinorType, Integer> precedenceMap;
+  public static final Map<MinorType, Set<MinorType>> secondaryImplicitCastRules;
+  public static int MAX_IMPLICIT_CAST_COST;
 
   static {    
     /* The precedenceMap is used to decide whether it's allowed to implicitly "promote" 
@@ -74,6 +78,55 @@ public static final Map<MinorType, Integer> precedenceMap;
     precedenceMap.put(MinorType.INTERVALDAY, i+= 2);
     precedenceMap.put(MinorType.INTERVALYEAR, i+= 2);
     precedenceMap.put(MinorType.INTERVAL, i+= 2);
+
+    MAX_IMPLICIT_CAST_COST = i;
+
+    /* Currently implicit cast follows the precedence rules.
+     * It may be useful to perform an implicit cast in
+     * the opposite direction as specified by the precedence rules.
+     *
+     * For example: As per the precedence rules we can implicitly cast
+     * from VARCHAR ---> BIGINT , but based upon some functions (eg: substr, concat)
+     * it may be useful to implicitly cast from BIGINT ---> VARCHAR.
+     *
+     * To allow for such cases we have a secondary set of rules which will allow the reverse
+     * implicit casts. Currently we only allow the reverse implicit cast to VARCHAR so we don't
+     * need any cost associated with it, if we add more of these that may collide we can add costs.
+     */
+    secondaryImplicitCastRules = new HashMap<>();
+    HashSet<MinorType> rule = new HashSet<>();
+
+    // Following cast functions should exist
+    rule.add(MinorType.TINYINT);
+    rule.add(MinorType.SMALLINT);
+    rule.add(MinorType.INT);
+    rule.add(MinorType.BIGINT);
+    rule.add(MinorType.UINT1);
+    rule.add(MinorType.UINT2);
+    rule.add(MinorType.UINT4);
+    rule.add(MinorType.UINT8);
+    rule.add(MinorType.DECIMAL9);
+    rule.add(MinorType.DECIMAL18);
+    rule.add(MinorType.DECIMAL28SPARSE);
+    rule.add(MinorType.DECIMAL28DENSE);
+    rule.add(MinorType.DECIMAL38SPARSE);
+    rule.add(MinorType.DECIMAL38DENSE);
+    rule.add(MinorType.MONEY);
+    rule.add(MinorType.FLOAT4);
+    rule.add(MinorType.FLOAT8);
+    rule.add(MinorType.BIT);
+    rule.add(MinorType.FIXEDCHAR);
+    rule.add(MinorType.FIXED16CHAR);
+    rule.add(MinorType.VARCHAR);
+    rule.add(MinorType.DATE);
+    rule.add(MinorType.TIME);
+    rule.add(MinorType.TIMESTAMP);
+    rule.add(MinorType.TIMESTAMPTZ);
+    rule.add(MinorType.INTERVAL);
+    rule.add(MinorType.INTERVALYEAR);
+    rule.add(MinorType.INTERVALDAY);
+
+    secondaryImplicitCastRules.put(MinorType.VARCHAR, rule);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/cd4f281e/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
index 3aab08f..515843d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
@@ -778,6 +778,8 @@ public class TypeCastRules {
            (rules.get(to.getMinorType()) == null ? false : rules.get(to.getMinorType()).contains(from.getMinorType()));
   }
 
+  private static final int DATAMODE_CAST_COST = 1;
+
   /*
    * code decide whether it's legal to do implicit cast. -1 : not allowed for
    * implicit cast > 0: cost associated with implicit cast. ==0: parms are
@@ -789,7 +791,13 @@ public class TypeCastRules {
     if (call.args.size() != holder.getParamCount()) {
       return -1;
     }
-      
+
+    // Indicates whether we used secondary cast rules
+    boolean secondaryCast = false;
+
+    // number of arguments that could implicitly casts using precedence map or didn't require casting at all
+    int nCasts = 0;
+
     for (int i = 0; i < holder.getParamCount(); i++) {
       MajorType argType = call.args.get(i).getMajorType();
       MajorType parmType = holder.getParmMajorType(i);
@@ -816,9 +824,18 @@ public class TypeCastRules {
       }
 
       if (parmVal - argVal < 0) {
-        return -1;
+
+        /* Precedence rules does not allow to implicitly cast, however check
+         * if the seconday rules allow us to cast
+         */
+        Set<MinorType> rules;
+        if ((rules = (ResolverTypePrecedence.secondaryImplicitCastRules.get(parmType.getMinorType()))) != null &&
+            rules.contains(argType.getMinorType()) != false) {
+          secondaryCast = true;
+        } else {
+          return -1;
+        }
       }
-      
       // Check null vs non-null, using same logic as that in Types.softEqual()
       // Only when the function uses NULL_IF_NULL, nullable and non-nullable are inter-changable.
       // Otherwise, the function implementation is not a match. 
@@ -839,12 +856,30 @@ public class TypeCastRules {
             return -1;
           }
           else if (parmType.getMode() == DataMode.OPTIONAL && argType.getMode() == DataMode.REQUIRED) {
-            cost++;
+            cost+= DATAMODE_CAST_COST;
           }
         }
       }
 
-      cost += (parmVal - argVal); 
+      int castCost;
+
+      if ((castCost = (parmVal - argVal)) >= 0) {
+        nCasts++;
+        cost += castCost;
+      }
+    }
+
+    if (secondaryCast) {
+      // We have a secondary cast for one or more of the arguments, determine the cost associated
+      int secondaryCastCost =  Integer.MAX_VALUE - 1;
+
+      // Subtract maximum possible implicit costs from the secondary cast cost
+      secondaryCastCost -= (nCasts * (ResolverTypePrecedence.MAX_IMPLICIT_CAST_COST + DATAMODE_CAST_COST));
+
+      // Add cost of implicitly casting the rest of the arguments that didn't use secondary casting
+      secondaryCastCost += cost;
+
+      return secondaryCastCost;
     }
 
     return cost;

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/cd4f281e/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestReverseImplicitCast.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestReverseImplicitCast.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestReverseImplicitCast.java
new file mode 100644
index 0000000..a0b77a5
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestReverseImplicitCast.java
@@ -0,0 +1,78 @@
+/**
+ * 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.drill.exec.physical.impl;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+import mockit.Injectable;
+import org.apache.drill.common.util.FileUtils;
+import org.apache.drill.exec.client.DrillClient;
+import org.apache.drill.exec.pop.PopUnitTestBase;
+import org.apache.drill.exec.proto.UserProtos;
+import org.apache.drill.exec.record.RecordBatchLoader;
+import org.apache.drill.exec.record.VectorWrapper;
+import org.apache.drill.exec.rpc.user.QueryResultBatch;
+import org.apache.drill.exec.rpc.user.UserServer;
+import org.apache.drill.exec.server.Drillbit;
+import org.apache.drill.exec.server.DrillbitContext;
+import org.apache.drill.exec.server.RemoteServiceSet;
+import org.apache.drill.exec.vector.ValueVector;
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestReverseImplicitCast extends PopUnitTestBase {
+
+  @Test
+  public void twoWayCast(@Injectable final DrillbitContext bitContext,
+                         @Injectable UserServer.UserClientConnection connection) throws Throwable {
+
+    // Function checks for casting from Float, Double to Decimal data types
+    try (RemoteServiceSet serviceSet = RemoteServiceSet.getLocalServiceSet();
+         Drillbit bit = new Drillbit(CONFIG, serviceSet);
+         DrillClient client = new DrillClient(CONFIG, serviceSet.getCoordinator())) {
+
+      // run query.
+      bit.run();
+      client.connect();
+      List<QueryResultBatch> results = client.runQuery(UserProtos.QueryType.PHYSICAL,
+          Files.toString(FileUtils.getResourceAsFile("/functions/cast/two_way_implicit_cast.json"), Charsets.UTF_8));
+
+      RecordBatchLoader batchLoader = new RecordBatchLoader(bit.getContext().getAllocator());
+
+      QueryResultBatch batch = results.get(0);
+      assertTrue(batchLoader.load(batch.getHeader().getDef(), batch.getData()));
+
+      Iterator<VectorWrapper<?>> itr = batchLoader.iterator();
+
+      ValueVector.Accessor intAccessor1 = itr.next().getValueVector().getAccessor();
+      ValueVector.Accessor varcharAccessor1 = itr.next().getValueVector().getAccessor();
+
+      for (int i = 0; i < intAccessor1.getValueCount(); i++) {
+        System.out.println(intAccessor1.getObject(i));
+        assertEquals(intAccessor1.getObject(i), 10);
+        System.out.println(varcharAccessor1.getObject(i));
+        assertEquals(varcharAccessor1.getObject(i), "101");
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/cd4f281e/exec/java-exec/src/test/resources/functions/cast/two_way_implicit_cast.json
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/functions/cast/two_way_implicit_cast.json b/exec/java-exec/src/test/resources/functions/cast/two_way_implicit_cast.json
new file mode 100644
index 0000000..31cf541
--- /dev/null
+++ b/exec/java-exec/src/test/resources/functions/cast/two_way_implicit_cast.json
@@ -0,0 +1,36 @@
+{
+    head:{
+        type:"APACHE_DRILL_PHYSICAL",
+        version:"1",
+        generator:{
+            type:"manual"
+        }
+    },
+    graph:[
+        {
+            @id:1,
+            pop:"mock-scan",
+            url: "http://apache.org",
+            entries:[
+            	{records: 1, types: [
+            	  {name: "col1", type: "FLOAT4", mode: "REQUIRED"},
+            	  {name: "col2", type: "FLOAT8", mode: "REQUIRED"}
+         	]}
+            ]
+        },
+        {
+            @id:2,
+            child: 1,
+            pop:"project",
+            exprs: [
+    		{ref: "str_to_int_cast", expr:"8 + '2'" },
+	    	{ref: "int_to_str_cast", expr:"substr(10123, 1, 3)" }
+            ]
+        },
+        {
+            @id: 3,
+            child: 2,
+            pop: "screen"
+        }
+    ]
+}


[2/5] git commit: DRILL-640: Fix memory leak in limit operator

Posted by ja...@apache.org.
DRILL-640: Fix memory leak in limit operator


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

Branch: refs/heads/master
Commit: f2ff2c9d2aad429f042da8250ca6e1ef1f160318
Parents: d870b6e
Author: Mehant Baid <me...@gmail.com>
Authored: Mon May 5 14:48:18 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Wed May 7 18:43:13 2014 -0700

----------------------------------------------------------------------
 .../physical/impl/limit/LimitRecordBatch.java   | 12 +++
 .../impl/limit/TestLimitWithExchanges.java      | 29 +++++++
 .../test/resources/limit/limit_exchanges.json   | 87 ++++++++++++++++++++
 3 files changed, 128 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/f2ff2c9d/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/limit/LimitRecordBatch.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/limit/LimitRecordBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/limit/LimitRecordBatch.java
index 3f2ec27..ed56e79 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/limit/LimitRecordBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/limit/LimitRecordBatch.java
@@ -81,6 +81,18 @@ public class LimitRecordBatch extends AbstractSingleRecordBatch<Limit> {
   public IterOutcome next() {
     if(!noEndLimit && recordsLeft <= 0) {
       // don't kill incoming batches or call cleanup yet, as this could close allocators before the buffers have been cleared
+      // Drain the incoming record batch and clear the memory
+      IterOutcome upStream = incoming.next();
+
+      while (upStream == IterOutcome.OK || upStream == IterOutcome.OK_NEW_SCHEMA) {
+
+        // Clear the memory for the incoming batch
+        for (VectorWrapper<?> wrapper : incoming) {
+          wrapper.getValueVector().clear();
+        }
+        upStream = incoming.next();
+      }
+
       return IterOutcome.NONE;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/f2ff2c9d/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/limit/TestLimitWithExchanges.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/limit/TestLimitWithExchanges.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/limit/TestLimitWithExchanges.java
new file mode 100644
index 0000000..0e4d734
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/limit/TestLimitWithExchanges.java
@@ -0,0 +1,29 @@
+/**
+ * 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.drill.exec.physical.impl.limit;
+
+import org.apache.drill.BaseTestQuery;
+import org.junit.Test;
+
+public class TestLimitWithExchanges extends BaseTestQuery {
+
+  @Test
+  public void testLimitWithExchanges() throws Exception{
+    testPhysicalFromFile("limit/limit_exchanges.json");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/f2ff2c9d/exec/java-exec/src/test/resources/limit/limit_exchanges.json
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/limit/limit_exchanges.json b/exec/java-exec/src/test/resources/limit/limit_exchanges.json
new file mode 100644
index 0000000..5ad56be
--- /dev/null
+++ b/exec/java-exec/src/test/resources/limit/limit_exchanges.json
@@ -0,0 +1,87 @@
+{
+  "head" : {
+    "version" : 1,
+    "generator" : {
+      "type" : "DefaultSqlHandler",
+      "info" : ""
+    },
+    "type" : "APACHE_DRILL_PHYSICAL",
+    "resultMode" : "EXEC"
+  },
+  "graph" : [ {
+    "pop" : "parquet-scan",
+    "@id" : 1,
+    "entries" : [ {
+      "path" : "/tpch/nation.parquet"
+    } ],
+    "storage" : {
+      "type" : "file",
+      "connection" : "classpath:///",
+      "workspaces" : null,
+      "formats" : {
+        "psv" : {
+          "type" : "text",
+          "extensions" : [ "tbl" ],
+          "delimiter" : "|"
+        },
+        "csv" : {
+          "type" : "text",
+          "extensions" : [ "csv" ],
+          "delimiter" : ","
+        },
+        "tsv" : {
+          "type" : "text",
+          "extensions" : [ "tsv" ],
+          "delimiter" : "\t"
+        },
+        "parquet" : {
+          "type" : "parquet"
+        },
+        "json" : {
+          "type" : "json"
+        }
+      }
+    },
+    "format" : {
+      "type" : "parquet"
+    },
+    "selectionRoot" : "/Users/mbaid/sources/drill/tpch-work/sample-data/nationsMF"
+  }, {
+    "pop" : "project",
+    "@id" : 2,
+    "exprs" : [ {
+      "ref" : "`N_NATIONKEY`",
+      "expr" : "`N_NATIONKEY`"
+    } ],
+    "child" : 1
+  }, {
+    "pop" : "hash-to-random-exchange",
+    "@id" : 3,
+    "child" : 2,
+    "expr" : "hash(`N_NATIONKEY`) "
+  }, {
+    "pop" : "union-exchange",
+    "@id" : 4,
+    "child" : 3
+  }, 
+{
+    "pop" : "project",
+    "@id" : 5,
+    "exprs" : [ { 
+      "ref" : "`N_NATIONKEY`",
+      "expr" : "`N_NATIONKEY`"
+    } ],
+    "child" : 4
+  },
+{
+    "pop" : "limit",
+    "@id" : 6,
+    "child" : 5,
+    "first" : 0,
+    "last" : 1
+  }, {
+    "pop" : "screen",
+    "@id" : 7,
+    "child" : 6
+  } ]
+}


[5/5] git commit: DRILL-438: Add support for Views (CREATE, DROP and select)

Posted by ja...@apache.org.
DRILL-438: Add support for Views (CREATE, DROP and select)


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

Branch: refs/heads/master
Commit: b7bf00cbbdc410861061e59b122a40083b527564
Parents: cd4f281
Author: vkorukanti <ve...@gmail.com>
Authored: Thu Apr 24 11:57:44 2014 -0700
Committer: Jacques Nadeau <ja...@apache.org>
Committed: Wed May 7 19:18:42 2014 -0700

----------------------------------------------------------------------
 .../exec/store/hbase/HBaseSchemaFactory.java    |  11 +-
 .../exec/store/hbase/HBaseStoragePlugin.java    |   5 +-
 exec/java-exec/src/main/codegen/data/Parser.tdd |   7 +-
 .../src/main/codegen/includes/parserImpls.ftl   |  52 ++++
 .../apache/drill/exec/ops/FragmentContext.java  |  12 +-
 .../org/apache/drill/exec/ops/QueryContext.java |   2 +-
 .../drill/exec/planner/logical/DrillOptiq.java  |   1 +
 .../exec/planner/logical/DrillViewTable.java    |  66 +++++
 .../drill/exec/planner/sql/DrillSqlWorker.java  |  17 +-
 .../exec/planner/sql/handlers/ViewHandler.java  | 146 +++++++++++
 .../exec/planner/sql/parser/DrillSqlCall.java   |  39 +++
 .../exec/planner/sql/parser/SqlCreateView.java  | 100 ++++++++
 .../planner/sql/parser/SqlDescribeTable.java    |  11 +-
 .../exec/planner/sql/parser/SqlDropView.java    |  65 +++++
 .../exec/planner/sql/parser/SqlShowSchemas.java |  10 +-
 .../exec/planner/sql/parser/SqlShowTables.java  |  11 +-
 .../exec/planner/sql/parser/SqlUseSchema.java   |  11 +-
 .../types/DrillFixedRelDataTypeImpl.java        | 104 ++++++++
 .../apache/drill/exec/rpc/user/UserSession.java |   5 +
 .../apache/drill/exec/rpc/user/ViewStore.java   |  93 +++++++
 .../apache/drill/exec/store/AbstractSchema.java |  17 +-
 .../apache/drill/exec/store/SchemaFactory.java  |   3 +-
 .../drill/exec/store/StoragePluginRegistry.java |   5 +-
 .../drill/exec/store/dfs/FileSystemPlugin.java  |  10 +-
 .../exec/store/dfs/FileSystemSchemaFactory.java |  19 +-
 .../exec/store/dfs/WorkspaceSchemaFactory.java  |  35 ++-
 .../exec/store/hive/HiveStoragePlugin.java      |   6 +-
 .../store/hive/schema/HiveDatabaseSchema.java   |   5 +-
 .../store/hive/schema/HiveSchemaFactory.java    |   8 +-
 .../store/ischema/InfoSchemaStoragePlugin.java  |   9 +-
 .../exec/store/mock/MockStorageEngine.java      |   3 +-
 .../drill/exec/store/sys/SystemTablePlugin.java |   7 +-
 .../java/org/apache/drill/PlanningBase.java     |   2 +-
 .../org/apache/drill/TestTpchSingleMode.java    |   2 +-
 .../drill/exec/store/TestOrphanSchema.java      |   3 +-
 .../drill/exec/store/ischema/OrphanSchema.java  |   3 +-
 .../src/test/resources/queries/tpch/15.sql      |   2 +
 .../apache/drill/jdbc/test/TestJdbcQuery.java   | 251 ++++++++++++++++++-
 38 files changed, 1082 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseSchemaFactory.java
----------------------------------------------------------------------
diff --git a/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseSchemaFactory.java b/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseSchemaFactory.java
index 7f67f83..c4ac08c 100644
--- a/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseSchemaFactory.java
+++ b/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseSchemaFactory.java
@@ -19,14 +19,17 @@ package org.apache.drill.exec.store.hbase;
 
 import java.io.IOException;
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import net.hydromatic.optiq.Schema;
 import net.hydromatic.optiq.SchemaPlus;
 
+import net.hydromatic.optiq.Table;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.planner.logical.DynamicDrillTable;
-import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.SchemaFactory;
 import org.apache.hadoop.hbase.HTableDescriptor;
@@ -46,7 +49,7 @@ public class HBaseSchemaFactory implements SchemaFactory {
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
     HBaseSchema schema = new HBaseSchema(schemaName);
     SchemaPlus hPlus = parent.add(schemaName, schema);
     schema.setHolder(hPlus);
@@ -55,7 +58,7 @@ public class HBaseSchemaFactory implements SchemaFactory {
   class HBaseSchema extends AbstractSchema {
 
     public HBaseSchema(String name) {
-      super(name);
+      super(ImmutableList.<String>of(), name);
     }
 
     public void setHolder(SchemaPlus plusOfThis) {
@@ -72,7 +75,7 @@ public class HBaseSchemaFactory implements SchemaFactory {
     }
 
     @Override
-    public DrillTable getTable(String name) {
+    public Table getTable(String name) {
       Object selection = new HBaseScanSpec(name);
       return new DynamicDrillTable(plugin, schemaName, selection, plugin.getConfig());
     }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseStoragePlugin.java
----------------------------------------------------------------------
diff --git a/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseStoragePlugin.java b/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseStoragePlugin.java
index c1fb6af..ea1550d 100644
--- a/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseStoragePlugin.java
+++ b/contrib/storage-hbase/src/main/java/org/apache/drill/exec/store/hbase/HBaseStoragePlugin.java
@@ -27,6 +27,7 @@ import org.apache.drill.common.JSONOptions;
 import org.apache.drill.exec.rpc.user.DrillUser;
 import org.apache.drill.common.expression.SchemaPath;
 import org.apache.drill.common.logical.StoragePluginConfig;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.AbstractStoragePlugin;
 import org.apache.drill.exec.store.StoragePluginOptimizerRule;
@@ -67,8 +68,8 @@ public class HBaseStoragePlugin extends AbstractStoragePlugin {
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
-    schemaFactory.registerSchemas(user, parent);
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
+    schemaFactory.registerSchemas(session, parent);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/codegen/data/Parser.tdd
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/data/Parser.tdd b/exec/java-exec/src/main/codegen/data/Parser.tdd
index 4f47795..176ee79 100644
--- a/exec/java-exec/src/main/codegen/data/Parser.tdd
+++ b/exec/java-exec/src/main/codegen/data/Parser.tdd
@@ -29,9 +29,10 @@
   # List of keywords.
   keywords: [
     "DATABASES",
+    "REPLACE",
     "SCHEMAS",
     "SHOW",
-    "TABLES"
+    "TABLES",
     "USE"
   ]
 
@@ -40,7 +41,9 @@
     "SqlShowTables()",
     "SqlShowSchemas()",
     "SqlDescribeTable()",
-    "SqlUseSchema()"
+    "SqlUseSchema()",
+    "SqlCreateOrReplaceView()",
+    "SqlDropView()"
   ]
 
   # List of methods for parsing custom literals.

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/codegen/includes/parserImpls.ftl
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl
index cd5ee72..5b6e2b5 100644
--- a/exec/java-exec/src/main/codegen/includes/parserImpls.ftl
+++ b/exec/java-exec/src/main/codegen/includes/parserImpls.ftl
@@ -113,3 +113,55 @@ SqlNode SqlUseSchema():
         return new SqlUseSchema(pos, schema);
     }
 }
+
+/**
+ * Parses a create view or replace existing view statement.
+ *   CREATE [OR REPLACE] VIEW view_name AS select_statement
+ */
+SqlNode SqlCreateOrReplaceView() :
+{
+    SqlParserPos pos;
+    boolean replaceView = false;
+    SqlIdentifier viewName;
+    SqlNode query;
+    SqlNodeList fieldList = null;
+}
+{
+    <CREATE> { pos = getPos(); }
+    [ <OR> <REPLACE> { replaceView = true; } ]
+    <VIEW>
+    viewName = CompoundIdentifier()
+    [
+        <LPAREN>
+        fieldList = SimpleIdentifierCommaList()
+        <RPAREN>
+        {
+            for(SqlNode node : fieldList)
+            {
+                if (((SqlIdentifier)node).isStar())
+                    throw new ParseException("View's field list has a '*', which is invalid.");
+            }
+        }
+    ]
+    <AS>
+    query = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
+    {
+        return new SqlCreateView(pos, viewName, fieldList, query, replaceView);
+    }
+}
+
+/**
+ * Parses a drop view statement.
+ * DROP VIEW view_name;
+ */
+SqlNode SqlDropView() :
+{
+    SqlParserPos pos;
+}
+{
+    <DROP> { pos = getPos(); }
+    <VIEW>
+    {
+        return new SqlDropView(pos, CompoundIdentifier());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/ops/FragmentContext.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/FragmentContext.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/FragmentContext.java
index 2a6ab0e..38d76e0 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/FragmentContext.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/FragmentContext.java
@@ -123,9 +123,15 @@ public class FragmentContext implements Closeable {
   }
 
   public SchemaPlus getRootSchema(){
-    SchemaPlus root = Frameworks.createRootSchema();
-    context.getStorage().getSchemaFactory().registerSchemas(null, root);
-    return root;
+    if (connection == null) {
+      fail(new UnsupportedOperationException("Schema tree can only be created in root fragment. " +
+          "This is a non-root fragment."));
+      return null;
+    } else {
+      SchemaPlus root = Frameworks.createRootSchema();
+      context.getStorage().getSchemaFactory().registerSchemas(connection.getSession(), root);
+      return root;
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java
index f6ce04f..e3d2f54 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ops/QueryContext.java
@@ -79,7 +79,7 @@ public class QueryContext{
 
   public SchemaPlus getRootSchema(){
     SchemaPlus rootSchema = Frameworks.createRootSchema();
-    drillbitContext.getSchemaFactory().registerSchemas(session.getUser(), rootSchema);
+    drillbitContext.getSchemaFactory().registerSchemas(session, rootSchema);
     return rootSchema;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
index 2e61970..aee6da4 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
@@ -249,6 +249,7 @@ public class DrillOptiq {
 
         case "INTERVAL_YEAR_MONTH": castType = Types.required(MinorType.INTERVALYEAR); break;
         case "INTERVAL_DAY_TIME": castType = Types.required(MinorType.INTERVALDAY); break;
+        case "ANY": return arg; // Type will be same as argument.
         default: castType = Types.required(MinorType.valueOf(call.getType().getSqlTypeName().getName()));
       }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillViewTable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillViewTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillViewTable.java
new file mode 100644
index 0000000..6415869
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillViewTable.java
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.planner.logical;
+
+import com.google.common.collect.ImmutableList;
+import net.hydromatic.optiq.impl.ViewTable;
+import org.apache.drill.exec.planner.types.DrillFixedRelDataTypeImpl;
+import org.apache.drill.exec.planner.types.RelDataTypeDrillImpl;
+import org.apache.drill.exec.planner.types.RelDataTypeHolder;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.relopt.RelOptTable;
+import org.eigenbase.relopt.RelOptTable.ToRelContext;
+import org.eigenbase.relopt.RelOptUtil;
+import org.eigenbase.reltype.*;
+
+import java.util.List;
+
+public class DrillViewTable extends ViewTable {
+  private RelDataType rowType;
+  private boolean starSchema = false; // is the view schema "*"?
+  private RelDataTypeHolder holder = new RelDataTypeHolder();
+
+  public DrillViewTable(String viewSql, List<String> schemaPath, RelDataType rowType) {
+    super(Object.class, null, viewSql, schemaPath);
+
+    this.rowType = rowType;
+    if (rowType.getFieldCount() == 1 && rowType.getFieldNames().get(0).equals("*"))
+      starSchema = true;
+  }
+
+  @Override
+  public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+    // if the view's schema is a "*" schema, create dynamic row type. Otherwise create fixed row type.
+    if (starSchema)
+      return new RelDataTypeDrillImpl(holder, typeFactory);
+
+    return rowType;
+  }
+
+  @Override
+  public RelNode toRel(ToRelContext context, RelOptTable relOptTable) {
+    RelDataType rowType = relOptTable.getRowType();
+    RelNode rel = context.expandView(rowType, getViewSql(), getSchemaPath());
+
+    // if the View's field list is not "*", try to create a cast.
+    if (!starSchema)
+      return RelOptUtil.createCastRel(rel, rowType, true);
+
+    return rel;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlWorker.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlWorker.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlWorker.java
index 048d116..6e9a00f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlWorker.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/DrillSqlWorker.java
@@ -34,17 +34,10 @@ import org.apache.drill.exec.physical.PhysicalPlan;
 import org.apache.drill.exec.planner.logical.DrillRuleSets;
 import org.apache.drill.exec.planner.physical.DrillDistributionTraitDef;
 import org.apache.drill.exec.planner.sql.handlers.DefaultSqlHandler;
-import org.apache.drill.exec.planner.sql.handlers.DescribeTableHandler;
 import org.apache.drill.exec.planner.sql.handlers.ExplainHandler;
 import org.apache.drill.exec.planner.sql.handlers.SetOptionHandler;
-import org.apache.drill.exec.planner.sql.handlers.ShowSchemasHandler;
-import org.apache.drill.exec.planner.sql.handlers.ShowTablesHandler;
 import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
-import org.apache.drill.exec.planner.sql.handlers.UseSchemaHandler;
-import org.apache.drill.exec.planner.sql.parser.SqlDescribeTable;
-import org.apache.drill.exec.planner.sql.parser.SqlShowSchemas;
-import org.apache.drill.exec.planner.sql.parser.SqlShowTables;
-import org.apache.drill.exec.planner.sql.parser.SqlUseSchema;
+import org.apache.drill.exec.planner.sql.parser.DrillSqlCall;
 import org.apache.drill.exec.planner.sql.parser.impl.DrillParserImpl;
 import org.apache.drill.exec.store.StoragePluginRegistry;
 import org.eigenbase.rel.RelCollationTraitDef;
@@ -113,10 +106,10 @@ public class DrillSqlWorker {
       handler = new SetOptionHandler(context);
       break;
     case OTHER:
-      if (sqlNode instanceof SqlShowTables){ handler = new ShowTablesHandler(planner, context); break; }
-      else if (sqlNode instanceof SqlShowSchemas){ handler = new ShowSchemasHandler(planner, context); break; }
-      else if (sqlNode instanceof SqlDescribeTable){ handler = new DescribeTableHandler(planner, context); break; }
-      else if (sqlNode instanceof SqlUseSchema){ handler = new UseSchemaHandler(context); break; }
+      if (sqlNode instanceof DrillSqlCall) {
+        handler = ((DrillSqlCall)sqlNode).getSqlHandler(planner, context);
+        break;
+      }
       // fallthrough
     default:
       handler = new DefaultSqlHandler(planner, context);

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java
new file mode 100644
index 0000000..a78c54f
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/ViewHandler.java
@@ -0,0 +1,146 @@
+/**
+ * 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.drill.exec.planner.sql.handlers;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.google.common.base.Joiner;
+import net.hydromatic.optiq.SchemaPlus;
+import net.hydromatic.optiq.impl.ViewTable;
+import net.hydromatic.optiq.tools.Planner;
+import net.hydromatic.optiq.tools.RelConversionException;
+import net.hydromatic.optiq.tools.ValidationException;
+
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.physical.PhysicalPlan;
+import org.apache.drill.exec.planner.logical.DrillViewTable;
+import org.apache.drill.exec.planner.sql.DirectPlan;
+import org.apache.drill.exec.planner.sql.parser.SqlCreateView;
+import org.apache.drill.exec.planner.sql.parser.SqlDropView;
+import org.apache.drill.exec.planner.types.DrillFixedRelDataTypeImpl;
+import org.apache.drill.exec.store.AbstractSchema;
+import org.eigenbase.rel.RelNode;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.sql.SqlNode;
+
+public abstract class ViewHandler implements SqlHandler{
+  static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ViewHandler.class);
+
+  protected Planner planner;
+  protected QueryContext context;
+
+  public ViewHandler(Planner planner, QueryContext context) {
+    this.planner = planner;
+    this.context = context;
+  }
+
+  /** From a given SchemaPlus return a mutable Drill schema object AbstractSchema if exists. Otherwise throw errors. */
+  protected static AbstractSchema getDrillSchema(SchemaPlus schemaPlus) throws Exception{
+    AbstractSchema drillSchema;
+    try {
+      drillSchema = schemaPlus.unwrap(AbstractSchema.class);
+    } catch(ClassCastException e) {
+      throw new Exception(String.format("Can't create view in schema '%s'", schemaPlus.getName()), e);
+    }
+
+    if (!drillSchema.isMutable())
+      throw new Exception(String.format("Views are not allowed in schema '%s'", schemaPlus.getName()));
+
+    return drillSchema;
+  }
+
+  /** Handler for Create View DDL command */
+  public static class CreateView extends ViewHandler {
+
+    public CreateView(Planner planner, QueryContext context) {
+      super(planner, context);
+    }
+
+    @Override
+    public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConversionException, IOException {
+      SqlCreateView createView = DefaultSqlHandler.unwrap(sqlNode, SqlCreateView.class);
+
+      try {
+        AbstractSchema drillSchema = getDrillSchema(context.getNewDefaultSchema());
+
+        String viewSql = createView.getQuery().toString();
+
+        SqlNode validatedQuery = planner.validate(createView.getQuery());
+        RelNode validatedRelNode = planner.convert(validatedQuery);
+
+        // If view's field list is specified then its size should match view's query field list size.
+        RelDataType queryRowType = validatedRelNode.getRowType();
+
+        List<String> viewFieldNames = createView.getFieldNames();
+        if (viewFieldNames.size() > 0) {
+          // number of fields match.
+          if (viewFieldNames.size() != queryRowType.getFieldCount())
+            throw new Exception("View's field list and View's query field list have different counts.");
+
+          // make sure View's query field list has no "*"
+          for(String field : queryRowType.getFieldNames()) {
+            if (field.equals("*"))
+              throw new Exception("View's query field list has a '*', which is invalid when View's field list is specified.");
+          }
+
+          queryRowType = new DrillFixedRelDataTypeImpl(planner.getTypeFactory(), viewFieldNames);
+        }
+
+        ViewTable viewTable = new DrillViewTable(viewSql, drillSchema.getSchemaPath(), queryRowType);
+
+        String schemaPath = Joiner.on(".").join(drillSchema.getSchemaPath());
+
+        boolean replaced = context.getSession().getViewStore().addView(
+            schemaPath, createView.getViewName(), viewTable, createView.getReplace());
+
+        String summary = String.format("View '%s' %s successfully in '%s' schema",
+            createView.getViewName(), replaced ? "replaced" : "created", schemaPath);
+
+        return DirectPlan.createDirectPlan(context, true, summary);
+      } catch(Exception e) {
+        logger.error("Failed to create view '{}'", createView.getViewName(), e);
+        return DirectPlan.createDirectPlan(context, false, String.format("Error: %s", e.getMessage()));
+      }
+    }
+  }
+
+  /** Handler for Drop View DDL command. */
+  public static class DropView extends ViewHandler {
+    public DropView(QueryContext context) {
+      super(null, context);
+    }
+
+    @Override
+    public PhysicalPlan getPlan(SqlNode sqlNode) throws ValidationException, RelConversionException, IOException {
+      SqlDropView createView = DefaultSqlHandler.unwrap(sqlNode, SqlDropView.class);
+
+      try {
+        AbstractSchema drillSchema = getDrillSchema(context.getNewDefaultSchema());
+        String schemaPath = Joiner.on(".").join(drillSchema.getSchemaPath());
+        context.getSession().getViewStore().dropView(schemaPath, createView.getViewName());
+
+        return DirectPlan.createDirectPlan(context, true,
+            String.format("View '%s' deleted successfully from '%s' schema", createView.getViewName(), schemaPath));
+      } catch(Exception e) {
+        logger.debug("Failed to delete view {}", createView.getViewName(), e);
+        return DirectPlan.createDirectPlan(context, false, String.format("Error: %s", e.getMessage()));
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/DrillSqlCall.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/DrillSqlCall.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/DrillSqlCall.java
new file mode 100644
index 0000000..32f57b4
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/DrillSqlCall.java
@@ -0,0 +1,39 @@
+/**
+ * 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.drill.exec.planner.sql.parser;
+
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.DefaultSqlHandler;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
+import org.eigenbase.sql.SqlCall;
+import org.eigenbase.sql.parser.SqlParserPos;
+
+/**
+ * SqlCall interface with addition of method to get the handler.
+ */
+public abstract class DrillSqlCall extends SqlCall {
+
+  public DrillSqlCall(SqlParserPos pos) {
+    super(pos);
+  }
+
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new DefaultSqlHandler(planner, context);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java
new file mode 100644
index 0000000..b124e1d
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlCreateView.java
@@ -0,0 +1,100 @@
+/**
+ * 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.drill.exec.planner.sql.parser;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.ImmutableList;
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
+import org.apache.drill.exec.planner.sql.handlers.ViewHandler;
+import org.eigenbase.sql.*;
+import org.eigenbase.sql.parser.SqlParserPos;
+
+import java.util.List;
+
+public class SqlCreateView extends DrillSqlCall {
+  public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("CREATE_VIEW", SqlKind.OTHER);
+
+  private SqlIdentifier viewName;
+  private SqlNodeList fieldList;
+  private SqlNode query;
+  private boolean replaceView;
+
+  public SqlCreateView(SqlParserPos pos, SqlIdentifier viewName, SqlNodeList fieldList,
+                       SqlNode query, boolean replaceView) {
+    super(pos);
+    this.viewName = viewName;
+    this.query = query;
+    this.replaceView = replaceView;
+    this.fieldList = fieldList;
+  }
+
+  @Override
+  public SqlOperator getOperator() {
+    return OPERATOR;
+  }
+
+  @Override
+  public List<SqlNode> getOperandList() {
+    return ImmutableList.of(viewName, fieldList, query,
+        SqlLiteral.createBoolean(replaceView, SqlParserPos.ZERO));
+  }
+
+  @Override
+  public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
+    writer.keyword("CREATE");
+    if (replaceView) {
+      writer.keyword("OR");
+      writer.keyword("REPLACE");
+    }
+    writer.keyword("VIEW");
+    viewName.unparse(writer, leftPrec, rightPrec);
+    if (fieldList != null && fieldList.size() > 0) {
+      writer.keyword("(");
+      fieldList.get(0).unparse(writer, leftPrec, rightPrec);
+      for(int i=1; i<fieldList.size(); i++) {
+        writer.keyword(",");
+        fieldList.get(i).unparse(writer, leftPrec, rightPrec);
+      }
+      writer.keyword(")");
+    }
+    writer.keyword("AS");
+    query.unparse(writer, leftPrec, rightPrec);
+  }
+
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new ViewHandler.CreateView(planner, context);
+  }
+
+  public String getViewName() { return viewName.getSimple(); }
+
+  public List<String> getFieldNames() {
+    if (fieldList == null) return ImmutableList.of();
+
+    List<String> fieldNames = Lists.newArrayList();
+    for(SqlNode node : fieldList.getList()) {
+      fieldNames.add(node.toString());
+    }
+    return fieldNames;
+  }
+
+  public SqlNode getQuery() { return query; }
+  public boolean getReplace() { return replaceView; }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDescribeTable.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDescribeTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDescribeTable.java
index 24c2d03..0a666de 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDescribeTable.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDescribeTable.java
@@ -18,6 +18,10 @@
 package org.apache.drill.exec.planner.sql.parser;
 
 import com.google.common.collect.Lists;
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.DescribeTableHandler;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
 import org.eigenbase.sql.*;
 import org.eigenbase.sql.parser.SqlParserPos;
 
@@ -27,7 +31,7 @@ import java.util.List;
  * Sql parser tree node to represent statement:
  * { DESCRIBE | DESC } tblname [col_name | wildcard ]
  */
-public class SqlDescribeTable extends SqlCall {
+public class SqlDescribeTable extends DrillSqlCall {
 
   private final SqlIdentifier table;
   private final SqlIdentifier column;
@@ -66,6 +70,11 @@ public class SqlDescribeTable extends SqlCall {
     if (columnQualifier != null) columnQualifier.unparse(writer, leftPrec, rightPrec);
   }
 
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new DescribeTableHandler(planner, context);
+  }
+
   public SqlIdentifier getTable() { return table; }
   public SqlIdentifier getColumn() { return column; }
   public SqlNode getColumnQualifier() { return columnQualifier; }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDropView.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDropView.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDropView.java
new file mode 100644
index 0000000..8ba7edd
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlDropView.java
@@ -0,0 +1,65 @@
+/**
+ * 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.drill.exec.planner.sql.parser;
+
+import com.google.common.collect.ImmutableList;
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
+import org.apache.drill.exec.planner.sql.handlers.ViewHandler.DropView;
+import org.eigenbase.sql.*;
+import org.eigenbase.sql.parser.SqlParserPos;
+
+import java.util.List;
+
+public class SqlDropView extends DrillSqlCall {
+  public static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("DROP_VIEW", SqlKind.OTHER);
+
+  private SqlIdentifier viewName;
+
+  public SqlDropView(SqlParserPos pos, SqlIdentifier viewName) {
+    super(pos);
+    this.viewName = viewName;
+  }
+
+  @Override
+  public SqlOperator getOperator() {
+    return OPERATOR;
+  }
+
+  @Override
+  public List<SqlNode> getOperandList() {
+    return ImmutableList.of((SqlNode)viewName);
+  }
+
+  @Override
+  public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
+    writer.keyword("DROP");
+    writer.keyword("VIEW");
+    viewName.unparse(writer, leftPrec, rightPrec);
+  }
+
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new DropView(context);
+  }
+
+  public String getViewName() {
+    return viewName.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowSchemas.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowSchemas.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowSchemas.java
index 526ae04..aa212a7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowSchemas.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowSchemas.java
@@ -20,7 +20,8 @@ package org.apache.drill.exec.planner.sql.parser;
 import com.google.common.collect.Lists;
 import net.hydromatic.optiq.tools.Planner;
 import org.apache.drill.exec.ops.QueryContext;
-import org.apache.drill.exec.planner.sql.handlers.DefaultSqlHandler;
+import org.apache.drill.exec.planner.sql.handlers.ShowSchemasHandler;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
 import org.eigenbase.sql.*;
 import org.eigenbase.sql.parser.SqlParserPos;
 
@@ -30,7 +31,7 @@ import java.util.List;
  * Sql parse tree node to represent statement:
  * SHOW {DATABASES | SCHEMAS} [LIKE 'pattern' | WHERE expr]
  */
-public class SqlShowSchemas extends SqlCall {
+public class SqlShowSchemas extends DrillSqlCall {
 
   private final SqlNode likePattern;
   private final SqlNode whereClause;
@@ -68,6 +69,11 @@ public class SqlShowSchemas extends SqlCall {
     if (whereClause != null) whereClause.unparse(writer, leftPrec, rightPrec);
   }
 
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new ShowSchemasHandler(planner, context);
+  }
+
   public SqlNode getLikePattern() { return likePattern; }
   public SqlNode getWhereClause() { return whereClause; }
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowTables.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowTables.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowTables.java
index aad5ca5..e3be378 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowTables.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlShowTables.java
@@ -18,6 +18,10 @@
 package org.apache.drill.exec.planner.sql.parser;
 
 import com.google.common.collect.Lists;
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.ShowTablesHandler;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
 import org.eigenbase.sql.*;
 import org.eigenbase.sql.parser.SqlParserPos;
 
@@ -27,7 +31,7 @@ import java.util.List;
  * Sql parse tree node to represent statement:
  * SHOW TABLES [{FROM | IN} db_name] [LIKE 'pattern' | WHERE expr]
  */
-public class SqlShowTables extends SqlCall {
+public class SqlShowTables extends DrillSqlCall {
 
   private final SqlIdentifier db;
   private final SqlNode likePattern;
@@ -69,6 +73,11 @@ public class SqlShowTables extends SqlCall {
     if (whereClause != null) whereClause.unparse(writer, leftPrec, rightPrec);
   }
 
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new ShowTablesHandler(planner, context);
+  }
+
   public SqlIdentifier getDb() { return db; }
   public SqlNode getLikePattern() { return likePattern; }
   public SqlNode getWhereClause() { return whereClause; }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlUseSchema.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlUseSchema.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlUseSchema.java
index a48963e..92d3aff 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlUseSchema.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/SqlUseSchema.java
@@ -18,6 +18,10 @@
 package org.apache.drill.exec.planner.sql.parser;
 
 import com.google.common.collect.ImmutableList;
+import net.hydromatic.optiq.tools.Planner;
+import org.apache.drill.exec.ops.QueryContext;
+import org.apache.drill.exec.planner.sql.handlers.SqlHandler;
+import org.apache.drill.exec.planner.sql.handlers.UseSchemaHandler;
 import org.eigenbase.sql.*;
 import org.eigenbase.sql.parser.SqlParserPos;
 
@@ -26,7 +30,7 @@ import java.util.List;
 /**
  * Sql parser tree node to represent <code>USE SCHEMA</code> statement.
  */
-public class SqlUseSchema extends SqlCall {
+public class SqlUseSchema extends DrillSqlCall {
 
   public static final SqlSpecialOperator OPERATOR =
       new SqlSpecialOperator("USE_SCHEMA", SqlKind.OTHER);
@@ -54,6 +58,11 @@ public class SqlUseSchema extends SqlCall {
     schema.unparse(writer, leftPrec, rightPrec);
   }
 
+  @Override
+  public SqlHandler getSqlHandler(Planner planner, QueryContext context) {
+    return new UseSchemaHandler(context);
+  }
+
   /**
    * Get the schema name. A schema identifier can contain more than one level of schema.
    * Ex: "dfs.home" identifier contains two levels "dfs" and "home".

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillFixedRelDataTypeImpl.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillFixedRelDataTypeImpl.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillFixedRelDataTypeImpl.java
new file mode 100644
index 0000000..f20a174
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillFixedRelDataTypeImpl.java
@@ -0,0 +1,104 @@
+/**
+ * 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.drill.exec.planner.types;
+
+import com.google.common.collect.Lists;
+import org.eigenbase.reltype.RelDataTypeFactory;
+import org.eigenbase.reltype.RelDataTypeField;
+import org.eigenbase.reltype.RelDataTypeFieldImpl;
+import org.eigenbase.reltype.RelDataTypeImpl;
+import org.eigenbase.reltype.RelDataTypePrecedenceList;
+import org.eigenbase.sql.type.SqlTypeExplicitPrecedenceList;
+import org.eigenbase.sql.type.SqlTypeName;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Implements RowType for fixed field list with ANY type.
+ */
+public class DrillFixedRelDataTypeImpl extends RelDataTypeImpl {
+  private List<RelDataTypeField> fields = Lists.newArrayList();
+  private final RelDataTypeFactory typeFactory;
+
+  public DrillFixedRelDataTypeImpl(RelDataTypeFactory typeFactory, List<String> columnNames) {
+    this.typeFactory = typeFactory;
+
+    // Add the initial list of columns.
+    for (String column : columnNames)
+      addField(column);
+    computeDigest();
+  }
+
+  private void addField(String columnName) {
+    RelDataTypeField newField = new RelDataTypeFieldImpl(
+        columnName, fields.size(), typeFactory.createSqlType(SqlTypeName.ANY));
+    fields.add(newField);
+  }
+
+  @Override
+  public List<RelDataTypeField> getFieldList() {
+    return fields;
+  }
+
+  @Override
+  public int getFieldCount() {
+    return fields.size();
+  }
+
+  @Override
+  public RelDataTypeField getField(String fieldName, boolean caseSensitive) {
+    // return the field with given name if available.
+    for (RelDataTypeField f : fields) {
+      if (fieldName.equalsIgnoreCase(f.getName())) {
+        return f;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<String> getFieldNames() {
+    List<String> fieldNames = Lists.newArrayList();
+    for(RelDataTypeField f : fields){
+      fieldNames.add(f.getName());
+    }
+
+    return fieldNames;
+  }
+
+  @Override
+  public SqlTypeName getSqlTypeName() {
+    return SqlTypeName.ANY;
+  }
+
+  @Override
+  public RelDataTypePrecedenceList getPrecedenceList() {
+    return new SqlTypeExplicitPrecedenceList((List<SqlTypeName>) (List) Collections.emptyList());
+  }
+
+  @Override
+  protected void generateTypeString(StringBuilder sb, boolean withDetail) {
+    sb.append("(DrillFixedRecordRow" + getFieldNames() + ")");
+  }
+
+  @Override
+  public boolean isStruct() {
+    return true;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java
index 86c4bad..1607179 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/UserSession.java
@@ -41,11 +41,14 @@ public class UserSession {
   private UserCredentials credentials;
   private Map<String, String> properties;
   private OptionManager options;
+  private ViewStore viewStore;
 
   public UserSession(OptionManager systemOptions, UserCredentials credentials, UserProperties properties) throws IOException{
     this.credentials = credentials;
     this.options = new SessionOptionManager(systemOptions);
     this.properties = Maps.newHashMap();
+    this.viewStore = new ViewStore();
+
     if (properties == null) return;
     for (int i=0; i<properties.getPropertiesCount(); i++) {
       Property prop = properties.getProperties(i);
@@ -61,6 +64,8 @@ public class UserSession {
     return user;
   }
 
+  public ViewStore getViewStore() { return viewStore; }
+
   /**
    * Update the schema path for the session.
    * @param fullPath The desired path to set to.

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/ViewStore.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/ViewStore.java b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/ViewStore.java
new file mode 100644
index 0000000..f5de489
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/rpc/user/ViewStore.java
@@ -0,0 +1,93 @@
+/**
+ * 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.drill.exec.rpc.user;
+
+import com.google.common.collect.*;
+import net.hydromatic.optiq.impl.ViewTable;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * ViewStore for holding and managing the views created in a user session.
+ *
+ * Note: Currently these views are for session only and doesn't persist across session.
+ */
+public class ViewStore {
+  // Map of views associated in a schema
+  private Map<String, Map<String, ViewTable>> viewMap = Maps.newHashMap();
+
+  /**
+   * Get all views belonging to the given schema.
+   * @param schemaPath
+   * @return Map of (viewName, ViewTable) entries.
+   */
+  public Map<String, ViewTable> getViews(String schemaPath) {
+    if (viewMap.containsKey(schemaPath))
+      return viewMap.get(schemaPath);
+
+    return Collections.emptyMap();
+  }
+
+  /**
+   * Add the given view to store.
+   *
+   * @param schemaPath
+   * @param viewName Name of the view.
+   * @param view {@link ViewTable} object.
+   * @param replace If a view with given name already exists, replace it.
+   * @return True if a view is replaced.
+   */
+  public boolean addView(String schemaPath, String viewName, ViewTable view, boolean replace) throws ViewAlreadyExistsException {
+    if (!viewMap.containsKey(schemaPath)) {
+      Map<String, ViewTable> viewNameMap = Maps.newHashMap();
+      viewMap.put(schemaPath, viewNameMap);
+    }
+
+    boolean replaced = false;
+    if (viewMap.get(schemaPath).get(viewName) != null) {
+      if (replace)
+        replaced = true;
+      else
+        throw new ViewAlreadyExistsException(schemaPath, viewName);
+    }
+    viewMap.get(schemaPath).put(viewName, view);
+
+    return replaced;
+  }
+
+  /** Delete the ViewTable with given parameters from store. */
+  public void dropView(String schemaPath, String viewName) throws NoSuchViewExistsException {
+    if (viewMap.containsKey(schemaPath) && viewMap.get(schemaPath).containsKey(viewName))
+      viewMap.get(schemaPath).remove(viewName);
+    else
+      throw new NoSuchViewExistsException(schemaPath, viewName);
+  }
+
+  public static class ViewAlreadyExistsException extends Exception {
+    public ViewAlreadyExistsException(String schemaPath, String viewName){
+      super(String.format("Schema '%s' already contains a view view name '%s'.", schemaPath, viewName));
+    }
+  }
+
+  public static class NoSuchViewExistsException extends Exception {
+    public NoSuchViewExistsException(String schemaPath, String viewName){
+      super(String.format("Schema '%s' has no view named '%s'", schemaPath, viewName));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/AbstractSchema.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/AbstractSchema.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/AbstractSchema.java
index 64087f5..5806ca7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/AbstractSchema.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/AbstractSchema.java
@@ -19,24 +19,31 @@ package org.apache.drill.exec.store;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 import net.hydromatic.linq4j.expressions.DefaultExpression;
 import net.hydromatic.linq4j.expressions.Expression;
 import net.hydromatic.optiq.Function;
 import net.hydromatic.optiq.Schema;
 import net.hydromatic.optiq.SchemaPlus;
 
+import net.hydromatic.optiq.Table;
 import org.apache.drill.exec.planner.logical.DrillTable;
 
 public abstract class AbstractSchema implements Schema{
   static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AbstractSchema.class);
 
+  protected final List<String> schemaPath;
   protected final String name;
   private static final Expression EXPRESSION = new DefaultExpression(Object.class);
 
-  public AbstractSchema(String name) {
-    super();
+  public AbstractSchema(List<String> parentSchemaPath, String name) {
+    schemaPath = Lists.newArrayList();
+    schemaPath.addAll(parentSchemaPath);
+    schemaPath.add(name);
     this.name = name;
   }
 
@@ -44,6 +51,10 @@ public abstract class AbstractSchema implements Schema{
     return name;
   }
 
+  public List<String> getSchemaPath() {
+    return schemaPath;
+  }
+
   @Override
   public Collection<Function> getFunctions(String name) {
     return Collections.emptyList();
@@ -70,7 +81,7 @@ public abstract class AbstractSchema implements Schema{
   }
 
   @Override
-  public DrillTable getTable(String name){
+  public Table getTable(String name){
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/SchemaFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/SchemaFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/SchemaFactory.java
index 60ccbe8..5acbe78 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/SchemaFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/SchemaFactory.java
@@ -20,9 +20,10 @@ package org.apache.drill.exec.store;
 import net.hydromatic.optiq.SchemaPlus;
 
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 
 public interface SchemaFactory {
   static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SchemaFactory.class);
 
-  public void registerSchemas(DrillUser user, SchemaPlus parent);
+  public void registerSchemas(UserSession session, SchemaPlus parent);
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/StoragePluginRegistry.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/StoragePluginRegistry.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/StoragePluginRegistry.java
index 948c74f..ad9a7db 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/StoragePluginRegistry.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/StoragePluginRegistry.java
@@ -44,6 +44,7 @@ import org.apache.drill.exec.exception.DrillbitStartupException;
 import org.apache.drill.exec.planner.logical.DrillRuleSets;
 import org.apache.drill.exec.planner.logical.StoragePlugins;
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.dfs.FileSystemPlugin;
 import org.apache.drill.exec.store.dfs.FormatPlugin;
@@ -223,9 +224,9 @@ public class StoragePluginRegistry implements Iterable<Map.Entry<String, Storage
   public class DrillSchemaFactory implements SchemaFactory{
 
     @Override
-    public void registerSchemas(DrillUser user, SchemaPlus parent) {
+    public void registerSchemas(UserSession session, SchemaPlus parent) {
       for(Map.Entry<String, StoragePlugin> e : plugins.entrySet()){
-        e.getValue().registerSchemas(user, parent);
+        e.getValue().registerSchemas(session, parent);
       }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemPlugin.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemPlugin.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemPlugin.java
index dd0cef4..6ade4ee 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemPlugin.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemPlugin.java
@@ -83,16 +83,16 @@ public class FileSystemPlugin extends AbstractStoragePlugin{
 
       List<WorkspaceSchemaFactory> factories = null;
       if(config.workspaces == null || config.workspaces.isEmpty()){
-        factories = Collections.singletonList(new WorkspaceSchemaFactory(this, "default", name, fs, "/", matchers));
+        factories = Collections.singletonList(new WorkspaceSchemaFactory(this, "default", name, fs, "/", matchers, true/*TODO*/));
       }else{
         factories = Lists.newArrayList();
         for(Map.Entry<String, String> space : config.workspaces.entrySet()){
-          factories.add(new WorkspaceSchemaFactory(this, space.getKey(), name, fs, space.getValue(), matchers));
+          factories.add(new WorkspaceSchemaFactory(this, space.getKey(), name, fs, space.getValue(), matchers, true/*TODO*/));
         }
 
         // if the "default" workspace is not given add one.
         if (!config.workspaces.containsKey("default")) {
-          factories.add(new WorkspaceSchemaFactory(this, "default", name, fs, "/", matchers));
+          factories.add(new WorkspaceSchemaFactory(this, "default", name, fs, "/", matchers, true/*TODO*/));
         }
       }
       this.schemaFactory = new FileSystemSchemaFactory(name, factories);
@@ -130,8 +130,8 @@ public class FileSystemPlugin extends AbstractStoragePlugin{
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
-    schemaFactory.registerSchemas(user, parent);
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
+    schemaFactory.registerSchemas(session, parent);
   }
 
   public FormatPlugin getFormatPlugin(String name){

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemSchemaFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemSchemaFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemSchemaFactory.java
index 93bac0c..92a1efc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemSchemaFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/FileSystemSchemaFactory.java
@@ -22,12 +22,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import net.hydromatic.optiq.Function;
 import net.hydromatic.optiq.Schema;
 import net.hydromatic.optiq.SchemaPlus;
 
+import net.hydromatic.optiq.Table;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.SchemaFactory;
 import org.apache.drill.exec.store.dfs.WorkspaceSchemaFactory.WorkspaceSchema;
@@ -52,8 +55,8 @@ public class FileSystemSchemaFactory implements SchemaFactory{
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
-    FileSystemSchema schema = new FileSystemSchema(schemaName);
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
+    FileSystemSchema schema = new FileSystemSchema(schemaName, session);
     SchemaPlus plusOfThis = parent.add(schema.getName(), schema);
     schema.setPlus(plusOfThis);
   }
@@ -63,10 +66,10 @@ public class FileSystemSchemaFactory implements SchemaFactory{
     private final WorkspaceSchema defaultSchema;
     private final Map<String, WorkspaceSchema> schemaMap = Maps.newHashMap();
 
-    public FileSystemSchema(String name) {
-      super(name);
+    public FileSystemSchema(String name, UserSession session) {
+      super(ImmutableList.<String>of(), name);
       for(WorkspaceSchemaFactory f :  factories){
-        WorkspaceSchema s = f.createSchema();
+        WorkspaceSchema s = f.createSchema(getSchemaPath(), session);
         schemaMap.put(s.getName(), s);
       }
 
@@ -80,7 +83,7 @@ public class FileSystemSchemaFactory implements SchemaFactory{
     }
 
     @Override
-    public DrillTable getTable(String name) {
+    public Table getTable(String name) {
       return defaultSchema.getTable(name);
     }
 
@@ -109,6 +112,10 @@ public class FileSystemSchemaFactory implements SchemaFactory{
       return defaultSchema.getTableNames();
     }
 
+    @Override
+    public boolean isMutable() {
+      return defaultSchema.isMutable();
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/WorkspaceSchemaFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/WorkspaceSchemaFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/WorkspaceSchemaFactory.java
index 1551e5a..cbaf651 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/WorkspaceSchemaFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/dfs/WorkspaceSchemaFactory.java
@@ -21,10 +21,14 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Set;
 
+import com.google.common.base.Joiner;
+import com.google.common.collect.Sets;
+import net.hydromatic.optiq.Table;
 import org.apache.drill.common.exceptions.ExecutionSetupException;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.planner.logical.DynamicDrillTable;
 import org.apache.drill.exec.planner.sql.ExpandingConcurrentMap;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.dfs.shim.DrillFileSystem;
 import org.apache.hadoop.fs.Path;
@@ -42,9 +46,10 @@ public class WorkspaceSchemaFactory implements ExpandingConcurrentMap.MapValueFa
   private final String storageEngineName;
   private final String schemaName;
   private final FileSystemPlugin plugin;
+  private final boolean isMutable;
 
   public WorkspaceSchemaFactory(FileSystemPlugin plugin, String schemaName, String storageEngineName, DrillFileSystem fileSystem, String path,
-      List<FormatMatcher> formatMatchers) throws ExecutionSetupException {
+      List<FormatMatcher> formatMatchers, boolean isMutable) throws ExecutionSetupException {
     this.fs = fileSystem;
     this.plugin = plugin;
     this.root = new Path(path);
@@ -58,10 +63,11 @@ public class WorkspaceSchemaFactory implements ExpandingConcurrentMap.MapValueFa
     }
     this.storageEngineName = storageEngineName;
     this.schemaName = schemaName;
+    this.isMutable = isMutable;
   }
 
-  public WorkspaceSchema createSchema() {
-    return new WorkspaceSchema(schemaName);
+  public WorkspaceSchema createSchema(List<String> parentSchemaPath, UserSession session) {
+    return new WorkspaceSchema(parentSchemaPath, schemaName, isMutable, session);
   }
 
   @Override
@@ -105,21 +111,32 @@ public class WorkspaceSchemaFactory implements ExpandingConcurrentMap.MapValueFa
   public class WorkspaceSchema extends AbstractSchema {
 
     private ExpandingConcurrentMap<String, DrillTable> tables = new ExpandingConcurrentMap<String, DrillTable>(WorkspaceSchemaFactory.this);
-    
-    public WorkspaceSchema(String name) {
-      super(name);
+    private boolean isMutable;
+    private UserSession session;
+
+    public WorkspaceSchema(List<String> parentSchemaPath, String name, boolean isMutable, UserSession session) {
+      super(parentSchemaPath, name);
+      this.isMutable = isMutable;
+      this.session = session;
     }
 
     @Override
     public Set<String> getTableNames() {
-      return tables.keySet();
+      return Sets.union(tables.keySet(), session.getViewStore().getViews(Joiner.on(".").join(getSchemaPath())).keySet());
     }
 
     @Override
-    public DrillTable getTable(String name) {
-      return tables.get(name);
+    public Table getTable(String name) {
+      if (tables.containsKey(name))
+        return tables.get(name);
+
+      return session.getViewStore().getViews(Joiner.on(".").join(getSchemaPath())).get(name);
     }
 
+    @Override
+    public boolean isMutable() {
+      return isMutable;
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/HiveStoragePlugin.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/HiveStoragePlugin.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/HiveStoragePlugin.java
index 0a70b20..6d5f6d2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/HiveStoragePlugin.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/HiveStoragePlugin.java
@@ -25,8 +25,8 @@ import net.hydromatic.optiq.SchemaPlus;
 
 import org.apache.drill.common.JSONOptions;
 import org.apache.drill.common.exceptions.ExecutionSetupException;
-import org.apache.drill.exec.rpc.user.DrillUser;
 import org.apache.drill.common.expression.SchemaPath;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.AbstractStoragePlugin;
 import org.apache.drill.exec.store.hive.schema.HiveSchemaFactory;
@@ -74,8 +74,8 @@ public class HiveStoragePlugin extends AbstractStoragePlugin {
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
-    schemaFactory.registerSchemas(user, parent);
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
+    schemaFactory.registerSchemas(session, parent);
   }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveDatabaseSchema.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveDatabaseSchema.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveDatabaseSchema.java
index 3608ea7..4390d74 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveDatabaseSchema.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveDatabaseSchema.java
@@ -20,6 +20,7 @@ package org.apache.drill.exec.store.hive.schema;
 import java.util.List;
 import java.util.Set;
 
+import net.hydromatic.optiq.Table;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.hive.schema.HiveSchemaFactory.HiveSchema;
@@ -36,13 +37,13 @@ public class HiveDatabaseSchema extends AbstractSchema{
       List<String> tableList, //
       HiveSchema hiveSchema, //
       String name) {
-    super(name);
+    super(hiveSchema.getSchemaPath(), name);
     this.hiveSchema = hiveSchema;
     this.tables = Sets.newHashSet(tableList);
   }
 
   @Override
-  public DrillTable getTable(String tableName) {
+  public Table getTable(String tableName) {
     return hiveSchema.getDrillTable(this.name, tableName);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveSchemaFactory.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveSchemaFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveSchemaFactory.java
index 7b30a41..4b22942 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveSchemaFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/hive/schema/HiveSchemaFactory.java
@@ -23,12 +23,14 @@ import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 
+import com.google.common.collect.ImmutableList;
 import net.hydromatic.optiq.Schema;
 import net.hydromatic.optiq.SchemaPlus;
 
 import org.apache.drill.common.exceptions.ExecutionSetupException;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.SchemaFactory;
 import org.apache.drill.exec.store.hive.HiveReadEntry;
@@ -171,7 +173,7 @@ public class HiveSchemaFactory implements SchemaFactory {
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
     HiveSchema schema = new HiveSchema(schemaName);
     SchemaPlus hPlus = parent.add(schemaName, schema);
     schema.setHolder(hPlus);
@@ -182,7 +184,7 @@ public class HiveSchemaFactory implements SchemaFactory {
     private HiveDatabaseSchema defaultSchema;
 
     public HiveSchema(String name) {
-      super(name);
+      super(ImmutableList.<String>of(), name);
       getSubSchema("default");
     }
 
@@ -223,7 +225,7 @@ public class HiveSchemaFactory implements SchemaFactory {
     }
 
     @Override
-    public DrillTable getTable(String name) {
+    public net.hydromatic.optiq.Table getTable(String name) {
       if(defaultSchema == null){
         return super.getTable(name);
       }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaStoragePlugin.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaStoragePlugin.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaStoragePlugin.java
index e7e3f37..ecf5a8b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaStoragePlugin.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/ischema/InfoSchemaStoragePlugin.java
@@ -22,13 +22,16 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import net.hydromatic.optiq.SchemaPlus;
 
+import net.hydromatic.optiq.Table;
 import org.apache.drill.common.JSONOptions;
 import org.apache.drill.common.expression.SchemaPath;
 import org.apache.drill.common.logical.StoragePluginConfig;
 import org.apache.drill.exec.planner.logical.DrillTable;
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.AbstractSchema;
 import org.apache.drill.exec.store.AbstractStoragePlugin;
@@ -66,7 +69,7 @@ public class InfoSchemaStoragePlugin extends AbstractStoragePlugin{
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
     ISchema s = new ISchema(parent, this);
     parent.add(s.getName(), s);
   }
@@ -74,7 +77,7 @@ public class InfoSchemaStoragePlugin extends AbstractStoragePlugin{
   private class ISchema extends AbstractSchema{
     private Map<String, InfoSchemaDrillTable> tables;
     public ISchema(SchemaPlus parent, InfoSchemaStoragePlugin plugin){
-      super("INFORMATION_SCHEMA");
+      super(ImmutableList.<String>of(), "INFORMATION_SCHEMA");
       Map<String, InfoSchemaDrillTable> tbls = Maps.newHashMap();
       for(SelectedTable tbl : SelectedTable.values()){
         tbls.put(tbl.name(), new InfoSchemaDrillTable(plugin, "INFORMATION_SCHEMA", tbl, config));
@@ -83,7 +86,7 @@ public class InfoSchemaStoragePlugin extends AbstractStoragePlugin{
     }
 
     @Override
-    public DrillTable getTable(String name) {
+    public Table getTable(String name) {
       return tables.get(name);
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/MockStorageEngine.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/MockStorageEngine.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/MockStorageEngine.java
index 4fe1d1b..1adbacc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/MockStorageEngine.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/MockStorageEngine.java
@@ -28,6 +28,7 @@ import org.apache.drill.common.expression.SchemaPath;
 import org.apache.drill.common.logical.StoragePluginConfig;
 import org.apache.drill.exec.physical.base.AbstractGroupScan;
 import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.AbstractStoragePlugin;
 import org.apache.drill.exec.store.mock.MockGroupScanPOP.MockScanEntry;
@@ -55,7 +56,7 @@ public class MockStorageEngine extends AbstractStoragePlugin {
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/main/java/org/apache/drill/exec/store/sys/SystemTablePlugin.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/sys/SystemTablePlugin.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/sys/SystemTablePlugin.java
index 7fb8b6c..fd3a898 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/sys/SystemTablePlugin.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/sys/SystemTablePlugin.java
@@ -22,6 +22,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import net.hydromatic.optiq.SchemaPlus;
 
 import org.apache.drill.common.JSONOptions;
@@ -30,7 +31,7 @@ import org.apache.drill.common.logical.StoragePluginConfig;
 import org.apache.drill.exec.ops.FragmentContext;
 import org.apache.drill.exec.physical.base.AbstractGroupScan;
 import org.apache.drill.exec.planner.logical.DrillTable;
-import org.apache.drill.exec.rpc.user.DrillUser;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.server.options.DrillConfigIterator;
 import org.apache.drill.exec.server.options.OptionValue;
@@ -60,7 +61,7 @@ public class SystemTablePlugin extends AbstractStoragePlugin{
   }
 
   @Override
-  public void registerSchemas(DrillUser user, SchemaPlus parent) {
+  public void registerSchemas(UserSession session, SchemaPlus parent) {
     parent.add(schema.getName(), schema);
   }
 
@@ -89,7 +90,7 @@ public class SystemTablePlugin extends AbstractStoragePlugin{
     private Set<String> tableNames;
 
     public SystemSchema() {
-      super("sys");
+      super(ImmutableList.<String>of(), "sys");
       Set<String> names = Sets.newHashSet();
       for(SystemTable t : SystemTable.values()){
         names.add(t.getTableName());

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java b/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
index 6770ee7..e030da5 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
@@ -94,7 +94,7 @@ public class PlanningBase extends ExecTest{
     registry.init();
     final FunctionImplementationRegistry functionRegistry = new FunctionImplementationRegistry(config);
     final SchemaPlus root = Frameworks.createRootSchema();
-    registry.getSchemaFactory().registerSchemas(null, root);
+    registry.getSchemaFactory().registerSchemas(new UserSession(null, null, null), root);
 
 
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/test/java/org/apache/drill/TestTpchSingleMode.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestTpchSingleMode.java b/exec/java-exec/src/test/java/org/apache/drill/TestTpchSingleMode.java
index a459bef..63a5727 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestTpchSingleMode.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestTpchSingleMode.java
@@ -111,7 +111,7 @@ public class TestTpchSingleMode extends BaseTestQuery{
   }
 
   @Test
-  @Ignore // requires views.
+  @Ignore // Fails with CannotPlanException
   public void tpch15() throws Exception{
     testSingleMode("queries/tpch/15.sql");
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/test/java/org/apache/drill/exec/store/TestOrphanSchema.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/TestOrphanSchema.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/TestOrphanSchema.java
index d7e74cb..864793a 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/TestOrphanSchema.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/TestOrphanSchema.java
@@ -25,6 +25,7 @@ import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.ExecTest;
 import org.apache.drill.exec.cache.LocalCache;
 import org.apache.drill.exec.memory.TopLevelAllocator;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.junit.Test;
 
@@ -56,7 +57,7 @@ public class TestOrphanSchema extends ExecTest {
     StoragePluginRegistry r = new StoragePluginRegistry(bitContext);
     SchemaPlus plus = Frameworks.createRootSchema();
     r.init();
-    r.getSchemaFactory().registerSchemas(null, plus);
+    r.getSchemaFactory().registerSchemas(new UserSession(null, null, null), plus);
 
     printSchema(plus, 0);
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/test/java/org/apache/drill/exec/store/ischema/OrphanSchema.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/ischema/OrphanSchema.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/ischema/OrphanSchema.java
index 1f1b367..b4ed88a 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/ischema/OrphanSchema.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/ischema/OrphanSchema.java
@@ -25,6 +25,7 @@ import net.hydromatic.optiq.tools.Frameworks;
 import org.apache.drill.common.config.DrillConfig;
 import org.apache.drill.exec.cache.LocalCache;
 import org.apache.drill.exec.memory.TopLevelAllocator;
+import org.apache.drill.exec.rpc.user.UserSession;
 import org.apache.drill.exec.server.DrillbitContext;
 import org.apache.drill.exec.store.StoragePluginRegistry;
 import org.junit.Test;
@@ -55,7 +56,7 @@ public class OrphanSchema {
     StoragePluginRegistry r = new StoragePluginRegistry(bitContext);
     r.init();
     SchemaPlus plus = Frameworks.createRootSchema();
-    r.getSchemaFactory().registerSchemas(null, plus);
+    r.getSchemaFactory().registerSchemas(new UserSession(null, null, null), plus);
     return plus;
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/java-exec/src/test/resources/queries/tpch/15.sql
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/test/resources/queries/tpch/15.sql b/exec/java-exec/src/test/resources/queries/tpch/15.sql
index 251631d..0ffa896 100644
--- a/exec/java-exec/src/test/resources/queries/tpch/15.sql
+++ b/exec/java-exec/src/test/resources/queries/tpch/15.sql
@@ -1,4 +1,6 @@
 -- tpch15 using 1395599672 as a seed to the RNG
+use dfs.`default`; -- views can only be created in dfs schema
+
 create view revenue0 (supplier_no, total_revenue) as
   select
     l_suppkey,


[4/5] DRILL-438: Add support for Views (CREATE, DROP and select)

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/b7bf00cb/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcQuery.java
----------------------------------------------------------------------
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcQuery.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcQuery.java
index 8130a33..ded0848 100644
--- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcQuery.java
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/test/TestJdbcQuery.java
@@ -22,6 +22,7 @@ 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.concurrent.TimeUnit;
 
@@ -39,6 +40,9 @@ import org.junit.rules.TestRule;
 import com.google.common.base.Function;
 import com.google.common.base.Stopwatch;
 
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 public class TestJdbcQuery extends JdbcTest{
   static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TestJdbcQuery.class);
 
@@ -482,13 +486,256 @@ public class TestJdbcQuery extends JdbcTest{
           ResultSet resultSet = statement.executeQuery("USE hive.db1");
           String result = JdbcAssert.toString(resultSet).trim();
           String expected = "ok=true; summary=Default schema changed to 'hive.db1'";
-          Assert.assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
 
 
           resultSet = statement.executeQuery("SELECT * FROM kv_db1 LIMIT 2");
           result = JdbcAssert.toString(resultSet).trim();
           expected = "key=1; value= key_1\nkey=2; value= key_2";
-          Assert.assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected), expected.equals(result));
+          statement.close();
+          return null;
+        } catch (Exception e) {
+          throw new RuntimeException(e);
+        }
+      }
+    });
+  }
+
+  /** Helper test method for view tests */
+  private void testViewHelper(final String viewCreate, final String viewName,
+                              final String viewQuery, final String queryResult) throws Exception{
+    JdbcAssert.withNoDefaultSchema().withConnection(new Function<Connection, Void>() {
+      public Void apply(Connection connection) {
+        try {
+          Statement statement = connection.createStatement();
+
+          // change default schema
+          statement.executeQuery("USE dfs.`default`");
+
+          // create view
+          ResultSet resultSet = statement.executeQuery(viewCreate);
+          String result = JdbcAssert.toString(resultSet).trim();
+          String viewCreateResult = "ok=true; summary=View '" + viewName + "' created successfully in 'dfs.default' schema";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, viewCreateResult),
+              viewCreateResult.equals(result));
+
+          // query from view
+          resultSet = statement.executeQuery(viewQuery);
+          result = JdbcAssert.toString(resultSet).trim();
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, queryResult),
+              queryResult.equals(result));
+
+          statement.close();
+          return null;
+        } catch (Exception e) {
+          throw new RuntimeException(e);
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testView1() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview1 AS SELECT * FROM cp.`region.json`",
+        "testview1",
+        "SELECT * FROM testview1 LIMIT 1",
+        "region_id=0; sales_city=None; sales_state_province=None; sales_district=No District; " +
+            "sales_region=No Region; sales_country=No Country; sales_district_id=0");
+  }
+
+  @Test
+  public void testView2() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview2 AS SELECT region_id, sales_city FROM cp.`region.json`",
+        "testview2",
+        "SELECT * FROM testview2 LIMIT 2",
+        "region_id=0; sales_city=None\nregion_id=1; sales_city=San Francisco");
+  }
+
+  @Test
+  public void testView3() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview3(regionid, salescity) AS SELECT region_id, sales_city FROM cp.`region.json`",
+        "testview3",
+        "SELECT * FROM testview3 LIMIT 2",
+        "regionid=0; salescity=None\nregionid=1; salescity=San Francisco");
+  }
+
+  @Test
+  @Ignore // See DRILL-595 - can't project columns from inner query.
+  public void testView4() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview1 AS SELECT * FROM cp.`region.json`",
+        "testview1",
+        "SELECT region_id, sales_city FROM testview1 LIMIT 2",
+        "");
+  }
+
+  @Test
+  public void testView5() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview2 AS SELECT region_id, sales_city FROM cp.`region.json`",
+        "testview2",
+        "SELECT region_id, sales_city FROM testview2 LIMIT 2",
+        "region_id=0; sales_city=None\nregion_id=1; sales_city=San Francisco");
+  }
+
+  @Test
+  public void testView6() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview2 AS SELECT region_id, sales_city FROM cp.`region.json`",
+        "testview2",
+        "SELECT sales_city FROM testview2 LIMIT 2",
+        "sales_city=None\nsales_city=San Francisco");
+  }
+
+  @Test
+  public void testView7() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview3(regionid, salescity) AS SELECT region_id, sales_city FROM cp.`region.json` LIMIT 2",
+        "testview3",
+        "SELECT regionid, salescity FROM testview3",
+        "regionid=0; salescity=None\nregionid=1; salescity=San Francisco");
+  }
+
+  @Test
+  public void testView8() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview3(regionid, salescity) AS " +
+            "SELECT region_id, sales_city FROM cp.`region.json` ORDER BY region_id DESC",
+        "testview3",
+        "SELECT regionid FROM testview3 LIMIT 2",
+        "regionid=109\nregionid=108");
+  }
+
+  @Test
+  @Ignore // Query on testview2 fails with CannotPlanException. Seems to be an issue with Union.
+  public void testView9() throws Exception{
+    testViewHelper(
+        "CREATE VIEW testview2 AS " +
+            "SELECT region_id FROM cp.`region.json` " +
+              "UNION " +
+            "SELECT employee_id FROM cp.`employee.json`",
+        "testview2",
+        "SELECT sales_city FROM testview2 LIMIT 2",
+        "sales_city=None\nsales_city=San Francisco");
+  }
+
+  @Test
+  public void testViewOnHiveTable1() throws Exception{
+    testViewHelper(
+        "CREATE VIEW hiveview AS SELECT * FROM hive.kv",
+        "hiveview",
+        "SELECT * FROM hiveview LIMIT 1",
+        "key=1; value= key_1");
+  }
+
+  @Test
+  public void testViewOnHiveTable2() throws Exception{
+    testViewHelper(
+        "CREATE VIEW hiveview AS SELECT * FROM hive.kv",
+        "hiveview",
+        "SELECT key, `value` FROM hiveview LIMIT 1",
+        "key=1; value= key_1");
+  }
+
+  @Test
+  public void testViewOnHiveTable3() throws Exception{
+    testViewHelper(
+        "CREATE VIEW hiveview AS SELECT * FROM hive.kv",
+        "hiveview",
+        "SELECT `value` FROM hiveview LIMIT 1",
+        "value= key_1");
+  }
+
+  @Test
+  public void testViewOnHiveTable4() throws Exception{
+    testViewHelper(
+        "CREATE VIEW hiveview AS SELECT key, `value` FROM hive.kv",
+        "hiveview",
+        "SELECT * FROM hiveview LIMIT 1",
+        "key=1; value= key_1");
+  }
+
+  @Test
+  public void testViewOnHiveTable5() throws Exception{
+    testViewHelper(
+        "CREATE VIEW hiveview AS SELECT key, `value` FROM hive.kv",
+        "hiveview",
+        "SELECT key, `value` FROM hiveview LIMIT 1",
+        "key=1; value= key_1");
+  }
+
+  @Test
+  public void testDropView() throws Exception{
+    JdbcAssert.withNoDefaultSchema().withConnection(new Function<Connection, Void>() {
+      public Void apply(Connection connection) {
+        try {
+          Statement statement = connection.createStatement();
+
+          // change default schema
+          statement.executeQuery("USE dfs.`default`");
+
+          // create view
+          statement.executeQuery(
+              "CREATE VIEW testview3(regionid) AS SELECT region_id FROM cp.`region.json`");
+
+          // query from view
+          ResultSet resultSet = statement.executeQuery("SELECT regionid FROM testview3 LIMIT 1");
+          String result = JdbcAssert.toString(resultSet).trim();
+          String expected = "regionid=0";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected),
+              expected.equals(result));
+
+          resultSet = statement.executeQuery("DROP VIEW testview3");
+          result = JdbcAssert.toString(resultSet).trim();
+          expected = "ok=true; summary=View 'testview3' deleted successfully from 'dfs.default' schema";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected),
+              expected.equals(result));
+
+          statement.close();
+          return null;
+        } catch (Exception e) {
+          throw new RuntimeException(e);
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testShowDescribeTablesWithView() throws Exception{
+    JdbcAssert.withNoDefaultSchema().withConnection(new Function<Connection, Void>() {
+      public Void apply(Connection connection) {
+        try {
+          Statement statement = connection.createStatement();
+
+          // change default schema
+          statement.executeQuery("USE dfs.`default`");
+
+          // create view
+          statement.executeQuery(
+              "CREATE VIEW testview3 AS SELECT * FROM hive.kv");
+
+          // show tables on view
+          ResultSet resultSet = statement.executeQuery("SHOW TABLES like 'testview3'");
+          String result = JdbcAssert.toString(resultSet).trim();
+          String expected =
+              "TABLE_SCHEMA=dfs.default; TABLE_NAME=testview3\n" +
+              "TABLE_SCHEMA=dfs; TABLE_NAME=testview3";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected),
+              expected.equals(result));
+
+          // describe a view
+          resultSet = statement.executeQuery("DESCRIBE dfs.`default`.testview3");
+          result = JdbcAssert.toString(resultSet).trim();
+          expected =
+              "COLUMN_NAME=key; DATA_TYPE=INTEGER; IS_NULLABLE=NO\n" +
+              "COLUMN_NAME=value; DATA_TYPE=VARCHAR; IS_NULLABLE=NO";
+          assertTrue(String.format("Generated string:\n%s\ndoes not match:\n%s", result, expected),
+              expected.equals(result));
+
           statement.close();
           return null;
         } catch (Exception e) {