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 4b1462b23e3a..cb468c523f36 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 @@ -602,7 +602,8 @@ object Decimal { val bigDecimal = stringToJavaBigDecimal(str) // We fast fail because constructing a very large JavaBigDecimal to Decimal is very slow. // For example: Decimal("6.0790316E+25569151") - if (numDigitsInIntegralPart(bigDecimal) > DecimalType.MAX_PRECISION) { + if (numDigitsInIntegralPart(bigDecimal) > DecimalType.MAX_PRECISION && + !SQLConf.get.allowNegativeScaleOfDecimalEnabled) { null } else { Decimal(bigDecimal) @@ -618,7 +619,8 @@ object Decimal { val bigDecimal = stringToJavaBigDecimal(str) // We fast fail because constructing a very large JavaBigDecimal to Decimal is very slow. // For example: Decimal("6.0790316E+25569151") - if (numDigitsInIntegralPart(bigDecimal) > DecimalType.MAX_PRECISION) { + if (numDigitsInIntegralPart(bigDecimal) > DecimalType.MAX_PRECISION && + !SQLConf.get.allowNegativeScaleOfDecimalEnabled) { throw QueryExecutionErrors.outOfDecimalTypeRangeError(str) } else { Decimal(bigDecimal) 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 57449f5b6dc6..5433c561a037 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 @@ -299,4 +299,19 @@ class DecimalSuite extends SparkFunSuite with PrivateMethodTester with SQLHelper assert(Decimal.fromStringANSI(UTF8String.fromString(string)) === Decimal(string)) } } + + test("SPARK-37451: Performance improvement regressed String to Decimal cast") { + val values = Array("7.836725755512218E38") + for (string <- values) { + assert(Decimal.fromString(UTF8String.fromString(string)) === null) + intercept[ArithmeticException](Decimal.fromStringANSI(UTF8String.fromString(string))) + } + + withSQLConf(SQLConf.LEGACY_ALLOW_NEGATIVE_SCALE_OF_DECIMAL_ENABLED.key -> "true") { + for (string <- values) { + assert(Decimal.fromString(UTF8String.fromString(string)) === Decimal(string)) + assert(Decimal.fromStringANSI(UTF8String.fromString(string)) === Decimal(string)) + } + } + } }