DRILL-595, DRILL-811, DRILL-1029: Support select * in view, subquery, table 
expression in with clause. Most fixes in Optiq.


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

Branch: refs/heads/master
Commit: 4f59d4f0f835fec935cbdf05a277015cb763b9e4
Parents: c4cc9e4
Author: Jinfeng Ni <j...@maprtech.com>
Authored: Fri Aug 15 17:21:38 2014 -0700
Committer: Jacques Nadeau <jacq...@apache.org>
Committed: Wed Aug 27 13:33:47 2014 -0700

----------------------------------------------------------------------
 .../org/apache/drill/exec/dotdrill/View.java    |  10 ++
 .../drill/exec/planner/StarColumnHelper.java    |  10 +-
 .../drill/exec/planner/logical/DrillOptiq.java  |  10 ++
 .../exec/planner/logical/DrillViewTable.java    |   3 +-
 .../org/apache/drill/TestExampleQueries.java    | 150 +++++++++++++++++++
 pom.xml                                         |   2 +-
 6 files changed, 182 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java 
b/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
index 7965e02..8119c29 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/dotdrill/View.java
@@ -20,6 +20,7 @@ package org.apache.drill.exec.dotdrill;
 import java.util.List;
 
 import com.google.common.collect.ImmutableList;
+import org.apache.drill.exec.planner.StarColumnHelper;
 import org.apache.drill.exec.planner.types.RelDataTypeDrillImpl;
 import org.apache.drill.exec.planner.types.RelDataTypeHolder;
 import org.eigenbase.reltype.RelDataType;
@@ -135,6 +136,15 @@ public class View {
     return fields.isEmpty();
   }
 
+  @JsonIgnore
+  public boolean hasStar() {
+    for (FieldType field : fields) {
+      if (StarColumnHelper.isNonPrefixedStarColumn(field.name))
+        return true;
+    }
+    return false;
+  }
+
   public String getSql() {
     return sql;
   }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/exec/java-exec/src/main/java/org/apache/drill/exec/planner/StarColumnHelper.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/StarColumnHelper.java
 
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/StarColumnHelper.java
index 4c04b22..591faf9 100644
--- 
a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/StarColumnHelper.java
+++ 
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/StarColumnHelper.java
@@ -45,7 +45,15 @@ public class StarColumnHelper {
   public static boolean isPrefixedStarColumn(String fieldName) {
     return fieldName.indexOf(PREFIXED_STAR_COLUMN) > 0 ; // the delimiter * 
starts at none-zero position. 
   }
-  
+
+  public static boolean isNonPrefixedStarColumn(String fieldName) {
+    return fieldName.startsWith("*");
+  }
+
+  public static boolean isStarColumn(String fieldName) {
+    return isPrefixedStarColumn(fieldName) || 
isNonPrefixedStarColumn(fieldName);
+  }
+
   public static String extractStarColumnPrefix(String fieldName) {
     
     assert (isPrefixedStarColumn(fieldName));

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/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 aa88310..891b889 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
@@ -36,6 +36,7 @@ import org.apache.drill.common.types.TypeProtos.MajorType;
 import org.apache.drill.common.types.TypeProtos;
 import org.apache.drill.common.types.TypeProtos.MinorType;
 import org.apache.drill.common.types.Types;
+import org.apache.drill.exec.planner.StarColumnHelper;
 import org.eigenbase.rel.RelNode;
 import org.eigenbase.reltype.RelDataTypeField;
 import org.eigenbase.rex.RexCall;
@@ -167,6 +168,15 @@ public class DrillOptiq {
 
         if (call.getOperator() == SqlStdOperatorTable.ITEM) {
           SchemaPath left = (SchemaPath) 
call.getOperands().get(0).accept(this);
+
+          // Convert expr of item[*, 'abc'] into column expression 'abc'
+          String rootSegName = left.getRootSegment().getPath();
+          if (StarColumnHelper.isStarColumn(rootSegName)) {
+            rootSegName = rootSegName.substring(0, rootSegName.indexOf("*"));
+            final RexLiteral literal = (RexLiteral) call.getOperands().get(1);
+            return SchemaPath.getSimplePath(rootSegName + 
literal.getValue2().toString());
+          }
+
           final RexLiteral literal = (RexLiteral) call.getOperands().get(1);
           switch(literal.getTypeName()){
           case DECIMAL:

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/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
index e798d4e..68e666a 100644
--- 
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
@@ -56,7 +56,8 @@ public class DrillViewTable implements TranslatableTable, 
DrillViewInfoProvider
     RelDataType rowType = relOptTable.getRowType();
     RelNode rel = context.expandView(rowType, view.getSql(), 
view.getWorkspaceSchemaPath());
 
-    if (view.isDynamic()){
+    if (view.isDynamic() || view.hasStar()){
+      // if View's field has "*", return rel directly.
       return rel;
     }else{
       // if the View's field list is not "*", try to create a cast.

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
----------------------------------------------------------------------
diff --git 
a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java 
b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
index d9e8b20..0053388 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestExampleQueries.java
@@ -18,6 +18,7 @@
 package org.apache.drill;
 
 import org.apache.drill.common.util.FileUtils;
+import org.apache.drill.exec.rpc.RpcException;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -321,4 +322,153 @@ public class TestExampleQueries extends BaseTestQuery{
     test(query);
   }
 
+  @Test
+  public void testSelStarSubQJson2() throws Exception {
+    test("select v.first_name from (select * from cp.`employee.json`) v limit 
2" );
+  }
+
+  // Select * in SubQuery,  View  or CTE (With clause)
+  @Test  // Select * in SubQuery : regular columns appear in select clause, 
where, group by, order by.
+  public void testSelStarSubQPrefix() throws Exception {
+    test("select t.n_nationkey, t.n_name, t.n_regionkey from (select * from 
cp.`tpch/nation.parquet`) t where t.n_regionkey > 1 order by t.n_name" );
+
+    test("select n.n_regionkey, count(*) as cnt from ( select * from ( select 
* from cp.`tpch/nation.parquet`) t where t.n_nationkey < 10 ) n where 
n.n_nationkey >1 group by n.n_regionkey order by n.n_regionkey ; ");
+
+    test("select t.n_regionkey, count(*) as cnt from (select * from 
cp.`tpch/nation.parquet`) t where t.n_nationkey > 1 group by t.n_regionkey 
order by t.n_regionkey;" );
+  }
+
+  @Test  // Select * in SubQuery : regular columns appear in select clause, 
where, group by, order by.
+  public void testSelStarSubQNoPrefix() throws Exception {
+    test("select n_nationkey, n_name, n_regionkey from (select * from 
cp.`tpch/nation.parquet`)  where n_regionkey > 1 order by n_name" );
+
+    test("select n_regionkey, count(*) as cnt from ( select * from ( select * 
from cp.`tpch/nation.parquet`)  where n_nationkey < 10 ) where n_nationkey >1 
group by n_regionkey order by n_regionkey ; ");
+
+    test("select n_regionkey, count(*) as cnt from (select * from 
cp.`tpch/nation.parquet`) t where n_nationkey > 1 group by n_regionkey order by 
n_regionkey;" );
+  }
+
+  @Test  // join two SubQuery, each having select * : regular columns appear 
in the select , where and on clause, group by, order by.
+  public void testSelStarSubQJoin() throws Exception {
+    // select clause, where.
+    test(" select n.n_nationkey, n.n_name, n.n_regionkey, r.r_name \n" +
+         " from (select * from cp.`tpch/nation.parquet`) n, \n" +
+         "      (select * from cp.`tpch/region.parquet`) r \n" +
+         " where n.n_regionkey = r.r_regionkey " );
+
+    // select clause, where, group by, order by
+    test(" select n.n_regionkey, count(*) as cnt \n" +
+         " from (select * from cp.`tpch/nation.parquet`) n  \n" +
+         "    , (select * from cp.`tpch/region.parquet`) r  \n" +
+         " where n.n_regionkey = r.r_regionkey and n.n_nationkey > 10 \n" +
+         " group by n.n_regionkey \n" +
+         " order by n.n_regionkey; " );
+
+    // select clause, where, on, group by, order by.
+    test(" select n.n_regionkey, count(*) as cnt \n" +
+         " from   (select * from cp.`tpch/nation.parquet`) n  \n" +
+         "   join (select * from cp.`tpch/region.parquet`) r  \n" +
+         " on n.n_regionkey = r.r_regionkey \n" +
+         " where n.n_nationkey > 10 \n" +
+         " group by n.n_regionkey \n" +
+         " order by n.n_regionkey; " );
+
+    // Outer query use select *. Join condition in where clause.
+    test(" select *  \n" +
+         " from (select * from cp.`tpch/nation.parquet`) n \n" +
+         "    , (select * from cp.`tpch/region.parquet`) r \n" +
+         " where n.n_regionkey = r.r_regionkey " );
+
+    // Outer query use select *. Join condition in on clause.
+    test(" select *  \n" +
+         " from (select * from cp.`tpch/nation.parquet`) n \n" +
+         "    join (select * from cp.`tpch/region.parquet`) r \n" +
+         " on n.n_regionkey = r.r_regionkey " );
+  }
+
+  @Test // DRILL-595 : Select * in CTE WithClause : regular columns appear in 
select clause, where, group by, order by.
+  public void testDRILL_595WithClause() throws Exception {
+    test(" with x as (select * from cp.`region.json`) \n" +
+         " select x.region_id, x.sales_city \n" +
+         " from x where x.region_id > 10 limit 5;");
+
+    test(" with x as (select * from cp.`region.json`) \n" +
+        " select region_id, sales_city \n" +
+        " from x where region_id > 10 limit 5;");
+
+    test(" with x as (select * from cp.`tpch/nation.parquet`) \n" +
+         " select x.n_regionkey, count(*) as cnt \n" +
+         " from x \n" +
+         " where x.n_nationkey > 5 \n" +
+         " group by x.n_regionkey \n" +
+         " order by cnt limit 5; ");
+
+  }
+
+  @Test // DRILL-595 : Join two CTE, each having select * : regular columns 
appear in the select , where and on clause, group by, order by.
+  public void testDRILL_595WithClauseJoin() throws Exception {
+    test("with n as (select * from cp.`tpch/nation.parquet`), \n " +
+        "     r as (select * from cp.`tpch/region.parquet`) \n" +
+        "select n.n_nationkey, n.n_name, n.n_regionkey, r.r_name \n" +
+        "from  n, r \n" +
+        "where n.n_regionkey = r.r_regionkey ;" );
+
+    test("with n as (select * from cp.`tpch/nation.parquet`), \n " +
+        "     r as (select * from cp.`tpch/region.parquet`) \n" +
+        "select n.n_regionkey, count(*) as cnt \n" +
+        "from  n, r \n" +
+        "where n.n_regionkey = r.r_regionkey  and n.n_nationkey > 5 \n" +
+        "group by n.n_regionkey \n" +
+        "order by cnt;" );
+  }
+
+  @Test // DRILL-811
+  public void testDRILL_811View() throws Exception {
+    test("use dfs.tmp");
+    test("create view nation_view as select * from cp.`tpch/nation.parquet`;");
+
+    test("select n.n_nationkey, n.n_name, n.n_regionkey from nation_view n 
where n.n_nationkey > 8 order by n.n_regionkey");
+
+    test("select n.n_regionkey, count(*) as cnt from nation_view n where 
n.n_nationkey > 8 group by n.n_regionkey order by n.n_regionkey");
+
+    test("drop view nation_view ");
+  }
+
+  @Test  // DRILL-811
+  public void testDRILL_811ViewJoin() throws Exception {
+    test("use dfs.tmp");
+    test("create view nation_view as select * from cp.`tpch/nation.parquet`;");
+    test("create view region_view as select * from cp.`tpch/region.parquet`;");
+
+    test("select n.n_nationkey, n.n_regionkey, r.r_name from region_view r , 
nation_view n where r.r_regionkey = n.n_regionkey ");
+
+    test("select n.n_regionkey, count(*) as cnt from region_view r , 
nation_view n where r.r_regionkey = n.n_regionkey and n.n_nationkey > 8 group 
by n.n_regionkey order by n.n_regionkey");
+
+    test("select n.n_regionkey, count(*) as cnt from region_view r join 
nation_view n on r.r_regionkey = n.n_regionkey and n.n_nationkey > 8 group by 
n.n_regionkey order by n.n_regionkey");
+
+    test("drop view region_view ");
+    test("drop view nation_view ");
+  }
+
+  @Test  // DRILL-811
+  public void testDRILL_811Json() throws Exception {
+    test("use dfs.tmp");
+    test("create view region_view as select * from cp.`region.json`;");
+    test("select sales_city, sales_region from region_view where region_id > 
50 order by sales_country; ");
+    test("drop view region_view ");
+  }
+
+  @Test(expected = RpcException.class)  // Should get "At line 1, column 8: 
Column 'n_nationkey' is ambiguous"
+  public void testSelStarAmbiguousJoin() throws Exception {
+    test("select x.n_nationkey, x.n_name, x.n_regionkey, x.r_name from (select 
* from cp.`tpch/nation.parquet` n, cp.`tpch/region.parquet` r where 
n.n_regionkey = r.r_regionkey) x " ) ;
+  }
+
+  @Test  // select star for a SchemaTable.
+  public void testSelStarSubQSchemaTable() throws Exception {
+    test("select name, kind, type from (select * from sys.options);");
+  }
+
+  @Test  // Join a select star of SchemaTable, with a select star of 
Schema-less table.
+  public void testSelStarJoinSchemaWithSchemaLess() throws Exception {
+    test("select t1.name, t1.kind, t2.n_nationkey from (select * from 
sys.options) t1 join (select * from cp.`tpch/nation.parquet`) t2 on t1.name = 
t2.n_name;");
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-drill/blob/4f59d4f0/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index f04d5b2..de02c92 100644
--- a/pom.xml
+++ b/pom.xml
@@ -664,7 +664,7 @@
           <dependency>
             <groupId>net.hydromatic</groupId>
             <artifactId>optiq-core</artifactId>
-            <version>0.9-SNAPSHOT</version>
+            <version>0.9-drill-r2</version>
             <exclusions>
               <exclusion>
                 <groupId>org.jgrapht</groupId>

Reply via email to