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) {

Reply via email to