aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/catalyst/src/main/scala/org/apache/spark/sql/types/Decimal.scala20
-rw-r--r--sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala6
2 files changed, 20 insertions, 6 deletions
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/types/Decimal.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/types/Decimal.scala
index e8f6884c02..80916ee9c5 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/types/Decimal.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/types/Decimal.scala
@@ -132,14 +132,22 @@ final class Decimal extends Ordered[Decimal] with Serializable {
}
/**
- * Set this Decimal to the given BigInteger value. Will have precision 38 and scale 0.
+ * If the value is not in the range of long, convert it to BigDecimal and
+ * the precision and scale are based on the converted value.
+ *
+ * This code avoids BigDecimal object allocation as possible to improve runtime efficiency
*/
def set(bigintval: BigInteger): Decimal = {
- this.decimalVal = null
- this.longVal = bigintval.longValueExact()
- this._precision = DecimalType.MAX_PRECISION
- this._scale = 0
- this
+ try {
+ this.decimalVal = null
+ this.longVal = bigintval.longValueExact()
+ this._precision = DecimalType.MAX_PRECISION
+ this._scale = 0
+ this
+ } catch {
+ case _: ArithmeticException =>
+ set(BigDecimal(bigintval))
+ }
}
/**
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala
index 714883a409..93c231e30b 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala
@@ -212,4 +212,10 @@ class DecimalSuite extends SparkFunSuite with PrivateMethodTester {
}
}
}
+
+ test("SPARK-20341: support BigInt's value does not fit in long value range") {
+ val bigInt = scala.math.BigInt("9223372036854775808")
+ val decimal = Decimal.apply(bigInt)
+ assert(decimal.toJavaBigDecimal.unscaledValue.toString === "9223372036854775808")
+ }
}