Repository: hive Updated Branches: refs/heads/master 2b882d5b1 -> 0d0721fa4
HIVE-20940: Bridge cases in which Calcite's type resolution is more stricter than Hive. (Zoltan Haindrich reviewed by Ashutosh Chauhan) Signed-off-by: Zoltan Haindrich <k...@rxd.hu> Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/0d0721fa Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/0d0721fa Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/0d0721fa Branch: refs/heads/master Commit: 0d0721fa4dacde4c505aa727a27f958e916e8a2d Parents: 2b882d5 Author: Zoltan Haindrich <k...@rxd.hu> Authored: Wed Nov 21 07:47:25 2018 +0100 Committer: Zoltan Haindrich <k...@rxd.hu> Committed: Wed Nov 21 07:47:25 2018 +0100 ---------------------------------------------------------------------- .../calcite/translator/RexNodeConverter.java | 32 ++++++++++++++++++++ .../llap/vector_case_when_conversion.q.out | 8 ++--- 2 files changed, 36 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/0d0721fa/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/translator/RexNodeConverter.java ---------------------------------------------------------------------- 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 f6a6ff2..fef28dd 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 @@ -337,6 +337,8 @@ public class RexNodeConverter { if (calciteOp.getKind() == SqlKind.CASE) { // If it is a case operator, we need to rewrite it childRexNodeLst = rewriteCaseChildren(func, childRexNodeLst); + // Adjust branch types by inserting explicit casts if the actual is ambigous + childRexNodeLst = adjustCaseBranchTypes(childRexNodeLst, retType); } else if (HiveExtractDate.ALL_FUNCTIONS.contains(calciteOp)) { // If it is a extract operator, we need to rewrite it childRexNodeLst = rewriteExtractDateChildren(calciteOp, childRexNodeLst); @@ -362,6 +364,8 @@ public class RexNodeConverter { // This allows to be further reduced to OR, if possible calciteOp = SqlStdOperatorTable.CASE; childRexNodeLst = rewriteCoalesceChildren(func, childRexNodeLst); + // Adjust branch types by inserting explicit casts if the actual is ambigous + childRexNodeLst = adjustCaseBranchTypes(childRexNodeLst, retType); } else if (calciteOp == HiveToDateSqlOperator.INSTANCE) { childRexNodeLst = rewriteToDateChildren(childRexNodeLst); } @@ -471,6 +475,34 @@ public class RexNodeConverter { return newChildRexNodeLst; } + /** + * Adds explicit casts if Calcite's type system could not resolve the CASE branches to a common type. + * + * Calcite is more stricter than hive w.r.t type conversions. + * If a CASE has branches with string/int/boolean branch types; there is no common type. + */ + private List<RexNode> adjustCaseBranchTypes(List<RexNode> nodes, RelDataType retType) { + List<RelDataType> branchTypes = new ArrayList<>(); + for (int i = 1; i < nodes.size(); i += 2) { + branchTypes.add(nodes.get(i).getType()); + } + RelDataType commonType = cluster.getTypeFactory().leastRestrictive(branchTypes); + if (commonType != null) { + // conversion is possible; not changes are neccessary + return nodes; + } + List<RexNode> newNodes = new ArrayList<>(); + for (int i = 0; i < nodes.size(); i++) { + RexNode node = nodes.get(i); + if (i % 2 == 1) { + newNodes.add(cluster.getRexBuilder().makeCast(retType, node)); + } else { + newNodes.add(node); + } + } + return newNodes; + } + private List<RexNode> rewriteExtractDateChildren(SqlOperator op, List<RexNode> childRexNodeLst) throws SemanticException { List<RexNode> newChildRexNodeLst = new ArrayList<>(2); http://git-wip-us.apache.org/repos/asf/hive/blob/0d0721fa/ql/src/test/results/clientpositive/llap/vector_case_when_conversion.q.out ---------------------------------------------------------------------- diff --git a/ql/src/test/results/clientpositive/llap/vector_case_when_conversion.q.out b/ql/src/test/results/clientpositive/llap/vector_case_when_conversion.q.out index 8e07710..4da58e0 100644 --- a/ql/src/test/results/clientpositive/llap/vector_case_when_conversion.q.out +++ b/ql/src/test/results/clientpositive/llap/vector_case_when_conversion.q.out @@ -209,8 +209,8 @@ STAGE PLANS: Select Vectorization: className: VectorSelectOperator native: true - projectedOutputColumnNums: [6, 2, 4, 1, 18] - selectExpressions: VectorUDFAdaptor(CASE WHEN (cstring1 is not null) THEN (cstring1) WHEN (cint is not null) THEN (cint) WHEN (cfloat is not null) THEN (cfloat) WHEN (csmallint is not null) THEN (csmallint) ELSE ('none') END)(children: VectorUDFAdaptor(cstring1 is not null) -> 14:boolean, VectorUDFAdaptor(cint is not null) -> 15:boolean, VectorUDFAdaptor(cfloat is not null) -> 16:boolean, VectorUDFAdaptor(csmallint is not null) -> 17:boolean) -> 18:string + projectedOutputColumnNums: [6, 2, 4, 1, 21] + selectExpressions: VectorUDFAdaptor(CASE WHEN (cstring1 is not null) THEN (cstring1) WHEN (cint is not null) THEN (CAST( cint AS STRING)) WHEN (cfloat is not null) THEN (CAST( cfloat AS STRING)) WHEN (csmallint is not null) THEN (CAST( csmallint AS STRING)) ELSE ('none') END)(children: VectorUDFAdaptor(cstring1 is not null) -> 14:boolean, VectorUDFAdaptor(cint is not null) -> 15:boolean, VectorUDFAdaptor(CAST( cint AS STRING)) -> 16:string, VectorUDFAdaptor(cfloat is not null) -> 17:boolean, VectorUDFAdaptor(CAST( cfloat AS STRING)) -> 18:string, VectorUDFAdaptor(csmallint is not null) -> 19:boolean, VectorUDFAdaptor(CAST( csmallint AS STRING)) -> 20:string) -> 21:string Reduce Sink Vectorization: className: VectorReduceSinkObjectHashOperator native: true @@ -517,8 +517,8 @@ STAGE PLANS: Select Vectorization: className: VectorSelectOperator native: true - projectedOutputColumnNums: [6, 2, 4, 1, 18] - selectExpressions: VectorUDFAdaptor(CASE WHEN (cstring1 is not null) THEN (cstring1) WHEN (cint is not null) THEN (cint) WHEN (cfloat is not null) THEN (cfloat) WHEN (csmallint is not null) THEN (csmallint) ELSE (null) END)(children: VectorUDFAdaptor(cstring1 is not null) -> 14:boolean, VectorUDFAdaptor(cint is not null) -> 15:boolean, VectorUDFAdaptor(cfloat is not null) -> 16:boolean, VectorUDFAdaptor(csmallint is not null) -> 17:boolean) -> 18:string + projectedOutputColumnNums: [6, 2, 4, 1, 21] + selectExpressions: VectorUDFAdaptor(CASE WHEN (cstring1 is not null) THEN (cstring1) WHEN (cint is not null) THEN (CAST( cint AS STRING)) WHEN (cfloat is not null) THEN (CAST( cfloat AS STRING)) WHEN (csmallint is not null) THEN (CAST( csmallint AS STRING)) ELSE (null) END)(children: VectorUDFAdaptor(cstring1 is not null) -> 14:boolean, VectorUDFAdaptor(cint is not null) -> 15:boolean, VectorUDFAdaptor(CAST( cint AS STRING)) -> 16:string, VectorUDFAdaptor(cfloat is not null) -> 17:boolean, VectorUDFAdaptor(CAST( cfloat AS STRING)) -> 18:string, VectorUDFAdaptor(csmallint is not null) -> 19:boolean, VectorUDFAdaptor(CAST( csmallint AS STRING)) -> 20:string) -> 21:string Reduce Sink Vectorization: className: VectorReduceSinkObjectHashOperator native: true