KYLIN-2636 optimize case when in group by KYLIN-2636 bug fix
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/79c75015 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/79c75015 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/79c75015 Branch: refs/heads/KYLIN-2606 Commit: 79c75015e49b2216f6e8ca9ec0cedbff72737821 Parents: 2c54989 Author: Hongbin Ma <mahong...@apache.org> Authored: Mon May 22 16:45:24 2017 +0800 Committer: Hongbin Ma <mahong...@apache.org> Committed: Tue May 23 20:30:06 2017 +0800 ---------------------------------------------------------------------- .../resources/query/sql_subquery/query32.sql | 14 +++++ .../resources/query/sql_subquery/query33.sql | 14 +++++ .../resources/query/sql_subquery/query34.sql | 14 +++++ .../kylin/query/relnode/OLAPProjectRel.java | 61 +++++++++++++++++++- 4 files changed, 102 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/79c75015/kylin-it/src/test/resources/query/sql_subquery/query32.sql ---------------------------------------------------------------------- diff --git a/kylin-it/src/test/resources/query/sql_subquery/query32.sql b/kylin-it/src/test/resources/query/sql_subquery/query32.sql new file mode 100644 index 0000000..394ea15 --- /dev/null +++ b/kylin-it/src/test/resources/query/sql_subquery/query32.sql @@ -0,0 +1,14 @@ + + select sum(price) as sum_price, (case when '1'='1' then test_cal_dt.week_beg_dt when '1'='2' then test_kylin_fact.lstg_site_id else test_kylin_fact.leaf_categ_id end) as xxx + from test_kylin_fact + inner JOIN edw.test_cal_dt as test_cal_dt + ON test_kylin_fact.cal_dt = test_cal_dt.cal_dt + inner JOIN test_category_groupings + ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id AND test_kylin_fact.lstg_site_id = test_category_groupings.site_id + inner JOIN edw.test_sites as test_sites + ON test_kylin_fact.lstg_site_id = test_sites.site_id + + where case when '1'='1' then test_kylin_fact.cal_dt < date'2012-04-01' when '1'='2' then test_cal_dt.week_beg_dt > date'2012-04-01' else test_kylin_fact.lstg_site_id is not null end and lstg_format_name='FP-GTC' + + group by case when '1'='1' then test_cal_dt.week_beg_dt when '1'='2' then test_kylin_fact.lstg_site_id else test_kylin_fact.leaf_categ_id end + http://git-wip-us.apache.org/repos/asf/kylin/blob/79c75015/kylin-it/src/test/resources/query/sql_subquery/query33.sql ---------------------------------------------------------------------- diff --git a/kylin-it/src/test/resources/query/sql_subquery/query33.sql b/kylin-it/src/test/resources/query/sql_subquery/query33.sql new file mode 100644 index 0000000..08ecc8e --- /dev/null +++ b/kylin-it/src/test/resources/query/sql_subquery/query33.sql @@ -0,0 +1,14 @@ + + select sum(price) as sum_price, lstg_format_name,(case when '2'='1' then test_kylin_fact.lstg_site_id when '2'='2' then test_cal_dt.week_beg_dt else test_kylin_fact.leaf_categ_id end) as xxx + from test_kylin_fact + inner JOIN edw.test_cal_dt as test_cal_dt + ON test_kylin_fact.cal_dt = test_cal_dt.cal_dt + inner JOIN test_category_groupings + ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id AND test_kylin_fact.lstg_site_id = test_category_groupings.site_id + inner JOIN edw.test_sites as test_sites + ON test_kylin_fact.lstg_site_id = test_sites.site_id + + where case when '2'='1' then test_cal_dt.week_beg_dt > date'2012-04-01' when '2'='2' then test_kylin_fact.cal_dt < date'2012-04-01' else test_kylin_fact.lstg_site_id is not null end + + group by case when '2'='1' then test_kylin_fact.lstg_site_id when '2'='2' then test_cal_dt.week_beg_dt else test_kylin_fact.leaf_categ_id end,lstg_format_name + http://git-wip-us.apache.org/repos/asf/kylin/blob/79c75015/kylin-it/src/test/resources/query/sql_subquery/query34.sql ---------------------------------------------------------------------- diff --git a/kylin-it/src/test/resources/query/sql_subquery/query34.sql b/kylin-it/src/test/resources/query/sql_subquery/query34.sql new file mode 100644 index 0000000..0dda9aa --- /dev/null +++ b/kylin-it/src/test/resources/query/sql_subquery/query34.sql @@ -0,0 +1,14 @@ + + select sum(price) as sum_price, (case when '3'='1' then test_cal_dt.week_beg_dt else test_kylin_fact.cal_dt end) as xxx + from test_kylin_fact + inner JOIN edw.test_cal_dt as test_cal_dt + ON test_kylin_fact.cal_dt = test_cal_dt.cal_dt + inner JOIN test_category_groupings + ON test_kylin_fact.leaf_categ_id = test_category_groupings.leaf_categ_id AND test_kylin_fact.lstg_site_id = test_category_groupings.site_id + inner JOIN edw.test_sites as test_sites + ON test_kylin_fact.lstg_site_id = test_sites.site_id + + where case when '3'='1' then test_kylin_fact.cal_dt < date'2012-04-01' else test_cal_dt.week_beg_dt > date'2012-04-01' end and lstg_format_name='FP-GTC' + + group by case when '3'='1' then test_cal_dt.week_beg_dt else test_kylin_fact.cal_dt end + http://git-wip-us.apache.org/repos/asf/kylin/blob/79c75015/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java ---------------------------------------------------------------------- diff --git a/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java b/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java index 399a337..e7b09a3 100644 --- a/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java +++ b/query/src/main/java/org/apache/kylin/query/relnode/OLAPProjectRel.java @@ -18,6 +18,8 @@ package org.apache.kylin.query.relnode; +import static org.apache.kylin.metadata.filter.CompareTupleFilter.CompareResultType; + import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; @@ -46,13 +48,16 @@ import org.apache.calcite.rex.RexLiteral; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexOver; import org.apache.calcite.rex.RexProgram; +import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.fun.SqlCaseOperator; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.validate.SqlUserDefinedFunction; import org.apache.kylin.metadata.model.TblColRef; import org.apache.kylin.metadata.model.TblColRef.InnerDataTypeEnum; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; /** */ @@ -208,12 +213,66 @@ public class OLAPProjectRel extends Project implements OLAPRel { } } - for (RexNode operand : call.getOperands()) { + List<RexNode> children = limitTranslateScope(call.getOperands(), operator); + + for (RexNode operand : children) { translateRexNode(operand, inputColumnRowType, fieldName, sourceCollector); } return TblColRef.newInnerColumn(fieldName, InnerDataTypeEnum.LITERAL, call.toString()); } + //in most cases it will return children itself + private List<RexNode> limitTranslateScope(List<RexNode> children, SqlOperator operator) { + + //group by case when 1 = 1 then x 1 = 2 then y else z + if (operator instanceof SqlCaseOperator) { + int unknownWhenCalls = 0; + for (int i = 0; i < children.size() - 1; i += 2) { + if (children.get(i) instanceof RexCall) { + RexCall whenCall = (RexCall) children.get(i); + CompareResultType compareResultType = getCompareResultType(whenCall); + if (compareResultType == CompareResultType.AlwaysTrue) { + return Lists.newArrayList(children.get(i), children.get(i + 1)); + } else if (compareResultType == CompareResultType.Unknown) { + unknownWhenCalls++; + } + } + } + + if (unknownWhenCalls == 0) { + return Lists.newArrayList(children.get(children.size() - 1)); + } + } + + return children; + } + + private CompareResultType getCompareResultType(RexCall whenCall) { + List<RexNode> operands = whenCall.getOperands(); + if (SqlKind.EQUALS == whenCall.getKind() && operands != null && operands.size() == 2) { + if (operands.get(0).equals(operands.get(1))) { + return CompareResultType.AlwaysTrue; + } + + if (isConstant(operands.get(0)) && isConstant(operands.get(1))) { + return CompareResultType.AlwaysFalse; + } + } + return CompareResultType.Unknown; + } + + private boolean isConstant(RexNode rexNode) { + if (rexNode instanceof RexLiteral) { + return true; + } + + if (rexNode instanceof RexCall && SqlKind.CAST.equals(rexNode.getKind()) && ((RexCall) rexNode).getOperands().get(0) instanceof RexLiteral) { + return true; + } + + return false; + } + @Override public EnumerableRel implementEnumerable(List<EnumerableRel> inputs) { if (getInput() instanceof OLAPFilterRel) {