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 52ca3b0..7fdd9f0 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 @@ -105,6 +105,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; public class RexNodeConverter { @@ -334,6 +335,13 @@ private RexNode convert(ExprNodeGenericFuncDesc func) throws SemanticException { } else if (HiveFloorDate.ALL_FUNCTIONS.contains(calciteOp)) { // If it is a floor operator, we need to rewrite it childRexNodeLst = rewriteFloorDateChildren(calciteOp, childRexNodeLst); + } else if (FunctionRegistry.getNormalizedFunctionName( + func.getFuncText()).equals("coalesce") && + childRexNodeLst.size() > 1 ) { + // Rewrite COALESCE as a CASE + // This allows to be further reduced to OR, if possible + calciteOp = SqlStdOperatorTable.CASE; + childRexNodeLst = rewriteCoalesceChildren(func, childRexNodeLst); } expr = cluster.getRexBuilder().makeCall(calciteOp, childRexNodeLst); } else { @@ -491,6 +499,25 @@ private RexNode handleExplicitCast(ExprNodeGenericFuncDesc func, List c return newChildRexNodeLst; } + private List rewriteCoalesceChildren( + ExprNodeGenericFuncDesc func, List childRexNodeLst) { + final List convertedChildList = Lists.newArrayList(); + assert childRexNodeLst.size() > 0; + final RexBuilder rexBuilder = cluster.getRexBuilder(); + int i=0; + for (; i < childRexNodeLst.size()-1; ++i ) { + // WHEN child not null THEN child + final RexNode child = childRexNodeLst.get(i); + RexNode childCond = rexBuilder.makeCall( + SqlStdOperatorTable.IS_NOT_NULL, child); + convertedChildList.add(childCond); + convertedChildList.add(child); + } + // Add the last child as the ELSE element + convertedChildList.add(childRexNodeLst.get(i)); + return convertedChildList; + } + private static boolean checkForStatefulFunctions(List list) { for (ExprNodeDesc node : list) { if (node instanceof ExprNodeGenericFuncDesc) {