diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java index 9cd6812ce4..ed260bfd2a 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java @@ -687,6 +687,41 @@ public boolean accept(ExprNodeDescEqualityWrapper e) { } } + private ExprNodeDesc rewriteBetweenToIn(final ExprNodeDesc comparisonExpression, final ExprNodeDesc leftExpression, + final ExprNodeDesc rightExpression, boolean invert) { + if(ExprNodeDescUtils.isIntegerType(comparisonExpression) + && leftExpression instanceof ExprNodeConstantDesc + && rightExpression instanceof ExprNodeConstantDesc){ + Long startVal = ((Integer) ((ExprNodeConstantDesc) leftExpression).getValue()).longValue(); + Long endVal = ((Integer) ((ExprNodeConstantDesc) rightExpression).getValue()).longValue(); + List constantExprs = new ArrayList<>(); + constantExprs.add(comparisonExpression); + //generate list of contiguous integers + for(long i=startVal; i<=endVal; i++){ + ExprNodeConstantDesc constExpr = new ExprNodeConstantDesc(comparisonExpression.getTypeInfo(), i); + constantExprs.add(constExpr); + } + ExprNodeDesc newExpression = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, + new GenericUDFIn(), constantExprs); + return newExpression; + } + else { + // We transform the BETWEEN clause to AND clause (with NOT on top in invert is true). + // This is more straightforward, as the evaluateExpression method will deal with + // generating the final row count relying on the basic comparator evaluation methods + final ExprNodeDesc leftComparator = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, + new GenericUDFOPEqualOrGreaterThan(), Lists.newArrayList(comparisonExpression, leftExpression)); + final ExprNodeDesc rightComparator = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, + new GenericUDFOPEqualOrLessThan(), Lists.newArrayList(comparisonExpression, rightExpression)); + ExprNodeDesc newExpression = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, + new GenericUDFOPAnd(), Lists.newArrayList(leftComparator, rightComparator)); + if (invert) { + newExpression = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, + new GenericUDFOPNot(), Lists.newArrayList(newExpression)); + } + return newExpression; + } + } private long evaluateBetweenExpr(Statistics stats, ExprNodeDesc pred, long currNumRows, AnnotateStatsProcCtx aspCtx, List neededCols, Operator op) throws SemanticException { final ExprNodeGenericFuncDesc fd = (ExprNodeGenericFuncDesc) pred; @@ -702,19 +737,7 @@ private long evaluateBetweenExpr(Statistics stats, ExprNodeDesc pred, long currN return currNumRows; } - // We transform the BETWEEN clause to AND clause (with NOT on top in invert is true). - // This is more straightforward, as the evaluateExpression method will deal with - // generating the final row count relying on the basic comparator evaluation methods - final ExprNodeDesc leftComparator = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, - new GenericUDFOPEqualOrGreaterThan(), Lists.newArrayList(comparisonExpression, leftExpression)); - final ExprNodeDesc rightComparator = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, - new GenericUDFOPEqualOrLessThan(), Lists.newArrayList(comparisonExpression, rightExpression)); - ExprNodeDesc newExpression = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, - new GenericUDFOPAnd(), Lists.newArrayList(leftComparator, rightComparator)); - if (invert) { - newExpression = new ExprNodeGenericFuncDesc(TypeInfoFactory.booleanTypeInfo, - new GenericUDFOPNot(), Lists.newArrayList(newExpression)); - } + ExprNodeDesc newExpression = rewriteBetweenToIn(comparisonExpression, leftExpression, rightExpression, invert); return evaluateExpression(stats, newExpression, aspCtx, neededCols, op, currNumRows); } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeDescUtils.java b/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeDescUtils.java index 5275561619..ed6d8de730 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeDescUtils.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeDescUtils.java @@ -938,7 +938,7 @@ public static boolean isSame(List first, List second return true; } - // Given an expression this method figures out of the type for the expression belongs to string group + // Given an expression this method figures out if the type for the expression belongs to string group // e.g. (String, Char, Varchar etc) public static boolean isStringType(ExprNodeDesc expr) { TypeInfo typeInfo = expr.getTypeInfo(); @@ -951,4 +951,18 @@ public static boolean isStringType(ExprNodeDesc expr) { } return false; } + // Given an expression this method figures out if the type for the expression is integer + // i.e. INT, SHORT or LONG + public static boolean isIntegerType(ExprNodeDesc expr) { + TypeInfo typeInfo = expr.getTypeInfo(); + if (typeInfo.getCategory() == ObjectInspector.Category.PRIMITIVE) { + PrimitiveObjectInspector.PrimitiveCategory primitiveCategory = ((PrimitiveTypeInfo) typeInfo).getPrimitiveCategory(); + if(primitiveCategory == PrimitiveCategory.INT + || primitiveCategory == PrimitiveCategory.SHORT + || primitiveCategory == PrimitiveCategory.LONG){ + return true; + } + } + return false; + } }