From 5a183b7f9301751f1ed8cd286d81c6efa8adb740 Mon Sep 17 00:00:00 2001 From: Zhong Date: Fri, 18 Aug 2017 21:41:35 +0800 Subject: [PATCH] APACHE-KYLIN-2773: fix join condition push down issue when related columns are compatible while not consistent --- .../apache/calcite/sql2rel/SqlToRelConverter.java | 49 ++++++++++++---------- .../apache/kylin/query/optrule/OLAPJoinRule.java | 34 ++++++++++++++- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java index 8085a70..d4d46ce 100644 --- a/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java +++ b/atopcalcite/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java @@ -17,6 +17,26 @@ */ package org.apache.calcite.sql2rel; +import static org.apache.calcite.sql.SqlUtil.stripAs; +import static org.apache.calcite.util.Static.RESOURCE; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.AbstractList; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + import org.apache.calcite.avatica.util.Spaces; import org.apache.calcite.linq4j.Ord; import org.apache.calcite.plan.Convention; @@ -166,6 +186,7 @@ import org.apache.calcite.util.NumberUtil; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; import org.apache.calcite.util.trace.CalciteTrace; +import org.slf4j.Logger; import com.google.common.base.Function; import com.google.common.base.Preconditions; @@ -177,28 +198,6 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.slf4j.Logger; - -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.util.AbstractList; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import static org.apache.calcite.sql.SqlUtil.stripAs; -import static org.apache.calcite.util.Static.RESOURCE; - /* * The code has synced with calcite. Hope one day, we could remove the hardcode override point. * OVERRIDE POINT: @@ -2375,7 +2374,11 @@ public class SqlToRelConverter { (Join) RelFactories.DEFAULT_JOIN_FACTORY.createJoin(leftRel, rightRel, joinCond, ImmutableSet.of(), joinType, false); - return RelOptUtil.pushDownJoinConditions(originalJoin); + if (leftRel instanceof TableScan || rightRel instanceof TableScan) { + return originalJoin; + } else { + return RelOptUtil.pushDownJoinConditions(originalJoin); + } } private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) { diff --git a/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java b/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java index c31d1d0..1b357d5 100644 --- a/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java +++ b/query/src/main/java/org/apache/kylin/query/optrule/OLAPJoinRule.java @@ -18,6 +18,8 @@ package org.apache.kylin.query.optrule; +import java.util.List; + import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.RelOptCluster; import org.apache.calcite.plan.RelTraitSet; @@ -27,10 +29,15 @@ import org.apache.calcite.rel.convert.ConverterRule; import org.apache.calcite.rel.core.JoinInfo; import org.apache.calcite.rel.core.JoinRelType; import org.apache.calcite.rel.logical.LogicalJoin; +import org.apache.calcite.rex.RexCall; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.sql.SqlKind; import org.apache.kylin.query.relnode.OLAPFilterRel; import org.apache.kylin.query.relnode.OLAPJoinRel; import org.apache.kylin.query.relnode.OLAPRel; +import com.google.common.collect.Lists; + /** */ public class OLAPJoinRule extends ConverterRule { @@ -46,12 +53,14 @@ public class OLAPJoinRule extends ConverterRule { LogicalJoin join = (LogicalJoin) rel; RelNode left = join.getInput(0); RelNode right = join.getInput(1); + RexNode condition = join.getCondition(); RelTraitSet traitSet = join.getTraitSet().replace(OLAPRel.CONVENTION); left = convert(left, traitSet); right = convert(right, traitSet); + condition = convertCondition((RexCall) condition); - final JoinInfo info = JoinInfo.of(left, right, join.getCondition()); + final JoinInfo info = JoinInfo.of(left, right, condition); if (!info.isEqui() && join.getJoinType() != JoinRelType.INNER) { // EnumerableJoinRel only supports equi-join. We can put a filter on top // if it is an inner join. @@ -76,4 +85,27 @@ public class OLAPJoinRule extends ConverterRule { return newRel; } + private RexCall convertCondition(RexCall condition) { + SqlKind kind = condition.getOperator().getKind(); + if (kind == SqlKind.AND) { + List operands = Lists.newArrayListWithExpectedSize(condition.getOperands().size()); + for (RexNode operand : condition.getOperands()) { + operands.add(convertCondition((RexCall) operand)); + } + return condition.clone(condition.getType(), operands); + } else if (kind == SqlKind.EQUALS) { + List operands = condition.getOperands(); + RexNode op0 = ignoreCAST(operands.get(0)); + RexNode op1 = ignoreCAST(operands.get(1)); + return condition.clone(condition.getType(), Lists.newArrayList(op0, op1)); + } + return condition; + } + + private RexNode ignoreCAST(RexNode op) { + if (op instanceof RexCall && op.getKind() == SqlKind.CAST) { + op = ((RexCall) op).getOperands().get(0); + } + return op; + } } -- 2.5.4 (Apple Git-61)