This is an automated email from the ASF dual-hosted git repository.

kgyrtkirk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 17f7208  HIVE-25734: Wrongly-typed constant in case expression leads 
to incorrect empty result (#2815) ( Alessandro Solimando reviewed by Zoltan 
Haindrich)
17f7208 is described below

commit 17f72087bd0fc8b5d306e01277052cdcc87c8556
Author: Alessandro Solimando <alessandro.solima...@gmail.com>
AuthorDate: Tue Nov 30 09:54:33 2021 +0100

    HIVE-25734: Wrongly-typed constant in case expression leads to incorrect 
empty result (#2815) ( Alessandro Solimando reviewed by Zoltan Haindrich)
---
 .../rules/HivePointLookupOptimizerRule.java        |  35 +++-
 .../calcite/translator/RexNodeConverter.java       |  14 +-
 .../rules/TestHivePointLookupOptimizerRule.java    | 165 +++++++++++++++++-
 .../calcite/translator/TestRexNodeConverter.java   | 186 +++++++++++++++++++++
 .../clientpositive/cbo_case_when_wrong_type.q      |  10 ++
 .../llap/cbo_case_when_wrong_type.q.out            |  84 ++++++++++
 .../perf/tpcds30tb/tez/query39.q.out               |   8 +-
 7 files changed, 484 insertions(+), 18 deletions(-)

diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
index bf69d3a..da6e9e7 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HivePointLookupOptimizerRule.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.calcite.plan.RelOptRule;
 import org.apache.calcite.plan.RelOptRuleCall;
@@ -387,12 +388,12 @@ public abstract class HivePointLookupOptimizerRule 
extends RelOptRule {
     }
 
     private static boolean isColumnExpr(RexNode node) {
-      return !node.getType().isStruct() && 
HiveCalciteUtil.getInputRefs(node).size() > 0
+      return !node.getType().isStruct() && 
!HiveCalciteUtil.getInputRefs(node).isEmpty()
           && HiveCalciteUtil.isDeterministic(node);
     }
 
     private static boolean isConstExpr(RexNode node) {
-      return !node.getType().isStruct() && 
HiveCalciteUtil.getInputRefs(node).size() == 0
+      return !node.getType().isStruct() && 
HiveCalciteUtil.getInputRefs(node).isEmpty()
           && HiveCalciteUtil.isDeterministic(node);
     }
 
@@ -508,7 +509,7 @@ public abstract class HivePointLookupOptimizerRule extends 
RelOptRule {
 
       for (Entry<Set<RexNodeRef>, Collection<ConstraintGroup>> sa : 
assignmentGroups.asMap().entrySet()) {
         // skip opaque
-        if (sa.getKey().size() == 0) {
+        if (sa.getKey().isEmpty()) {
           continue;
         }
         // not enough equalities should not be handled
@@ -593,6 +594,7 @@ public abstract class HivePointLookupOptimizerRule extends 
RelOptRule {
       // into a null value.
       final Multimap<RexNode,RexNode> inLHSExprToRHSNullableExprs = 
LinkedHashMultimap.create();
       final List<RexNode> operands = new 
ArrayList<>(RexUtil.flattenAnd(call.getOperands()));
+
       for (int i = 0; i < operands.size(); i++) {
         RexNode operand = operands.get(i);
         if (operand.getKind() == SqlKind.IN) {
@@ -614,7 +616,11 @@ public abstract class HivePointLookupOptimizerRule extends 
RelOptRule {
                 inLHSExprToRHSNullableExprs.put(ref, constNode);
               }
             }
-            inLHSExprToRHSExprs.get(ref).retainAll(expressions);
+            Collection<RexNode> knownConstants = inLHSExprToRHSExprs.get(ref);
+            if (!shareSameType(knownConstants, expressions)) {
+              return call;
+            }
+            knownConstants.retainAll(expressions);
           } else {
             for (int j = 1; j < inCall.getOperands().size(); j++) {
               RexNode constNode = inCall.getOperands().get(j);
@@ -639,7 +645,12 @@ public abstract class HivePointLookupOptimizerRule extends 
RelOptRule {
             inLHSExprToRHSNullableExprs.put(c.exprNode, c.constNode);
           }
           if (inLHSExprToRHSExprs.containsKey(c.exprNode)) {
-            
inLHSExprToRHSExprs.get(c.exprNode).retainAll(Collections.singleton(c.constNode));
+            Collection<RexNode> knownConstants = 
inLHSExprToRHSExprs.get(c.exprNode);
+            Collection<RexNode> nextConstant = 
Collections.singleton(c.constNode);
+            if (!shareSameType(knownConstants, nextConstant)) {
+              return call;
+            }
+            knownConstants.retainAll(nextConstant);
           } else {
             inLHSExprToRHSExprs.put(c.exprNode, c.constNode);
           }
@@ -655,6 +666,20 @@ public abstract class HivePointLookupOptimizerRule extends 
RelOptRule {
       return RexUtil.composeConjunction(rexBuilder, newOperands, false);
     }
 
+    /**
+     * Check if the type of nodes in the two collections is homogeneous within 
the collections
+     * and identical between them.
+     * @param nodes1 the first collection of nodes
+     * @param nodes2 the second collection of nodes
+     * @return true if nodes in both collections is unique and identical, 
false otherwise
+     */
+    private static boolean shareSameType(Collection<RexNode> nodes1, 
Collection<RexNode> nodes2) {
+      return Stream.of(nodes1, nodes2).flatMap(Collection::stream)
+          .map(n -> n.getType().getSqlTypeName())
+          .distinct()
+          .count() == 1;
+    }
+
     private static RexNode handleOR(RexBuilder rexBuilder, RexCall call) {
       // IN clauses need to be combined by keeping all elements
       final List<RexNode> operands = new 
ArrayList<>(RexUtil.flattenOr(call.getOperands()));
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java
index 9aa1d59..6835289 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java
@@ -150,7 +150,7 @@ public class RexNodeConverter {
     ExprNodeDesc tmpExprNode;
     RexNode tmpRN;
 
-    List<RexNode> childRexNodeLst = new ArrayList<RexNode>();
+    List<RexNode> childRexNodeLst = new ArrayList<>();
     Builder<RelDataType> argTypeBldr = ImmutableList.<RelDataType> builder();
 
     // TODO: 1) Expand to other functions as needed 2) What about types other 
than primitive.
@@ -164,7 +164,7 @@ public class RexNodeConverter {
     boolean isCompare = !isNumeric && tgtUdf instanceof GenericUDFBaseCompare;
     boolean isWhenCase = tgtUdf instanceof GenericUDFWhen || tgtUdf instanceof 
GenericUDFCase;
     boolean isTransformableTimeStamp = func.getGenericUDF() instanceof 
GenericUDFUnixTimeStamp &&
-        func.getChildren().size() != 0;
+        !func.getChildren().isEmpty();
     boolean isBetween = !isNumeric && tgtUdf instanceof GenericUDFBetween;
     boolean isIN = !isNumeric && tgtUdf instanceof GenericUDFIn;
     boolean isAllPrimitive = true;
@@ -367,9 +367,15 @@ public class RexNodeConverter {
       for (int i = 1; i < length; i++) {
         if (i % 2 == 1) {
           // We rewrite it
+          RexNode node = childRexNodeLst.get(i);
+          if (node.isA(SqlKind.LITERAL) && 
!node.getType().equals(firstPred.getType())) {
+            // this effectively changes the type of the literal to that of the 
predicate
+            // to which it is anyway going to be compared with
+            // ex: CASE WHEN =($0:SMALLINT, 1:INTEGER) ... => CASE WHEN 
=($0:SMALLINT, 1:SMALLINT)
+            node = rexBuilder.makeCast(firstPred.getType(), node);
+          }
           newChildRexNodeLst.add(
-              rexBuilder.makeCall(
-                  SqlStdOperatorTable.EQUALS, firstPred, 
childRexNodeLst.get(i)));
+              rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, firstPred, 
node));
         } else {
           newChildRexNodeLst.add(childRexNodeLst.get(i));
         }
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
index 09f83ca..67ba437 100644
--- 
a/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/rules/TestHivePointLookupOptimizerRule.java
@@ -66,6 +66,7 @@ public class TestHivePointLookupOptimizerRule {
     public int f1;
     public int f2;
     public int f3;
+    public double f4;
   }
 
   @Before
@@ -97,7 +98,7 @@ public class TestHivePointLookupOptimizerRule {
     return builder.call(SqlStdOperatorTable.AND, args);
   }
 
-  public RexNode eq(String field, int value) {
+  public RexNode eq(String field, Number value) {
     return builder.call(SqlStdOperatorTable.EQUALS,
         builder.field(field), builder.literal(value));
   }
@@ -132,6 +133,162 @@ public class TestHivePointLookupOptimizerRule {
   }
 
   @Test
+  public void testInExprsMergedSingleOverlap() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+        .scan("t")
+        .filter(
+            and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2)
+                ),
+                or(
+                    eq("f1",1),
+                    eq("f1",3)
+                )
+            )
+        )
+        .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    assertEquals("=($0, 1)", condition.toString());
+  }
+
+  @Test
+  public void testInExprsAndEqualsMerged() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+        .scan("t")
+        .filter(
+            and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2)
+                ),
+                or(
+                    eq("f1",1),
+                    eq("f1",3)
+                ),
+                eq("f1",1)
+            )
+        )
+        .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    assertEquals("=($0, 1)", condition.toString());
+  }
+
+  @Test
+  public void testInExprsMergedMultipleOverlap() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+        .scan("t")
+        .filter(
+            and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2),
+                    eq("f1",4),
+                    eq("f1",3)
+                ),
+                or(
+                    eq("f1",5),
+                    eq("f1",1),
+                    eq("f1",2),
+                    eq("f1",3)
+                )
+            )
+        )
+        .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    assertEquals("IN($0, 1, 2, 3)", condition.toString());
+  }
+
+  @Test
+  public void testCaseWithConstantsOfDifferentType() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+        .scan("t")
+        .filter(
+            and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2)
+                ),
+                eq("f1", 1.0),
+                or(
+                    eq("f4",3.0),
+                    eq("f4",4.1)
+                )
+            )
+        )
+        .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    // ideally the result would be AND(=($0, 1), IN($3, 3.0E0:DOUBLE, 
4.1E0:DOUBLE)), but we
+    // don't try to compare constants of different type for the same column, 
even if comparable
+    assertEquals("AND(IN($0, 1, 2), =($0, 1.0E0:DOUBLE), IN($3, 3.0E0:DOUBLE, 
4.1E0:DOUBLE))",
+        condition.toString());
+  }
+
+  @Test
+  public void testCaseInAndEqualsWithConstantsOfDifferentType() {
+
+    // @formatter:off
+    final RelNode basePlan = builder
+        .scan("t")
+        .filter(
+            and(
+                or(
+                    eq("f1",1),
+                    eq("f1",2)
+                ),
+                eq("f1",1),
+                or(
+                    eq("f4",3.0),
+                    eq("f4",4.1)
+                ),
+                eq("f4",4.1)
+            )
+        )
+        .build();
+    // @formatter:on
+
+    planner.setRoot(basePlan);
+    RelNode optimizedRelNode = planner.findBestExp();
+
+    HiveFilter filter = (HiveFilter) optimizedRelNode;
+    RexNode condition = filter.getCondition();
+    assertEquals("AND(=($0, 1), =($3, 4.1E0:DOUBLE))", condition.toString());
+  }
+
+  @Test
   public void testSimpleStructCase() {
 
     // @formatter:off
@@ -203,11 +360,8 @@ public class TestHivePointLookupOptimizerRule {
                         or(eq("f2",3),eq("f2",4)),
                         or(eq("f3",3),eq("f3",4))
                         )
-
-
                 )
               ))
-
           .build();
     // @formatter:on
 
@@ -217,7 +371,8 @@ public class TestHivePointLookupOptimizerRule {
     HiveFilter filter = (HiveFilter) optimizedRelNode;
     RexNode condition = filter.getCondition();
     System.out.println(condition);
-    assertEquals("AND(IN($0, 1, 2), OR(AND(IN($1, 1, 2), IN($2, 1, 2)), 
AND(IN($1, 3, 4), IN($2, 3, 4))))",
+    assertEquals("AND(IN($0, 1, 2), OR(AND(IN($1, 1, 2), IN($2, 1, 2)), "
+            + "AND(IN($1, 3, 4), IN($2, 3, 4))))",
         condition.toString());
   }
 
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/translator/TestRexNodeConverter.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/translator/TestRexNodeConverter.java
new file mode 100644
index 0000000..341097b
--- /dev/null
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/optimizer/calcite/translator/TestRexNodeConverter.java
@@ -0,0 +1,186 @@
+/*
+ * 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.hadoop.hive.ql.optimizer.calcite.translator;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelOptSchema;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.logical.LogicalTableScan;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.fun.SqlStdOperatorTable;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.tools.RelBuilder;
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.ql.optimizer.calcite.HiveRelFactories;
+import org.apache.hadoop.hive.ql.optimizer.calcite.HiveTypeSystemImpl;
+import org.apache.hadoop.hive.ql.optimizer.calcite.RelOptHiveTable;
+import org.apache.hadoop.hive.ql.parse.CalcitePlanner;
+import org.apache.hadoop.hive.ql.parse.SemanticException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.mockito.Mockito.doReturn;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TestRexNodeConverter {
+
+  private static final String CASE_FUNC_TEST = "case";
+  private static final RexBuilder REX_BUILDER = new RexBuilder(
+      new JavaTypeFactoryImpl(new HiveTypeSystemImpl()));
+  private static final RelDataTypeFactory TYPE_FACTORY = 
REX_BUILDER.getTypeFactory();
+
+  private static RelDataType smallIntegerType;
+  private static RelDataType integerType;
+  @SuppressWarnings("FieldCanBeLocal")
+  private static RelDataType nullableSmallIntegerType;
+
+  private static RexNode varChar34;
+  private static RexNode varChar35;
+  private static RexNode varCharNull;
+
+  private static RelOptCluster relOptCluster;
+  private static RelBuilder relBuilder;
+  private static RelDataType tableType;
+
+  @Mock
+  private RelOptSchema schemaMock;
+  @Mock
+  private RelOptHiveTable tableMock;
+
+  private LogicalTableScan tableScan;
+
+  @BeforeClass
+  public static void beforeClass() {
+    smallIntegerType = TYPE_FACTORY.createSqlType(SqlTypeName.SMALLINT);
+    integerType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER);
+    nullableSmallIntegerType = 
TYPE_FACTORY.createTypeWithNullability(smallIntegerType, true);
+
+    RelDataType varcharType = TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR, 
20);
+    varChar34 = REX_BUILDER.makeLiteral("34", varcharType, true);
+    varChar35 = REX_BUILDER.makeLiteral("35", varcharType, true);
+    varCharNull = REX_BUILDER.makeLiteral(null, varcharType, true);
+
+    tableType = TYPE_FACTORY.createStructType(
+        ImmutableList.of(smallIntegerType, nullableSmallIntegerType),
+        ImmutableList.of("f1", "f2")
+    );
+
+    RelOptPlanner planner = CalcitePlanner.createPlanner(new HiveConf());
+    relOptCluster = RelOptCluster.create(planner, REX_BUILDER);
+  }
+
+  @Before
+  public void before() {
+    doReturn(tableType).when(tableMock).getRowType();
+    tableScan = LogicalTableScan.create(relOptCluster, tableMock, 
Collections.emptyList());
+    relBuilder = HiveRelFactories.HIVE_BUILDER.create(relOptCluster, 
schemaMock);
+  }
+
+  @Test public void testRewriteCaseChildren() throws SemanticException {
+    RelNode scan = relBuilder.push(tableScan).build();
+    RexNode inputRef = REX_BUILDER.makeInputRef(scan, 0);
+
+    List<RexNode> childrenNodeList = ImmutableList.of(
+        inputRef,
+        REX_BUILDER.makeLiteral(1, integerType, true),
+        varChar34,
+        REX_BUILDER.makeLiteral(6, integerType, true),
+        varChar35);
+
+    List<RexNode> expected = ImmutableList.of(
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(1, smallIntegerType, true)),
+        varChar34,
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(6, smallIntegerType, true)),
+        varChar35,
+        varCharNull);
+
+    List<RexNode> computed = RexNodeConverter.rewriteCaseChildren(
+        CASE_FUNC_TEST, childrenNodeList, REX_BUILDER);
+
+    Assert.assertEquals(expected, computed);
+  }
+
+  @Test public void testRewriteCaseChildrenNullChild() throws 
SemanticException {
+    RelNode scan = relBuilder.push(tableScan).build();
+    RexNode inputRef = REX_BUILDER.makeInputRef(scan, 0);
+
+    List<RexNode> childrenNodeList = ImmutableList.of(
+        inputRef,
+        REX_BUILDER.makeLiteral(1, integerType, true),
+        varChar34,
+        REX_BUILDER.makeLiteral(null, integerType, true),
+        varChar35);
+
+    List<RexNode> expected = ImmutableList.of(
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(1, smallIntegerType, true)),
+        varChar34,
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(null, smallIntegerType, true)),
+        varChar35,
+        varCharNull);
+
+    List<RexNode> computed = RexNodeConverter.rewriteCaseChildren(
+        CASE_FUNC_TEST, childrenNodeList, REX_BUILDER);
+
+    Assert.assertEquals(expected, computed);
+  }
+
+  @Test public void testRewriteCaseChildrenNullChildAndNullableType() throws 
SemanticException {
+    RelNode scan = relBuilder.push(tableScan).build();
+    RexNode inputRef = REX_BUILDER.makeInputRef(scan, 1);
+
+    List<RexNode> childrenNodeList = ImmutableList.of(
+        inputRef,
+        REX_BUILDER.makeLiteral(1, integerType, true),
+        varChar34,
+        REX_BUILDER.makeLiteral(null, integerType, true),
+        varChar35);
+
+    List<RexNode> expected = ImmutableList.of(
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(1, smallIntegerType, true)),
+        varChar34,
+        REX_BUILDER.makeCall(SqlStdOperatorTable.EQUALS,
+            inputRef, REX_BUILDER.makeLiteral(null, smallIntegerType, true)),
+        varChar35,
+        varCharNull);
+
+    List<RexNode> computed = RexNodeConverter.rewriteCaseChildren(
+        CASE_FUNC_TEST, childrenNodeList, REX_BUILDER);
+
+    Assert.assertEquals(expected, computed);
+  }
+}
diff --git a/ql/src/test/queries/clientpositive/cbo_case_when_wrong_type.q 
b/ql/src/test/queries/clientpositive/cbo_case_when_wrong_type.q
new file mode 100644
index 0000000..d559cdb
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/cbo_case_when_wrong_type.q
@@ -0,0 +1,10 @@
+create table t (a smallint, b string);
+insert into t values (1, 'a');
+insert into t values (2, 'aa');
+insert into t values (6, 'aaaaaa');
+
+select 1 from t where a in (1,2,3) and case a when 1 then true when 2 then 
true end;
+explain cbo select 1 from t where a in (1,2,3) and case a when 1 then true 
when 2 then true end;
+
+select 1 from t where a in (1,2,3) and case when a = 1 then true when a = 2 
then true end;
+explain cbo select 1 from t where a in (1,2,3) and case when a = 1 then true 
when a = 2 then true end;
\ No newline at end of file
diff --git 
a/ql/src/test/results/clientpositive/llap/cbo_case_when_wrong_type.q.out 
b/ql/src/test/results/clientpositive/llap/cbo_case_when_wrong_type.q.out
new file mode 100644
index 0000000..dd48583
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/cbo_case_when_wrong_type.q.out
@@ -0,0 +1,84 @@
+PREHOOK: query: create table t (a smallint, b string)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t (a smallint, b string)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+PREHOOK: query: insert into t values (1, 'a')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t
+POSTHOOK: query: insert into t values (1, 'a')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t
+POSTHOOK: Lineage: t.a SCRIPT []
+POSTHOOK: Lineage: t.b SCRIPT []
+PREHOOK: query: insert into t values (2, 'aa')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t
+POSTHOOK: query: insert into t values (2, 'aa')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t
+POSTHOOK: Lineage: t.a SCRIPT []
+POSTHOOK: Lineage: t.b SCRIPT []
+PREHOOK: query: insert into t values (6, 'aaaaaa')
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@t
+POSTHOOK: query: insert into t values (6, 'aaaaaa')
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@t
+POSTHOOK: Lineage: t.a SCRIPT []
+POSTHOOK: Lineage: t.b SCRIPT []
+PREHOOK: query: select 1 from t where a in (1,2,3) and case a when 1 then true 
when 2 then true end
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t
+#### A masked pattern was here ####
+POSTHOOK: query: select 1 from t where a in (1,2,3) and case a when 1 then 
true when 2 then true end
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t
+#### A masked pattern was here ####
+1
+1
+PREHOOK: query: explain cbo select 1 from t where a in (1,2,3) and case a when 
1 then true when 2 then true end
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select 1 from t where a in (1,2,3) and case a 
when 1 then true when 2 then true end
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject($f0=[1])
+  HiveFilter(condition=[IN($0, 1:SMALLINT, 2:SMALLINT)])
+    HiveTableScan(table=[[default, t]], table:alias=[t])
+
+PREHOOK: query: select 1 from t where a in (1,2,3) and case when a = 1 then 
true when a = 2 then true end
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t
+#### A masked pattern was here ####
+POSTHOOK: query: select 1 from t where a in (1,2,3) and case when a = 1 then 
true when a = 2 then true end
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t
+#### A masked pattern was here ####
+1
+1
+PREHOOK: query: explain cbo select 1 from t where a in (1,2,3) and case when a 
= 1 then true when a = 2 then true end
+PREHOOK: type: QUERY
+PREHOOK: Input: default@t
+#### A masked pattern was here ####
+POSTHOOK: query: explain cbo select 1 from t where a in (1,2,3) and case when 
a = 1 then true when a = 2 then true end
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@t
+#### A masked pattern was here ####
+CBO PLAN:
+HiveProject($f0=[1])
+  HiveFilter(condition=[IN($0, 1:SMALLINT, 2:SMALLINT)])
+    HiveTableScan(table=[[default, t]], table:alias=[t])
+
diff --git 
a/ql/src/test/results/clientpositive/perf/tpcds30tb/tez/query39.q.out 
b/ql/src/test/results/clientpositive/perf/tpcds30tb/tez/query39.q.out
index c633923..0b0e893 100644
--- a/ql/src/test/results/clientpositive/perf/tpcds30tb/tez/query39.q.out
+++ b/ql/src/test/results/clientpositive/perf/tpcds30tb/tez/query39.q.out
@@ -214,10 +214,10 @@ STAGE PLANS:
                 outputColumnNames: _col0, _col1, _col2, _col3, _col4, _col5
                 Statistics: Num rows: 7918 Data size: 380064 Basic stats: 
COMPLETE Column stats: COMPLETE
                 Filter Operator
-                  predicate: CASE WHEN (((UDFToDouble(_col2) / _col3) = 0)) 
THEN (false) ELSE (((power(((_col4 - ((_col5 * _col5) / _col3)) / CASE WHEN 
((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / (UDFToDouble(_col2) 
/ _col3)) > 1.0D)) END (type: boolean)
+                  predicate: CASE WHEN (((UDFToDouble(_col2) / _col3) = 0.0D)) 
THEN (false) ELSE (((power(((_col4 - ((_col5 * _col5) / _col3)) / CASE WHEN 
((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / (UDFToDouble(_col2) 
/ _col3)) > 1.0D)) END (type: boolean)
                   Statistics: Num rows: 3959 Data size: 190032 Basic stats: 
COMPLETE Column stats: COMPLETE
                   Select Operator
-                    expressions: _col0 (type: bigint), _col1 (type: bigint), 
(UDFToDouble(_col2) / _col3) (type: double), CASE WHEN (((UDFToDouble(_col2) / 
_col3) = 0)) THEN (null) ELSE ((power(((_col4 - ((_col5 * _col5) / _col3)) / 
CASE WHEN ((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / 
(UDFToDouble(_col2) / _col3))) END (type: double)
+                    expressions: _col0 (type: bigint), _col1 (type: bigint), 
(UDFToDouble(_col2) / _col3) (type: double), CASE WHEN (((UDFToDouble(_col2) / 
_col3) = 0.0D)) THEN (null) ELSE ((power(((_col4 - ((_col5 * _col5) / _col3)) / 
CASE WHEN ((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / 
(UDFToDouble(_col2) / _col3))) END (type: double)
                     outputColumnNames: _col0, _col1, _col2, _col3
                     Statistics: Num rows: 3959 Data size: 126688 Basic stats: 
COMPLETE Column stats: COMPLETE
                     Map Join Operator
@@ -263,10 +263,10 @@ STAGE PLANS:
                 outputColumnNames: _col0, _col1, _col2, _col3, _col4, _col5
                 Statistics: Num rows: 7918 Data size: 380064 Basic stats: 
COMPLETE Column stats: COMPLETE
                 Filter Operator
-                  predicate: CASE WHEN (((UDFToDouble(_col2) / _col3) = 0)) 
THEN (false) ELSE (((power(((_col4 - ((_col5 * _col5) / _col3)) / CASE WHEN 
((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / (UDFToDouble(_col2) 
/ _col3)) > 1.0D)) END (type: boolean)
+                  predicate: CASE WHEN (((UDFToDouble(_col2) / _col3) = 0.0D)) 
THEN (false) ELSE (((power(((_col4 - ((_col5 * _col5) / _col3)) / CASE WHEN 
((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / (UDFToDouble(_col2) 
/ _col3)) > 1.0D)) END (type: boolean)
                   Statistics: Num rows: 3959 Data size: 190032 Basic stats: 
COMPLETE Column stats: COMPLETE
                   Select Operator
-                    expressions: _col0 (type: bigint), _col1 (type: bigint), 
(UDFToDouble(_col2) / _col3) (type: double), CASE WHEN (((UDFToDouble(_col2) / 
_col3) = 0)) THEN (null) ELSE ((power(((_col4 - ((_col5 * _col5) / _col3)) / 
CASE WHEN ((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / 
(UDFToDouble(_col2) / _col3))) END (type: double)
+                    expressions: _col0 (type: bigint), _col1 (type: bigint), 
(UDFToDouble(_col2) / _col3) (type: double), CASE WHEN (((UDFToDouble(_col2) / 
_col3) = 0.0D)) THEN (null) ELSE ((power(((_col4 - ((_col5 * _col5) / _col3)) / 
CASE WHEN ((_col3 = 1L)) THEN (null) ELSE ((_col3 - 1)) END), 0.5) / 
(UDFToDouble(_col2) / _col3))) END (type: double)
                     outputColumnNames: _col0, _col1, _col2, _col3
                     Statistics: Num rows: 3959 Data size: 126688 Basic stats: 
COMPLETE Column stats: COMPLETE
                     Reduce Output Operator

Reply via email to