Skip to content

Commit

Permalink
[SPARK-25454][SQL] Avoid precision loss in division with decimal with…
Browse files Browse the repository at this point in the history
… negative scale
  • Loading branch information
mgaido91 committed Sep 18, 2018
1 parent b66e14d commit 7c4b454
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,17 @@ object DecimalPrecision extends TypeCoercionRule {
resultType)

case Divide(e1 @ DecimalType.Expression(p1, s1), e2 @ DecimalType.Expression(p2, s2)) =>
val adjP2 = if (s2 < 0) p2 - s2 else p2
val resultType = if (SQLConf.get.decimalOperationsAllowPrecisionLoss) {
// Precision: p1 - s1 + s2 + max(6, s1 + p2 + 1)
// Scale: max(6, s1 + p2 + 1)
val intDig = p1 - s1 + s2
val scale = max(DecimalType.MINIMUM_ADJUSTED_SCALE, s1 + p2 + 1)
val scale = max(DecimalType.MINIMUM_ADJUSTED_SCALE, s1 + adjP2 + 1)
val prec = intDig + scale
DecimalType.adjustPrecisionScale(prec, scale)
} else {
var intDig = min(DecimalType.MAX_SCALE, p1 - s1 + s2)
var decDig = min(DecimalType.MAX_SCALE, max(6, s1 + p2 + 1))
var decDig = min(DecimalType.MAX_SCALE, max(6, s1 + adjP2 + 1))
val diff = (intDig + decDig) - DecimalType.MAX_SCALE
if (diff > 0) {
decDig -= diff / 2 + 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,11 @@ class DecimalPrecisionSuite extends AnalysisTest with BeforeAndAfter {
val a = AttributeReference("a", DecimalType(3, -10))()
val b = AttributeReference("b", DecimalType(1, -1))()
val c = AttributeReference("c", DecimalType(35, 1))()
val nonNegative = AttributeReference("nn", DecimalType(11, 0))()
checkType(Multiply(a, b), DecimalType(5, -11))
checkType(Multiply(a, c), DecimalType(38, -9))
checkType(Multiply(b, c), DecimalType(37, 0))
checkType(Divide(nonNegative, a), DecimalType(15, 14))
}

/** strength reduction for integer/decimal comparisons */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@ select 12345678912345678912345678912.1234567 + 9999999999999999999999999999999.1
select 123456789123456789.1234567890 * 1.123456789123456789;
select 12345678912345.123456789123 / 0.000000012345678;

-- division with negative scale operands
select 26393499451/ 1000e6;

drop table decimals_test;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-- Automatically generated by SQLQueryTestSuite
-- Number of queries: 40
-- Number of queries: 41


-- !query 0
Expand Down Expand Up @@ -328,8 +328,16 @@ NULL


-- !query 39
drop table decimals_test
select 26393499451/ 1000e6
-- !query 39 schema
struct<>
struct<(CAST(CAST(26393499451 AS DECIMAL(11,0)) AS DECIMAL(11,0)) / CAST(1.000E+9 AS DECIMAL(11,0))):decimal(16,11)>
-- !query 39 output
26.393499451


-- !query 40
drop table decimals_test
-- !query 40 schema
struct<>
-- !query 40 output

0 comments on commit 7c4b454

Please sign in to comment.