Skip to content

Commit fc5b902

Browse files
MaxGekkcloud-fan
authored andcommitted
[SPARK-31727][SQL] Fix error message of casting timestamp to int in ANSI non-codegen mode
### What changes were proposed in this pull request? Change timestamp casting to int in ANSI and non-codegen mode, and make the error message consistent to the error messages in the codegen mode. In particular, casting to int is implemented in the same way as casting to short and byte. ### Why are the changes needed? 1. The error message in the non-codegen mode is diversed from the error message in the codegen mode. 2. The error message contains intermediate results that could confuse. ### Does this PR introduce _any_ user-facing change? Yes. Before the changes, the error message of casting timestamp to int contains intermediate result but after the changes it contains the input values which causes arithmetic overflow. ### How was this patch tested? By running the modified test suite `AnsiCastSuite`. Closes apache#28549 from MaxGekk/fix-error-msg-cast-timestamp. Authored-by: Max Gekk <[email protected]> Signed-off-by: Wenchen Fan <[email protected]>
1 parent 64795f9 commit fc5b902

File tree

2 files changed

+12
-7
lines changed
  • sql/catalyst/src
    • main/scala/org/apache/spark/sql/catalyst/expressions
    • test/scala/org/apache/spark/sql/catalyst/expressions

2 files changed

+12
-7
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/Cast.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,14 @@ abstract class CastBase extends UnaryExpression with TimeZoneAwareExpression wit
511511
case DateType =>
512512
buildCast[Int](_, d => null)
513513
case TimestampType if ansiEnabled =>
514-
buildCast[Long](_, t => LongExactNumeric.toInt(timestampToLong(t)))
514+
buildCast[Long](_, t => {
515+
val longValue = timestampToLong(t)
516+
if (longValue == longValue.toInt) {
517+
longValue.toInt
518+
} else {
519+
throw new ArithmeticException(s"Casting $t to int causes overflow")
520+
}
521+
})
515522
case TimestampType =>
516523
buildCast[Long](_, t => timestampToLong(t).toInt)
517524
case x: NumericType if ansiEnabled =>

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala

+4-6
Original file line numberDiff line numberDiff line change
@@ -1355,16 +1355,14 @@ class AnsiCastSuite extends CastSuiteBase {
13551355
}
13561356

13571357
test("cast a timestamp before the epoch 1970-01-01 00:00:00Z") {
1358+
def errMsg(t: String): String = s"Casting -2198208303900000 to $t causes overflow"
13581359
withDefaultTimeZone(UTC) {
13591360
val negativeTs = Timestamp.valueOf("1900-05-05 18:34:56.1")
13601361
assert(negativeTs.getTime < 0)
13611362
val expectedSecs = Math.floorDiv(negativeTs.getTime, MILLIS_PER_SECOND)
1362-
checkExceptionInExpression[ArithmeticException](
1363-
cast(negativeTs, ByteType), "to byte causes overflow")
1364-
checkExceptionInExpression[ArithmeticException](
1365-
cast(negativeTs, ShortType), "to short causes overflow")
1366-
checkExceptionInExpression[ArithmeticException](
1367-
cast(negativeTs, IntegerType), "to int causes overflow")
1363+
checkExceptionInExpression[ArithmeticException](cast(negativeTs, ByteType), errMsg("byte"))
1364+
checkExceptionInExpression[ArithmeticException](cast(negativeTs, ShortType), errMsg("short"))
1365+
checkExceptionInExpression[ArithmeticException](cast(negativeTs, IntegerType), errMsg("int"))
13681366
checkEvaluation(cast(negativeTs, LongType), expectedSecs)
13691367
}
13701368
}

0 commit comments

Comments
 (0)