You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/08/27 00:14:41 UTC

[3/3] git commit: [OPTIQ-388] Handle semi-joins in field trimmer

[OPTIQ-388] Handle semi-joins in field trimmer


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

Branch: refs/heads/master
Commit: c87a7b83c03f86691f2d591e89940c35748e431a
Parents: d241cc8
Author: Harish Butani <hb...@hortonworks.com>
Authored: Tue Aug 26 14:01:52 2014 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue Aug 26 14:36:47 2014 -0700

----------------------------------------------------------------------
 .../org/eigenbase/sql2rel/RelFieldTrimmer.java  | 25 ++++++++-
 .../org/eigenbase/test/RelOptRulesTest.java     | 58 ++++++++++++++++++++
 .../org/eigenbase/test/RelOptRulesTest.xml      | 44 +++++++++++++++
 3 files changed, 124 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/c87a7b83/core/src/main/java/org/eigenbase/sql2rel/RelFieldTrimmer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql2rel/RelFieldTrimmer.java b/core/src/main/java/org/eigenbase/sql2rel/RelFieldTrimmer.java
index 078bd03..e5e929e 100644
--- a/core/src/main/java/org/eigenbase/sql2rel/RelFieldTrimmer.java
+++ b/core/src/main/java/org/eigenbase/sql2rel/RelFieldTrimmer.java
@@ -21,6 +21,7 @@ import java.util.*;
 
 import org.eigenbase.rel.*;
 import org.eigenbase.rel.rules.RemoveTrivialProjectRule;
+import org.eigenbase.rel.rules.SemiJoinRel;
 import org.eigenbase.relopt.*;
 import org.eigenbase.reltype.*;
 import org.eigenbase.rex.*;
@@ -459,11 +460,13 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
    * {@link JoinRel}.
    */
   public TrimResult trimFields(
-      JoinRel join,
+      JoinRelBase join,
       BitSet fieldsUsed,
       Set<RelDataTypeField> extraFields) {
     final RelDataType rowType = join.getRowType();
-    final int fieldCount = rowType.getFieldCount();
+    final int fieldCount = join.getSystemFieldList().size()
+        + join.getLeft().getRowType().getFieldCount()
+        + join.getRight().getRowType().getFieldCount();
     final RexNode conditionExpr = join.getCondition();
     final int systemFieldCount = join.getSystemFieldList().size();
 
@@ -572,10 +575,26 @@ public class RelFieldTrimmer implements ReflectiveVisitor {
     RexNode newConditionExpr =
         conditionExpr.accept(shuttle);
 
-    final JoinRel newJoin =
+    final JoinRelBase newJoin =
         join.copy(join.getTraitSet(), newConditionExpr, newInputs.get(0),
             newInputs.get(1), join.getJoinType(), join.isSemiJoinDone());
 
+    // For SemiJoins only map fields from the left-side
+    if (newJoin instanceof SemiJoinRel) {
+      Mapping inputMapping = inputMappings.get(0);
+      mapping = Mappings.create(MappingType.INVERSE_SURJECTION,
+          join.getRowType().getFieldCount(),
+          newSystemFieldCount + inputMapping.getTargetCount());
+      for (int i = 0; i < newSystemFieldCount; ++i) {
+        mapping.set(i, i);
+      }
+      offset = systemFieldCount;
+      newOffset = newSystemFieldCount;
+      for (IntPair pair : inputMapping) {
+        mapping.set(pair.source + offset, pair.target + newOffset);
+      }
+    }
+
     return new TrimResult(newJoin, mapping);
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/c87a7b83/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java b/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
index db33f10..4e97fb5 100644
--- a/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/eigenbase/test/RelOptRulesTest.java
@@ -61,7 +61,11 @@ import org.eigenbase.relopt.hep.HepProgram;
 import org.eigenbase.relopt.hep.HepProgramBuilder;
 import org.eigenbase.reltype.RelDataType;
 import org.eigenbase.reltype.RelDataTypeFactory;
+import org.eigenbase.sql.SqlNode;
 import org.eigenbase.sql.type.SqlTypeName;
+import org.eigenbase.sql.validate.SqlValidator;
+import org.eigenbase.sql2rel.SqlToRelConverter;
+import org.eigenbase.util.Util;
 
 import net.hydromatic.optiq.prepare.Prepare;
 
@@ -177,6 +181,60 @@ public class RelOptRulesTest extends RelOptTestBase {
             + "  and emp.sal > 100)");
   }
 
+  protected void semiJoinTrim() {
+
+    final DiffRepository diffRepos = getDiffRepos();
+    String sql = diffRepos.expand(null, "${sql}");
+
+    TesterImpl t = (TesterImpl) tester;
+    final RelDataTypeFactory typeFactory = t.getTypeFactory();
+    final Prepare.CatalogReader catalogReader =
+        t.createCatalogReader(typeFactory);
+    final SqlValidator validator =
+        t.createValidator(
+            catalogReader, typeFactory);
+    final SqlToRelConverter converter =
+        t.createSqlToRelConverter(
+            validator,
+            catalogReader,
+            typeFactory);
+
+    final SqlNode sqlQuery;
+    try {
+      sqlQuery = t.parseQuery(sql);
+    } catch (Exception e) {
+      throw Util.newInternal(e);
+    }
+
+    final SqlNode validatedQuery = validator.validate(sqlQuery);
+    RelNode rel =
+        converter.convertQuery(validatedQuery, false, true);
+    rel = converter.decorrelate(sqlQuery, rel);
+
+    final HepProgram program =
+        HepProgram.builder()
+            .addRuleInstance(PushFilterPastProjectRule.INSTANCE)
+            .addRuleInstance(PushFilterPastJoinRule.FILTER_ON_JOIN)
+            .addRuleInstance(MergeProjectRule.INSTANCE)
+            .addRuleInstance(SemiJoinRule.INSTANCE)
+            .build();
+
+    HepPlanner planner = new HepPlanner(program);
+    planner.setRoot(rel);
+    rel = planner.findBestExp();
+
+    String planBefore = NL + RelOptUtil.toString(rel);
+    diffRepos.assertEquals("planBefore", "${planBefore}", planBefore);
+    converter.setTrimUnusedFields(true);
+    rel = converter.trimUnusedFields(rel);
+    String planAfter = NL + RelOptUtil.toString(rel);
+    diffRepos.assertEquals("planAfter", "${planAfter}", planAfter);
+  }
+
+  @Test public void testSemiJoinTrim() {
+    semiJoinTrim();
+  }
+
   @Test public void testReduceAverage() {
     checkPlanning(
         ReduceAggregatesRule.INSTANCE,

http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/c87a7b83/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
index 564a16b..0232bf9 100644
--- a/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/eigenbase/test/RelOptRulesTest.xml
@@ -2089,4 +2089,48 @@ SemiJoinRel(condition=[=($0, $2)], joinType=[inner])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testSemiJoinTrim">
+        <Resource name="sql">
+            <![CDATA[select s.deptno from (select * from dept where exists (
+  select * from emp
+  where emp.deptno = dept.deptno
+  and emp.sal > 100)) s join customer.account on s.deptno = account.acctno]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+ProjectRel(DEPTNO=[$0])
+  JoinRel(condition=[=($0, $2)], joinType=[inner])
+    SemiJoinRel(condition=[=($0, $2)], joinType=[inner])
+      TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+      ProjectRel($f01=[$9], $f0=[true])
+        JoinRel(condition=[=($7, $9)], joinType=[inner])
+          FilterRel(condition=[>($5, 100)])
+            TableAccessRel(table=[[CATALOG, SALES, EMP]])
+          AggregateRel(group=[{0}])
+            ProjectRel($f0=[$0])
+              TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+    TableAccessRel(table=[[CATALOG, CUSTOMER, ACCOUNT]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+ProjectRel(DEPTNO=[$0])
+  JoinRel(condition=[=($0, $1)], joinType=[inner])
+    SemiJoinRel(condition=[=($0, $1)], joinType=[inner])
+      ProjectRel(DEPTNO=[$0])
+        TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+      ProjectRel($f01=[$2])
+        JoinRel(condition=[=($1, $2)], joinType=[inner])
+          FilterRel(condition=[>($0, 100)])
+            ProjectRel(SAL=[$5], DEPTNO=[$7])
+              TableAccessRel(table=[[CATALOG, SALES, EMP]])
+          AggregateRel(group=[{0}])
+            ProjectRel($f0=[$0])
+              ProjectRel(DEPTNO=[$0])
+                TableAccessRel(table=[[CATALOG, SALES, DEPT]])
+    ProjectRel(ACCTNO=[$0])
+      TableAccessRel(table=[[CATALOG, CUSTOMER, ACCOUNT]])
+]]>
+        </Resource>
+    </TestCase>
 </Root>