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 <[email protected]>
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