From 9a15ba217ce442371db885e166f1e464d8eb9cfc Mon Sep 17 00:00:00 2001 From: Kazuaki Ishizaki Date: Wed, 19 Apr 2017 21:53:01 +0900 Subject: [PATCH 1/3] initial commit --- .../org/apache/spark/sql/types/Decimal.scala | 16 +++++++++++----- .../apache/spark/sql/types/DecimalSuite.scala | 6 ++++++ 2 files changed, 17 insertions(+), 5 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 e8f6884c025c..6c07d733424c 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 @@ -135,11 +135,17 @@ final class Decimal extends Ordered[Decimal] with Serializable { * Set this Decimal to the given BigInteger value. Will have precision 38 and scale 0. */ 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)) + this + } } /** 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 714883a4099c..93c231e30b49 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") + } } From 655e1155ee83e8c8e990e034702125e07b95e7bc Mon Sep 17 00:00:00 2001 From: Kazuaki Ishizaki Date: Thu, 20 Apr 2017 19:01:10 +0900 Subject: [PATCH 2/3] address review comment --- .../src/main/scala/org/apache/spark/sql/types/Decimal.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 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 6c07d733424c..9de0420a9d28 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,7 +132,10 @@ final class Decimal extends Ordered[Decimal] with Serializable { } /** - * Set this Decimal to the given BigInteger value. Will have precision 38 and scale 0. + * Set this Decimal to the given BigInteger value. Will have precision 38 and scale 0 + * if value is fit into long value range. Otherwise, use BigDecimal + * + * This code avoids BigDecimal object allocation as possible to improve runtime efficiency */ def set(bigintval: BigInteger): Decimal = { try { @@ -144,7 +147,6 @@ final class Decimal extends Ordered[Decimal] with Serializable { } catch { case _: ArithmeticException => set(BigDecimal(bigintval)) - this } } From 6425239bf6ffad6319e18225b6311cabd622dc54 Mon Sep 17 00:00:00 2001 From: Kazuaki Ishizaki Date: Fri, 21 Apr 2017 16:06:11 +0900 Subject: [PATCH 3/3] address review comment --- .../src/main/scala/org/apache/spark/sql/types/Decimal.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 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 9de0420a9d28..80916ee9c537 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,8 +132,8 @@ final class Decimal extends Ordered[Decimal] with Serializable { } /** - * Set this Decimal to the given BigInteger value. Will have precision 38 and scale 0 - * if value is fit into long value range. Otherwise, use BigDecimal + * 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 */