diff --git a/storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java b/storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java index f733c1ecb5..a48e2d7f5d 100644 --- a/storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java +++ b/storage-api/src/java/org/apache/hadoop/hive/common/type/FastHiveDecimalImpl.java @@ -863,6 +863,7 @@ public static boolean fastSetFromBigDecimal( // System.out.println("FAST_SET_FROM_BIG_DECIMAL adjusted for zeroes/scale " + bigDecimal + " scale " + bigDecimal.scale()); BigInteger unscaledValue = bigDecimal.unscaledValue(); + int precision = bigDecimal.precision(); // System.out.println("FAST_SET_FROM_BIG_DECIMAL unscaledValue " + unscaledValue + " length " + unscaledValue.toString().length()); final int scale = bigDecimal.scale(); @@ -881,7 +882,7 @@ public static boolean fastSetFromBigDecimal( return true; } // This method will scale down and round to fit, if necessary. - if (!fastSetFromBigInteger(unscaledValue, scale, fastResult)) { + if (!fastSetFromBigInteger(unscaledValue, scale, precision, fastResult)) { return false; } return true; @@ -1128,6 +1129,24 @@ public static boolean fastSetFromBigInteger( */ public static boolean fastSetFromBigInteger( BigInteger bigInteger, int scale, FastHiveDecimal fastResult) { + // Poor performance, because the precision will be calculated by bigInteger.toString() + return fastSetFromBigInteger(bigInteger, scale, -1, fastResult); + } + + /** + * Creates a fast decimal from a BigInteger with a specified scale. + * + * NOTE: The fastSetFromBigInteger method requires the caller to pass a fastResult + * parameter has been reset for better performance. + * + * @param bigInteger the value to set as an integer + * @param scale the scale to use + * @param precision the precision to use + * @param fastResult an object to reuse + * @return True if the BigInteger and scale were successfully converted to a decimal. + */ + public static boolean fastSetFromBigInteger( + BigInteger bigInteger, int scale, int precision, FastHiveDecimal fastResult) { if (scale < 0) { @@ -1150,8 +1169,10 @@ public static boolean fastSetFromBigInteger( bigInteger = bigInteger.negate(); } - // A slow way to get the number of decimal digits. - int precision = bigInteger.toString().length(); + if (precision < 0) { + // A slow way to get the number of decimal digits. + precision = bigInteger.toString().length(); + } // System.out.println("FAST_SET_FROM_BIG_INTEGER adjusted bigInteger " + bigInteger + " precision " + precision); @@ -8802,8 +8823,14 @@ public static boolean fastDivide( BigDecimal divisor = fastBigDecimalValue( rightSignum, rightFast0, rightFast1, rightFast2, rightIntegerDigitCount, rightScale); + int scale = Math.max(leftScale, rightScale); + if (scale > HiveDecimal.MAX_SCALE) { + scale = HiveDecimal.MAX_SCALE; + } else if (scale < 0) { + scale = 0; + } BigDecimal quotient = - denominator.divide(divisor, HiveDecimal.MAX_SCALE, BigDecimal.ROUND_HALF_UP); + denominator.divide(divisor, scale, BigDecimal.ROUND_HALF_UP); if (!fastSetFromBigDecimal( quotient,