Skip to content

Commit d14ad06

Browse files
viiryaIsaac
andcommitted
Keep plain notation for ordinary values in the error message and assert it
Co-authored-by: Isaac <no-reply@databricks.com>
1 parent 412e98b commit d14ad06

5 files changed

Lines changed: 30 additions & 14 deletions

File tree

‎sql/api/src/main/scala/org/apache/spark/sql/errors/DataTypeErrors.scala‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ import org.apache.spark.unsafe.types.UTF8String
3131
* into [[CompilationErrors]].
3232
*/
3333
private[sql] object DataTypeErrors extends DataTypeErrorsBase {
34+
// Above this many trailing zeros, a decimal value in an error message is rendered in
35+
// scientific notation instead of plain notation.
36+
private val MAX_PLAIN_STRING_TRAILING_ZEROS = 1000
37+
3438
def unsupportedOperationExceptionError(): SparkUnsupportedOperationException = {
3539
new SparkUnsupportedOperationException("_LEGACY_ERROR_TEMP_2225")
3640
}
@@ -210,9 +214,10 @@ private[sql] object DataTypeErrors extends DataTypeErrorsBase {
210214
new SparkArithmeticException(
211215
errorClass = "NUMERIC_VALUE_OUT_OF_RANGE.WITH_SUGGESTION",
212216
messageParameters = Map(
213-
// A negative scale (legacy mode only) can make the plain string arbitrarily long,
214-
// e.g. 1E+2147483647.
215-
"value" -> (if (value.scale < 0) value.toString else value.toPlainString),
217+
// A huge negative scale (legacy mode only) makes the plain string too long to build,
218+
// e.g. for 1E+2147483647.
219+
"value" -> (if (value.scale < -MAX_PLAIN_STRING_TRAILING_ZEROS) value.toString
220+
else value.toPlainString),
216221
"precision" -> decimalPrecision.toString,
217222
"scale" -> decimalScale.toString,
218223
"config" -> toSQLConf("spark.sql.ansi.enabled")),

‎sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/expressions/CastUtils.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.spark.sql.catalyst.expressions;
1919

2020
import org.apache.spark.QueryContext;
21+
import org.apache.spark.sql.errors.DataTypeErrors;
2122
import org.apache.spark.sql.errors.QueryExecutionErrors;
2223
import org.apache.spark.sql.types.DataType;
2324
import org.apache.spark.sql.types.DataTypes;
@@ -107,7 +108,7 @@ public static short doubleToShortExact(double v) {
107108
public static Decimal changePrecisionExact(
108109
Decimal d, int precision, int scale, QueryContext context) {
109110
if (d.changePrecision(precision, scale)) return d;
110-
throw QueryExecutionErrors.cannotChangeDecimalPrecisionError(d, precision, scale, context);
111+
throw DataTypeErrors.cannotChangeDecimalPrecisionError(d, precision, scale, context);
111112
}
112113

113114
public static Decimal changePrecisionOrNull(Decimal d, int precision, int scale) {

‎sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,6 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
103103
)
104104
}
105105

106-
def cannotChangeDecimalPrecisionError(
107-
value: Decimal,
108-
decimalPrecision: Int,
109-
decimalScale: Int,
110-
context: QueryContext = null): ArithmeticException = {
111-
DataTypeErrors.cannotChangeDecimalPrecisionError(
112-
value, decimalPrecision, decimalScale, context)
113-
}
114-
115106
def invalidInputSyntaxForBooleanError(
116107
s: UTF8String,
117108
context: QueryContext): SparkRuntimeException = {

‎sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastWithAnsiOnSuite.scala‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,25 @@ class CastWithAnsiOnSuite extends CastSuiteBase with QueryErrorsBase {
489489
"cannot be represented as Decimal(10, 2)")
490490
}
491491
checkEvaluation(cast("0e2147483647", DecimalType(10, 2)), Decimal("0.00"))
492+
493+
// The value is shown in plain notation unless its scale is hugely negative.
494+
Seq("1e2147483647" -> "1E+2147483647", "1e40" -> ("1" + "0" * 40)).foreach {
495+
case (str, value) =>
496+
if (!isTryCast) {
497+
checkError(
498+
exception = intercept[SparkArithmeticException](
499+
cast(str, DecimalType(10, 2)).eval()),
500+
condition = "NUMERIC_VALUE_OUT_OF_RANGE.WITH_SUGGESTION",
501+
parameters = Map(
502+
"value" -> value,
503+
"precision" -> "10",
504+
"scale" -> "2",
505+
"config" -> """"spark.sql.ansi.enabled""""),
506+
queryContext = Array(ExpectedContext(fragment = "", start = -1, stop = -1)))
507+
} else {
508+
checkEvaluation(cast(str, DecimalType(10, 2)), null)
509+
}
510+
}
492511
}
493512
}
494513

‎sql/catalyst/src/test/scala/org/apache/spark/sql/types/DecimalSuite.scala‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ class DecimalSuite extends SparkFunSuite with PrivateMethodTester with SQLHelper
494494
}
495495

496496
test("SPARK-60119: changePrecision with a source scale far from the target scale") {
497-
// A value below 0.1 ulp of the target scale rounds to 0 or +/-1 ulp depending only on its
497+
// A value below 0.01 ulp of the target scale rounds to 0 or +/-1 ulp depending only on its
498498
// sign and the rounding mode, so it must round like a small value of the same sign.
499499
Seq("1e-2147483647", "-1e-2147483647", "9.99e-100000000", "-1e-100000000",
500500
"0e-2147483647").foreach { str =>

0 commit comments

Comments
 (0)