drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject [1/2] drill git commit: DRILL-2958: Move Drill to alternative cost-based planner for join planning.
Date Sun, 10 May 2015 02:41:02 GMT
Repository: drill
Updated Branches:
  refs/heads/master 76cf72969 -> a29638363


DRILL-2958: Move Drill to alternative cost-based planner for join planning.

1. Add a new RelMdDistinctRowCount MetaDataProvider.

2. Resolve issue related to RelMetadataProvider, when querying view (Since view expander will
create a different RelOptCluster).

3. Catch CanNotPlanException in Physical Planning as well, since we allow DrillJoinRel to
be Cartesian Join, which then pass into LOPT planner.

4. Return none-infinite cost for Cartesian DrillJoinRel.

5. Ruleset change. Only use Join permutation (PushJoinPastThroughJoin) rule in the existing
planner. LOPT planner will not them.

Code clean up.


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

Branch: refs/heads/master
Commit: cd05500d1c63595d5d2cf8d83c8cfc8cc3c4c020
Parents: 76cf729
Author: Jinfeng Ni <jni@apache.org>
Authored: Wed Apr 29 11:16:04 2015 -0700
Committer: Jinfeng Ni <jni@apache.org>
Committed: Sat May 9 15:36:37 2015 -0700

----------------------------------------------------------------------
 .../exec/planner/common/DrillJoinRelBase.java   |  51 +++++-
 .../planner/common/DrillProjectRelBase.java     |   2 +-
 .../cost/DrillDefaultRelMetadataProvider.java   |  32 ++++
 .../cost/DrillRelMdDistinctRowCount.java        |  56 ++++++
 .../exec/planner/logical/DrillFilterRel.java    |   4 +
 .../exec/planner/logical/DrillJoinRel.java      |  16 +-
 .../exec/planner/logical/DrillProjectRel.java   |   4 +-
 .../planner/logical/DrillPushProjIntoScan.java  |  12 +-
 .../exec/planner/logical/DrillRelFactories.java |  90 ++++++++++
 .../exec/planner/logical/DrillRuleSets.java     |  45 +++--
 .../exec/planner/physical/PlannerSettings.java  |   3 +
 .../drill/exec/planner/sql/DrillSqlWorker.java  |  19 +-
 .../planner/sql/handlers/DefaultSqlHandler.java | 177 ++++++++++++++++++-
 .../server/options/SystemOptionManager.java     |   1 +
 14 files changed, 461 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillJoinRelBase.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillJoinRelBase.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillJoinRelBase.java
index 5ab416c..63fd497 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillJoinRelBase.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillJoinRelBase.java
@@ -51,7 +51,7 @@ public abstract class DrillJoinRelBase extends Join implements DrillRelNode
{
   private final double joinRowFactor;
 
   public DrillJoinRelBase(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode
right, RexNode condition,
-      JoinRelType joinType) throws InvalidRelException {
+      JoinRelType joinType){
     super(cluster, traits, left, right, condition, joinType, Collections.<String> emptySet());
     this.joinRowFactor = PrelUtil.getPlannerSettings(cluster.getPlanner()).getRowCountEstimateFactor();
   }
@@ -65,7 +65,19 @@ public abstract class DrillJoinRelBase extends Join implements DrillRelNode
{
           if (hasScalarSubqueryInput()) {
             return computeLogicalJoinCost(planner);
           } else {
-            return ((DrillCostFactory)planner.getCostFactory()).makeInfiniteCost();
+            /*
+             *  Why do we return non-infinite cost for CartsianJoin with non-scalar subquery,
when LOPT planner is enabled?
+             *   - We do not want to turn on the two Join permutation rule : PushJoinPastThroughJoin.LEFT,
RIGHT.
+             *   - As such, we may end up with filter on top of join, which will cause CanNotPlan
in LogicalPlanning, if we
+             *   return infinite cost.
+             *   - Such filter on top of join might be pushed into JOIN, when LOPT planner
is called.
+             *   - Return non-infinite cost will give LOPT planner a chance to try to push
the filters.
+             */
+            if (PrelUtil.getPlannerSettings(planner).isHepJoinOptEnabled()) {
+             return computeCartesianJoinCost(planner);
+            } else {
+              return ((DrillCostFactory)planner.getCostFactory()).makeInfiniteCost();
+            }
           }
         } else {
           return computeLogicalJoinCost(planner);
@@ -109,6 +121,41 @@ public abstract class DrillJoinRelBase extends Join implements DrillRelNode
{
     return this.rightKeys;
   }
 
+  protected  RelOptCost computeCartesianJoinCost(RelOptPlanner planner) {
+    double probeRowCount = RelMetadataQuery.getRowCount(this.getLeft());
+    double buildRowCount = RelMetadataQuery.getRowCount(this.getRight());
+
+    // cpu cost of hashing the join keys for the build side
+    double cpuCostBuild = DrillCostBase.HASH_CPU_COST * getRightKeys().size() * buildRowCount;
+    // cpu cost of hashing the join keys for the probe side
+    double cpuCostProbe = DrillCostBase.HASH_CPU_COST * getLeftKeys().size() * probeRowCount;
+
+    // cpu cost of evaluating each leftkey=rightkey join condition
+    double joinConditionCost = DrillCostBase.COMPARE_CPU_COST * this.getLeftKeys().size();
+
+    double factor = PrelUtil.getPlannerSettings(planner).getOptions()
+        .getOption(ExecConstants.HASH_JOIN_TABLE_FACTOR_KEY).float_val;
+    long fieldWidth = PrelUtil.getPlannerSettings(planner).getOptions()
+        .getOption(ExecConstants.AVERAGE_FIELD_WIDTH_KEY).num_val;
+
+    // table + hashValues + links
+    double memCost =
+        (
+            (fieldWidth * this.getRightKeys().size()) +
+                IntHolder.WIDTH +
+                IntHolder.WIDTH
+        ) * buildRowCount * factor;
+
+    double cpuCost = joinConditionCost * (probeRowCount * buildRowCount) // probe size determine
the join condition comparison cost
+        + cpuCostBuild + cpuCostProbe ;
+
+    DrillCostFactory costFactory = (DrillCostFactory) planner.getCostFactory();
+
+    final double mulFactor = 100000; // This is a magic number, just to make sure CartesianJoin
is more expensive than Non-CartesianJoin.
+
+    return costFactory.makeCost(buildRowCount * probeRowCount, cpuCost * mulFactor, 0, 0,
memCost * mulFactor);
+  }
+
   protected RelOptCost computeLogicalJoinCost(RelOptPlanner planner) {
     // During Logical Planning, although we don't care much about the actual physical join
that will
     // be chosen, we do care about which table - bigger or smaller - is chosen as the right
input

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillProjectRelBase.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillProjectRelBase.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillProjectRelBase.java
index 42ef6ac..d2b72c5 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillProjectRelBase.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillProjectRelBase.java
@@ -62,7 +62,7 @@ import com.google.common.collect.Lists;
 public abstract class DrillProjectRelBase extends Project implements DrillRelNode {
   private final int nonSimpleFieldCount ;
 
-  protected DrillProjectRelBase(Convention convention, RelOptCluster cluster, RelTraitSet
traits, RelNode child, List<RexNode> exps,
+  protected DrillProjectRelBase(Convention convention, RelOptCluster cluster, RelTraitSet
traits, RelNode child, List<? extends RexNode> exps,
       RelDataType rowType) {
     super(cluster, traits, child, exps, rowType, Flags.BOXED);
     assert getConvention() == convention;

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillDefaultRelMetadataProvider.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillDefaultRelMetadataProvider.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillDefaultRelMetadataProvider.java
new file mode 100644
index 0000000..7e60fd0
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillDefaultRelMetadataProvider.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.cost;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
+import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
+import org.apache.calcite.rel.metadata.RelMetadataProvider;
+
+public class DrillDefaultRelMetadataProvider {
+  private DrillDefaultRelMetadataProvider() {
+  }
+
+  public static final RelMetadataProvider INSTANCE = ChainedRelMetadataProvider.of(ImmutableList
+      .of(DrillRelMdDistinctRowCount.SOURCE,
+          new DefaultRelMetadataProvider()));
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillRelMdDistinctRowCount.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillRelMdDistinctRowCount.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillRelMdDistinctRowCount.java
new file mode 100644
index 0000000..90d6bb8
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/cost/DrillRelMdDistinctRowCount.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.cost;
+
+import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.metadata.ReflectiveRelMetadataProvider;
+import org.apache.calcite.rel.metadata.RelMdDistinctRowCount;
+import org.apache.calcite.rel.metadata.RelMetadataProvider;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.util.BuiltInMethod;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.drill.exec.planner.logical.DrillRel;
+import org.apache.drill.exec.planner.logical.DrillScanRel;
+
+public class DrillRelMdDistinctRowCount extends RelMdDistinctRowCount{
+  private static final DrillRelMdDistinctRowCount INSTANCE =
+      new DrillRelMdDistinctRowCount();
+
+  public static final RelMetadataProvider SOURCE =
+      ReflectiveRelMetadataProvider.reflectiveSource(
+          BuiltInMethod.DISTINCT_ROW_COUNT.method, INSTANCE);
+
+  @Override
+  public Double getDistinctRowCount(RelNode rel, ImmutableBitSet groupKey, RexNode predicate)
{
+    if (rel instanceof DrillScanRel) {
+      return getDistinctRowCount((DrillScanRel) rel, groupKey, predicate);
+    } else {
+      return super.getDistinctRowCount(rel, groupKey, predicate);
+    }
+  }
+
+  private Double getDistinctRowCount(DrillScanRel scan, ImmutableBitSet groupKey, RexNode
predicate) {
+    // Consistent with the estimation of Aggregate row count in RelMdRowCount : distinctRowCount
= rowCount * 10%.
+    return scan.getRows() * 0.1;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
index dbd08f4..7e649df 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillFilterRel.java
@@ -53,4 +53,8 @@ public class DrillFilterRel extends DrillFilterRelBase implements DrillRel
{
     return new DrillFilterRel(context.getCluster(), context.getLogicalTraits(), input, context.toRex(filter.getExpr()));
   }
 
+  public static DrillFilterRel create(RelNode child, RexNode condition) {
+    return new DrillFilterRel(child.getCluster(), child.getTraitSet(), child, condition)
 ;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
index dcccdb0..1c36e79 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillJoinRel.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.planner.logical;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.drill.common.expression.FieldReference;
 import org.apache.drill.common.logical.data.Join;
@@ -42,13 +43,16 @@ import org.apache.calcite.util.Pair;
 import com.google.common.collect.Lists;
 
 /**
- * Join implemented in Drill.
+ * Logical Join implemented in Drill.
  */
 public class DrillJoinRel extends DrillJoinRelBase implements DrillRel {
 
-  /** Creates a DrillJoinRel. */
+  /** Creates a DrillJoinRel.
+   * We do not throw InvalidRelException in Logical planning phase. It's up to the post-logical
planning check or physical planning
+   * to detect the unsupported join type, and throw exception.
+   * */
   public DrillJoinRel(RelOptCluster cluster, RelTraitSet traits, RelNode left, RelNode right,
RexNode condition,
-      JoinRelType joinType) throws InvalidRelException {
+      JoinRelType joinType)  {
     super(cluster, traits, left, right, condition, joinType);
 
     RelOptUtil.splitJoinCondition(left, right, condition, leftKeys, rightKeys);
@@ -66,11 +70,7 @@ public class DrillJoinRel extends DrillJoinRelBase implements DrillRel
{
 
   @Override
   public DrillJoinRel copy(RelTraitSet traitSet, RexNode condition, RelNode left, RelNode
right, JoinRelType joinType, boolean semiJoinDone) {
-    try {
-      return new DrillJoinRel(getCluster(), traitSet, left, right, condition, joinType);
-    } catch (InvalidRelException e) {
-      throw new AssertionError(e);
-    }
+    return new DrillJoinRel(getCluster(), traitSet, left, right, condition, joinType);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
index 6e132aa..3d27bef 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillProjectRel.java
@@ -41,7 +41,7 @@ import com.google.common.collect.Lists;
  * Project implemented in Drill.
  */
 public class DrillProjectRel extends DrillProjectRelBase implements DrillRel {
-  protected DrillProjectRel(RelOptCluster cluster, RelTraitSet traits, RelNode child, List<RexNode>
exps,
+  protected DrillProjectRel(RelOptCluster cluster, RelTraitSet traits, RelNode child, List<?
extends RexNode> exps,
       RelDataType rowType) {
     super(DRILL_LOGICAL, cluster, traits, child, exps, rowType);
   }
@@ -84,7 +84,7 @@ public class DrillProjectRel extends DrillProjectRelBase implements DrillRel
{
    * @param rowType
    * @return new instance of DrillProjectRel
    */
-  public static DrillProjectRel create(RelOptCluster cluster, RelTraitSet traits, RelNode
child, List<RexNode> exps,
+  public static DrillProjectRel create(RelOptCluster cluster, RelTraitSet traits, RelNode
child, List<? extends RexNode> exps,
                                        RelDataType rowType) {
     return new DrillProjectRel(cluster, traits, child, exps, rowType);
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillPushProjIntoScan.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillPushProjIntoScan.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillPushProjIntoScan.java
index 2981de8..950cd87 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillPushProjIntoScan.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillPushProjIntoScan.java
@@ -22,7 +22,9 @@ import java.io.IOException;
 import java.util.List;
 
 import org.apache.calcite.adapter.enumerable.EnumerableTableScan;
+import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.logical.LogicalProject;
 import org.apache.calcite.rel.rules.ProjectRemoveRule;
 import org.apache.drill.common.exceptions.DrillRuntimeException;
@@ -35,17 +37,19 @@ import org.apache.calcite.rex.RexNode;
 import com.google.common.collect.Lists;
 
 public class DrillPushProjIntoScan extends RelOptRule {
-  public static final RelOptRule INSTANCE = new DrillPushProjIntoScan();
+  public static final RelOptRule INSTANCE = new DrillPushProjIntoScan(LogicalProject.class,
EnumerableTableScan.class);
 
-  private DrillPushProjIntoScan() {
-    super(RelOptHelper.some(LogicalProject.class, RelOptHelper.any(EnumerableTableScan.class)),
"DrillPushProjIntoScan");
+  public static final RelOptRule DRILL_LOGICAL_INSTANCE = new DrillPushProjIntoScan(DrillProjectRel.class,
DrillScanRel.class);
+
+  private DrillPushProjIntoScan(Class<? extends Project> projectClass, Class<? extends
TableScan> scanClass) {
+    super(RelOptHelper.some(projectClass, RelOptHelper.any(scanClass)), "DrillPushProjIntoScan");
   }
 
 
   @Override
   public void onMatch(RelOptRuleCall call) {
     final Project proj = (Project) call.rel(0);
-    final EnumerableTableScan scan = (EnumerableTableScan) call.rel(1);
+    final TableScan scan = (TableScan) call.rel(1);
 
     try {
       ProjectPushInfo columnInfo = PrelUtil.getColumns(scan.getRowType(), proj.getProjects());

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRelFactories.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRelFactories.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRelFactories.java
new file mode 100644
index 0000000..0348a5b
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRelFactories.java
@@ -0,0 +1,90 @@
+/**
+ * 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 org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.logical.LogicalFilter;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUtil;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Contains factory implementation for creating various Drill Logical Rel nodes.
+ */
+
+public class DrillRelFactories {
+
+  public static final RelFactories.ProjectFactory DRILL_LOGICAL_PROJECT_FACTORY =
+      new DrillProjectFactoryImpl();
+
+  public static final RelFactories.FilterFactory DRILL_LOGICAL_FILTER_FACTORY =
+      new DrillFilterFactoryImpl();
+
+  public static final RelFactories.JoinFactory DRILL_LOGICAL_JOIN_FACTORY = new DrillJoinFactoryImpl();
+
+
+  /**
+   * Implementation of {@link RelFactories.ProjectFactory} that returns a vanilla
+   * {@link org.apache.calcite.rel.logical.LogicalProject}.
+   */
+  private static class DrillProjectFactoryImpl implements RelFactories.ProjectFactory {
+    @Override
+    public RelNode createProject(RelNode child,
+                                 List<? extends RexNode> childExprs, List<String>
fieldNames) {
+      final RelOptCluster cluster = child.getCluster();
+      final RelDataType rowType = RexUtil.createStructType(cluster.getTypeFactory(), childExprs,
fieldNames);
+      final RelNode project = DrillProjectRel.create(cluster, child.getTraitSet(), child,
childExprs, rowType);
+
+      return project;
+    }
+  }
+
+
+  /**
+   * Implementation of {@link RelFactories.FilterFactory} that
+   * returns a vanilla {@link LogicalFilter}.
+   */
+  private static class DrillFilterFactoryImpl implements RelFactories.FilterFactory {
+    @Override
+    public RelNode createFilter(RelNode child, RexNode condition) {
+      return DrillFilterRel.create(child, condition);
+    }
+  }
+
+
+  /**
+   * Implementation of {@link RelFactories.JoinFactory} that returns a vanilla
+   * {@link org.apache.calcite.rel.logical.LogicalJoin}.
+   */
+  private static class DrillJoinFactoryImpl implements RelFactories.JoinFactory {
+    @Override
+    public RelNode createJoin(RelNode left, RelNode right,
+                              RexNode condition, JoinRelType joinType,
+                              Set<String> variablesStopped, boolean semiJoinDone) {
+      return new DrillJoinRel(left.getCluster(), left.getTraitSet(), left, right, condition,
joinType);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
index 53e1bff..212cffa 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillRuleSets.java
@@ -111,24 +111,24 @@ public class DrillRuleSets {
    * @param context - shared state used during planning, currently used here
    *                to gain access to the fucntion registry described above.
    * @return - a RuleSet containing the logical rules that will always
-   *           be used.
+   *           be used, either by VolcanoPlanner directly, or
+   *           used VolcanoPlanner as pre-processing for LOPTPlanner.
+   *
+   * Note : Join permutation rule is excluded here.
    */
   public static RuleSet getDrillBasicRules(QueryContext context) {
     if (DRILL_BASIC_RULES == null) {
 
       DRILL_BASIC_RULES = new DrillRuleSet(ImmutableSet.<RelOptRule> builder().add(
//
         // Add support for WHERE style joins.
-//      PushFilterPastProjectRule.INSTANCE, // Replaced by DrillPushFilterPastProjectRule
       DrillPushFilterPastProjectRule.INSTANCE,
       DrillFilterJoinRules.DRILL_FILTER_ON_JOIN,
       DrillFilterJoinRules.DRILL_JOIN,
-      JoinPushThroughJoinRule.RIGHT,
-      JoinPushThroughJoinRule.LEFT,
+//      JoinPushThroughJoinRule.RIGHT,
+//      JoinPushThroughJoinRule.LEFT,
       // End support for WHERE style joins.
 
-      //Add back rules
-      FilterMergeRule.INSTANCE,   // MergeFilterRule. TODO: NO NEED OF DRILL'S version?
-      ExpandConversionRule.INSTANCE,
+      FilterMergeRule.INSTANCE,
 //      SwapJoinRule.INSTANCE,
       AggregateRemoveRule.INSTANCE,   // RemoveDistinctRule
 //      UnionToDistinctRule.INSTANCE,
@@ -136,34 +136,24 @@ public class DrillRuleSets {
 //      RemoveTrivialCalcRule.INSTANCE,
       SortRemoveRule.INSTANCE,      //RemoveSortRule.INSTANCE,
 
-//      TableAccessRule.INSTANCE, //
-      //MergeProjectRule.INSTANCE, //
       DrillMergeProjectRule.getInstance(true, RelFactories.DEFAULT_PROJECT_FACTORY, context.getFunctionRegistry()),
       AggregateExpandDistinctAggregatesRule.INSTANCE, //RemoveDistinctAggregateRule.INSTANCE,
//
-      // ReduceAggregatesRule.INSTANCE, // replaced by DrillReduceAggregatesRule
-      DrillValuesRule.INSTANCE,
+      DrillReduceAggregatesRule.INSTANCE,
 
       /*
       Projection push-down related rules
       */
-//      PushProjectPastFilterRule.INSTANCE,
       DrillPushProjectPastFilterRule.INSTANCE,
-//      ProjectJoinTransposeRule.INSTANCE,
       DrillPushProjectPastJoinRule.INSTANCE,
-
-//      SwapJoinRule.INSTANCE, //
-//      PushJoinThroughJoinRule.RIGHT, //
-//      PushJoinThroughJoinRule.LEFT, //
-//      PushSortPastProjectRule.INSTANCE, //
-
       DrillPushProjIntoScan.INSTANCE,
 
-//      DrillPushPartitionFilterIntoScan.FILTER_ON_PROJECT,
-//      DrillPushPartitionFilterIntoScan.FILTER_ON_SCAN,
       PruneScanRule.getFilterOnProject(context),
       PruneScanRule.getFilterOnScan(context),
 
-      ////////////////////////////////
+      /*
+       Convert from Calcite Logical to Drill Logical Rules.
+       */
+      ExpandConversionRule.INSTANCE,
       DrillScanRule.INSTANCE,
       DrillFilterRule.INSTANCE,
       DrillProjectRule.INSTANCE,
@@ -174,8 +164,7 @@ public class DrillRuleSets {
       DrillSortRule.INSTANCE,
       DrillJoinRule.INSTANCE,
       DrillUnionRule.INSTANCE,
-
-      DrillReduceAggregatesRule.INSTANCE
+      DrillValuesRule.INSTANCE
       )
       .build());
     }
@@ -183,6 +172,14 @@ public class DrillRuleSets {
     return DRILL_BASIC_RULES;
   }
 
+  // Ruleset for join permutation, used only in VolcanoPlanner.
+  public static RuleSet getJoinPermRules(QueryContext context) {
+    return new DrillRuleSet(ImmutableSet.<RelOptRule> builder().add( //
+        JoinPushThroughJoinRule.RIGHT,
+        JoinPushThroughJoinRule.LEFT
+        ).build());
+  }
+
   public static final RuleSet DRILL_PHYSICAL_DISK = new DrillRuleSet(ImmutableSet.of( //
       ProjectPrule.INSTANCE
 

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PlannerSettings.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PlannerSettings.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PlannerSettings.java
index d4fb4f2..3355018 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PlannerSettings.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PlannerSettings.java
@@ -64,6 +64,7 @@ public class PlannerSettings implements Context{
   public static final OptionValidator HASH_JOIN_SWAP_MARGIN_FACTOR = new RangeDoubleValidator("planner.join.hash_join_swap_margin_factor",
0, 100, 10d);
   public static final String ENABLE_DECIMAL_DATA_TYPE_KEY = "planner.enable_decimal_data_type";
   public static final OptionValidator ENABLE_DECIMAL_DATA_TYPE = new BooleanValidator(ENABLE_DECIMAL_DATA_TYPE_KEY,
false);
+  public static final OptionValidator HEP_JOIN_OPT = new BooleanValidator("planner.enable_hep_join_opt",
true);
 
   public static final OptionValidator IDENTIFIER_MAX_LENGTH =
       new RangeLongValidator("planner.identifier_max_length", 128 /* A minimum length is
needed because option names are identifiers themselves */,
@@ -161,6 +162,8 @@ public class PlannerSettings implements Context{
     return options.getOption(HASH_JOIN_SWAP.getOptionName()).bool_val;
   }
 
+  public boolean isHepJoinOptEnabled() { return options.getOption(HEP_JOIN_OPT.getOptionName()).bool_val;}
+
   public double getHashJoinSwapMarginFactor() {
     return options.getOption(HASH_JOIN_SWAP_MARGIN_FACTOR.getOptionName()).float_val / 100d;
   }

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/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 3c78c08..6961ee6 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
@@ -37,6 +37,7 @@ import org.apache.drill.exec.planner.cost.DrillCostBase;
 import org.apache.drill.exec.planner.logical.DrillConstExecutor;
 import org.apache.drill.exec.planner.logical.DrillRuleSets;
 import org.apache.drill.exec.planner.physical.DrillDistributionTraitDef;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
 import org.apache.drill.exec.planner.sql.handlers.AbstractSqlHandler;
 import org.apache.drill.exec.planner.sql.handlers.DefaultSqlHandler;
 import org.apache.drill.exec.planner.sql.handlers.ExplainHandler;
@@ -45,12 +46,10 @@ import org.apache.drill.exec.planner.sql.handlers.SqlHandlerConfig;
 import org.apache.drill.exec.planner.sql.parser.DrillSqlCall;
 import org.apache.drill.exec.planner.sql.parser.SqlCreateTable;
 import org.apache.drill.exec.planner.sql.parser.impl.DrillParserWithCompoundIdConverter;
-import org.apache.drill.exec.proto.UserBitShared.DrillPBError.ErrorType;
 import org.apache.drill.exec.planner.types.DrillRelDataTypeSystem;
 import org.apache.drill.exec.store.StoragePluginRegistry;
 import org.apache.drill.exec.testing.ExecutionControlsInjector;
 import org.apache.drill.exec.util.Pointer;
-import org.apache.drill.exec.work.foreman.ForemanException;
 import org.apache.drill.exec.work.foreman.ForemanSetupException;
 import org.apache.calcite.rel.RelCollationTraitDef;
 import org.apache.calcite.rel.rules.ReduceExpressionsRule;
@@ -60,10 +59,8 @@ import org.apache.calcite.plan.RelTraitDef;
 import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.plan.hep.HepProgramBuilder;
 import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
 import org.apache.calcite.sql.parser.SqlParseException;
 import org.apache.calcite.sql.parser.SqlParser;
-import org.apache.calcite.sql.parser.SqlParserImplFactory;
 import org.apache.hadoop.security.AccessControlException;
 
 public class DrillSqlWorker {
@@ -74,6 +71,8 @@ public class DrillSqlWorker {
   private final HepPlanner hepPlanner;
   public final static int LOGICAL_RULES = 0;
   public final static int PHYSICAL_MEM_RULES = 1;
+  public final static int LOGICAL_CONVERT_RULES = 2;
+
   private final QueryContext context;
 
   public DrillSqlWorker(QueryContext context) {
@@ -116,11 +115,19 @@ public class DrillSqlWorker {
     StoragePluginRegistry storagePluginRegistry = context.getStorage();
     RuleSet drillLogicalRules = DrillRuleSets.mergedRuleSets(
         DrillRuleSets.getDrillBasicRules(context),
+        DrillRuleSets.getJoinPermRules(context),
         DrillRuleSets.getDrillUserConfigurableLogicalRules(context));
     RuleSet drillPhysicalMem = DrillRuleSets.mergedRuleSets(
         DrillRuleSets.getPhysicalRules(context),
         storagePluginRegistry.getStoragePluginRuleSet());
-    RuleSet[] allRules = new RuleSet[] {drillLogicalRules, drillPhysicalMem};
+
+    // Following is used in LOPT join OPT.
+    RuleSet logicalConvertRules = DrillRuleSets.mergedRuleSets(
+        DrillRuleSets.getDrillBasicRules(context),
+        DrillRuleSets.getDrillUserConfigurableLogicalRules(context));
+
+    RuleSet[] allRules = new RuleSet[] {drillLogicalRules, drillPhysicalMem, logicalConvertRules};
+
     return allRules;
   }
 
@@ -129,6 +136,8 @@ public class DrillSqlWorker {
   }
 
   public PhysicalPlan getPlan(String sql, Pointer<String> textPlan) throws ForemanSetupException
{
+    final PlannerSettings ps = this.context.getPlannerSettings();
+
     SqlNode sqlNode;
     try {
       injector.injectChecked(context.getExecutionControls(), "sql-parsing", ForemanSetupException.class);

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DefaultSqlHandler.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DefaultSqlHandler.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DefaultSqlHandler.java
index 188aaa9..5e685c8 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DefaultSqlHandler.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/DefaultSqlHandler.java
@@ -27,7 +27,38 @@ import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.plan.hep.HepPlanner;
 import org.apache.calcite.rel.RelNode;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.hep.HepMatchOrder;
+import org.apache.calcite.plan.hep.HepProgram;
+import org.apache.calcite.plan.hep.HepProgramBuilder;
+import org.apache.calcite.rel.RelShuttleImpl;
+import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rel.core.Join;
+import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.core.TableFunctionScan;
+import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.logical.LogicalJoin;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalValues;
+import org.apache.calcite.rel.metadata.CachingRelMetadataProvider;
+import org.apache.calcite.rel.metadata.ChainedRelMetadataProvider;
+import org.apache.calcite.rel.metadata.DefaultRelMetadataProvider;
+import org.apache.calcite.rel.metadata.RelMetadataProvider;
+import org.apache.calcite.rel.rules.FilterAggregateTransposeRule;
+import org.apache.calcite.rel.rules.FilterJoinRule;
+import org.apache.calcite.rel.rules.FilterMergeRule;
+import org.apache.calcite.rel.rules.FilterProjectTransposeRule;
+import org.apache.calcite.rel.rules.JoinPushThroughJoinRule;
+import org.apache.calcite.rel.rules.JoinPushTransitivePredicatesRule;
+import org.apache.calcite.rel.rules.JoinToMultiJoinRule;
+import org.apache.calcite.rel.rules.LoptOptimizeJoinRule;
+import org.apache.calcite.rel.rules.ProjectMergeRule;
 import org.apache.calcite.rel.rules.ProjectRemoveRule;
+import org.apache.calcite.rel.rules.SemiJoinFilterTransposeRule;
+import org.apache.calcite.rel.rules.SemiJoinJoinTransposeRule;
+import org.apache.calcite.rel.rules.SemiJoinProjectTransposeRule;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexNode;
@@ -36,6 +67,7 @@ import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.TypedSqlNode;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
+import org.apache.calcite.sql2rel.RelFieldTrimmer;
 import org.apache.calcite.tools.Planner;
 import org.apache.calcite.tools.RelConversionException;
 import org.apache.calcite.tools.ValidationException;
@@ -50,8 +82,15 @@ import org.apache.drill.exec.physical.PhysicalPlan;
 import org.apache.drill.exec.physical.base.AbstractPhysicalVisitor;
 import org.apache.drill.exec.physical.base.PhysicalOperator;
 import org.apache.drill.exec.physical.impl.join.JoinUtils;
+import org.apache.drill.exec.planner.cost.DrillDefaultRelMetadataProvider;
+import org.apache.drill.exec.planner.logical.DrillFilterJoinRules;
+import org.apache.drill.exec.planner.logical.DrillJoinRel;
+import org.apache.drill.exec.planner.logical.DrillMergeProjectRule;
 import org.apache.drill.exec.planner.logical.DrillProjectRel;
+import org.apache.drill.exec.planner.logical.DrillPushFilterPastProjectRule;
+import org.apache.drill.exec.planner.logical.DrillPushProjectPastFilterRule;
 import org.apache.drill.exec.planner.logical.DrillRel;
+import org.apache.drill.exec.planner.logical.DrillRelFactories;
 import org.apache.drill.exec.planner.logical.DrillScreenRel;
 import org.apache.drill.exec.planner.logical.DrillStoreRel;
 import org.apache.drill.exec.planner.logical.PreProcessLogicalRel;
@@ -234,8 +273,14 @@ public class DefaultSqlHandler extends AbstractSqlHandler {
 
   protected DrillRel convertToDrel(RelNode relNode, RelDataType validatedRowType) throws
RelConversionException, SqlUnsupportedException {
     try {
-      RelNode convertedRelNode = planner.transform(DrillSqlWorker.LOGICAL_RULES,
-          relNode.getTraitSet().plus(DrillRel.DRILL_LOGICAL), relNode);
+      RelNode convertedRelNode;
+
+      if (! context.getPlannerSettings().isHepJoinOptEnabled()) {
+        convertedRelNode = logicalPlanningVolcano(relNode);
+      } else {
+        convertedRelNode = logicalPlanningVolcanoAndLopt(relNode);
+      }
+
       if (convertedRelNode instanceof DrillStoreRel) {
         throw new UnsupportedOperationException();
       } else {
@@ -261,10 +306,23 @@ public class DefaultSqlHandler extends AbstractSqlHandler {
     }
   }
 
-  protected Prel convertToPrel(RelNode drel) throws RelConversionException {
+
+  protected Prel convertToPrel(RelNode drel) throws RelConversionException, SqlUnsupportedException
{
     Preconditions.checkArgument(drel.getConvention() == DrillRel.DRILL_LOGICAL);
     RelTraitSet traits = drel.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.SINGLETON);
-    Prel phyRelNode = (Prel) planner.transform(DrillSqlWorker.PHYSICAL_MEM_RULES, traits,
drel);
+    Prel phyRelNode;
+    try {
+      phyRelNode = (Prel) planner.transform(DrillSqlWorker.PHYSICAL_MEM_RULES, traits, drel);
+    } catch (RelOptPlanner.CannotPlanException ex) {
+      logger.error(ex.getMessage());
+
+      if(JoinUtils.checkCartesianJoin(drel, new ArrayList<Integer>(), new ArrayList<Integer>()))
{
+        throw new UnsupportedRelOperatorException("This query cannot be planned possibly
due to either a cartesian join or an inequality join");
+      } else {
+        throw ex;
+      }
+    }
+
     OptionManager queryOptions = context.getOptions();
 
     if (context.getPlannerSettings().isMemoryEstimationEnabled()
@@ -275,7 +333,17 @@ public class DefaultSqlHandler extends AbstractSqlHandler {
       queryOptions.setOption(OptionValue.createBoolean(OptionValue.OptionType.QUERY, PlannerSettings.HASHJOIN.getOptionName(),
false));
       queryOptions.setOption(OptionValue.createBoolean(OptionValue.OptionType.QUERY, PlannerSettings.HASHAGG.getOptionName(),
false));
 
-      phyRelNode = (Prel) planner.transform(DrillSqlWorker.PHYSICAL_MEM_RULES, traits, drel);
+      try {
+        phyRelNode = (Prel) planner.transform(DrillSqlWorker.PHYSICAL_MEM_RULES, traits,
drel);
+      } catch (RelOptPlanner.CannotPlanException ex) {
+        logger.error(ex.getMessage());
+
+        if(JoinUtils.checkCartesianJoin(drel, new ArrayList<Integer>(), new ArrayList<Integer>()))
{
+          throw new UnsupportedRelOperatorException("This query cannot be planned possibly
due to either a cartesian join or an inequality join");
+        } else {
+          throw ex;
+        }
+      }
     }
 
     /*  The order of the following transformation is important */
@@ -422,4 +490,103 @@ public class DefaultSqlHandler extends AbstractSqlHandler {
   public SqlNode rewrite(SqlNode node) throws RelConversionException, ForemanSetupException
{
     return node;
   }
+
+  private RelNode logicalPlanningVolcano(RelNode relNode) throws RelConversionException,
SqlUnsupportedException {
+    return planner.transform(DrillSqlWorker.LOGICAL_RULES, relNode.getTraitSet().plus(DrillRel.DRILL_LOGICAL),
relNode);
+  }
+
+  /**
+   * Do logical planning using both VolcanoPlanner and LOPT HepPlanner.
+   * @param relNode
+   * @return
+   * @throws RelConversionException
+   * @throws SqlUnsupportedException
+   */
+  private RelNode logicalPlanningVolcanoAndLopt(RelNode relNode) throws RelConversionException,
SqlUnsupportedException {
+
+    final RelNode convertedRelNode = planner.transform(DrillSqlWorker.LOGICAL_CONVERT_RULES,
relNode.getTraitSet().plus(DrillRel.DRILL_LOGICAL), relNode);
+    log("VolCalciteRel", convertedRelNode);
+
+    final RelNode loptNode = getLoptJoinOrderTree(
+        convertedRelNode,
+        DrillJoinRel.class,
+        DrillRelFactories.DRILL_LOGICAL_JOIN_FACTORY,
+        DrillRelFactories.DRILL_LOGICAL_FILTER_FACTORY,
+        DrillRelFactories.DRILL_LOGICAL_PROJECT_FACTORY);
+
+    log("HepCalciteRel", loptNode);
+
+    return loptNode;
+  }
+
+
+  /**
+   * Appy Join Order Optimizations using Hep Planner.
+   */
+  public RelNode getLoptJoinOrderTree(RelNode root,
+                                      Class<? extends Join> joinClass,
+                                             RelFactories.JoinFactory joinFactory,
+                                             RelFactories.FilterFactory filterFactory,
+                                             RelFactories.ProjectFactory projectFactory)
{
+    final HepProgramBuilder hepPgmBldr = new HepProgramBuilder()
+        .addMatchOrder(HepMatchOrder.BOTTOM_UP)
+        .addRuleInstance(new JoinToMultiJoinRule(joinClass))
+        .addRuleInstance(new LoptOptimizeJoinRule(joinFactory, projectFactory, filterFactory))
+        .addRuleInstance(ProjectRemoveRule.INSTANCE);
+        // .addRuleInstance(new ProjectMergeRule(true, projectFactory));
+
+        // .addRuleInstance(DrillMergeProjectRule.getInstance(true, projectFactory, this.context.getFunctionRegistry()));
+
+
+    final HepProgram hepPgm = hepPgmBldr.build();
+    final HepPlanner hepPlanner = new HepPlanner(hepPgm);
+
+    final List<RelMetadataProvider> list = Lists.newArrayList();
+    list.add(DrillDefaultRelMetadataProvider.INSTANCE);
+    hepPlanner.registerMetadataProviders(list);
+    final RelMetadataProvider cachingMetaDataProvider = new CachingRelMetadataProvider(ChainedRelMetadataProvider.of(list),
hepPlanner);
+
+    // Modify RelMetaProvider for every RelNode in the SQL operator Rel tree.
+    root.accept(new MetaDataProviderModifier(cachingMetaDataProvider));
+
+    hepPlanner.setRoot(root);
+
+    RelNode calciteOptimizedPlan = hepPlanner.findBestExp();
+
+    return calciteOptimizedPlan;
+  }
+
+
+  public static class MetaDataProviderModifier extends RelShuttleImpl {
+    private final RelMetadataProvider metadataProvider;
+
+    public MetaDataProviderModifier(RelMetadataProvider metadataProvider) {
+      this.metadataProvider = metadataProvider;
+    }
+
+    @Override
+    public RelNode visit(TableScan scan) {
+      scan.getCluster().setMetadataProvider(metadataProvider);
+      return super.visit(scan);
+    }
+
+    @Override
+    public RelNode visit(TableFunctionScan scan) {
+      scan.getCluster().setMetadataProvider(metadataProvider);
+      return super.visit(scan);
+    }
+
+    @Override
+    public RelNode visit(LogicalValues values) {
+      values.getCluster().setMetadataProvider(metadataProvider);
+      return super.visit(values);
+    }
+
+    @Override
+    protected RelNode visitChild(RelNode parent, int i, RelNode child) {
+      child.accept(this);
+      parent.getCluster().setMetadataProvider(metadataProvider);
+      return parent;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/cd05500d/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
----------------------------------------------------------------------
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
index 4d8b034..e9ee68b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
@@ -71,6 +71,7 @@ public class SystemOptionManager extends BaseOptionManager {
       PlannerSettings.PARTITION_SENDER_MAX_THREADS,
       PlannerSettings.PARTITION_SENDER_SET_THREADS,
       PlannerSettings.ENABLE_DECIMAL_DATA_TYPE,
+      PlannerSettings.HEP_JOIN_OPT,
       ExecConstants.CAST_TO_NULLABLE_NUMERIC_OPTION,
       ExecConstants.OUTPUT_FORMAT_VALIDATOR,
       ExecConstants.PARQUET_BLOCK_SIZE_VALIDATOR,


Mime
View raw message