This is an automated email from the ASF dual-hosted git repository.

yao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new a7990f30b2e2 [SPARK-55755][SQL][TESTS] Handle null ArithmeticException 
message on JDK 25
a7990f30b2e2 is described below

commit a7990f30b2e22e30278d3cc09999d2044223c880
Author: Kent Yao <[email protected]>
AuthorDate: Sat Feb 28 23:10:43 2026 +0800

    [SPARK-55755][SQL][TESTS] Handle null ArithmeticException message on JDK 25
    
    ### What changes were proposed in this pull request?
    
    On JDK 25, `Math.multiplyExact`/`Math.addExact` may throw 
`ArithmeticException` without a message (null instead of `"long overflow"`). 
This causes `NullPointerException` in tests that check the raw exception 
message via `.getMessage.contains(...)`.
    
    This PR:
    1. **`MathUtils.withOverflow`**: Provides a fallback message `"Overflow"` 
when the raw JDK exception message is null, preventing null propagation into 
Spark error conditions (both interpreted and codegen paths).
    2. **Test assertions**: Makes raw `ArithmeticException` message checks 
null-safe across:
       - `DateExpressionsSuite` (line 1825)
       - `CatalystTypeConvertersSuite` (line 305)
       - `DateTimeUtilsSuite` (line 835)
       - `IntervalUtilsSuite` (line 593)
       - `TimestampFormatterSuite` (lines 451, 453)
    
    ### Why are the changes needed?
    
    The JDK 25 scheduled CI build fails with:
    ```
    java.lang.NullPointerException: Cannot invoke 
"String.contains(java.lang.CharSequence)" because 
"$org_scalatest_assert_macro_left" is null
      at DateExpressionsSuite.scala:1825
    ```
    
    See: 
https://github.com/apache/spark/actions/runs/22513372344/job/65226962993
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Existing tests pass on JDK 17. The `MathUtils.withOverflow` fix ensures 
non-null messages regardless of JDK version.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Yes, co-authored with GitHub Copilot.
    
    Closes #54553 from yaooqinn/fix-jdk25-long-overflow.
    
    Authored-by: Kent Yao <[email protected]>
    Signed-off-by: Kent Yao <[email protected]>
---
 .../main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala  | 7 +++++--
 .../apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala    | 3 ++-
 .../spark/sql/catalyst/expressions/DateExpressionsSuite.scala      | 3 ++-
 .../org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala    | 3 ++-
 .../org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala    | 3 ++-
 .../apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala   | 5 +++--
 6 files changed, 16 insertions(+), 8 deletions(-)

diff --git 
a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala 
b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala
index b113bccc74df..9f8ee7ae9319 100644
--- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala
+++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/util/MathUtils.scala
@@ -94,7 +94,9 @@ object MathUtils {
       f
     } catch {
       case e: ArithmeticException =>
-        throw ExecutionErrors.arithmeticOverflowError(e.getMessage, hint, 
context)
+        // On JDK 25+, Math.*Exact may throw ArithmeticException without a 
message
+        val message = if (e.getMessage != null) e.getMessage else "Overflow"
+        throw ExecutionErrors.arithmeticOverflowError(message, hint, context)
     }
   }
 
@@ -103,7 +105,8 @@ object MathUtils {
        |try {
        |  $evalCode
        |} catch (ArithmeticException e) {
-       |  throw QueryExecutionErrors.arithmeticOverflowError(e.getMessage(), 
"", $context);
+       |  String msg = e.getMessage() != null ? e.getMessage() : "Overflow";
+       |  throw QueryExecutionErrors.arithmeticOverflowError(msg, "", 
$context);
        |}
        |""".stripMargin
   }
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
index 1b46825b3414..75ca908a941b 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/CatalystTypeConvertersSuite.scala
@@ -302,7 +302,8 @@ class CatalystTypeConvertersSuite extends SparkFunSuite 
with SQLHelper {
     val errMsg = intercept[ArithmeticException] {
       IntervalUtils.durationToMicros(Duration.ofSeconds(Long.MaxValue, 
Long.MaxValue))
     }.getMessage
-    assert(errMsg.contains("long overflow"))
+    // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a 
message
+    assert(errMsg == null || errMsg.contains("long overflow"))
   }
 
   test("SPARK-35726: Truncate java.time.Duration by fields of day-time 
interval type") {
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
index 4e942b8b3e51..dede06bdc4b6 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/DateExpressionsSuite.scala
@@ -1822,7 +1822,8 @@ class DateExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
             null)
         }.getCause
         assert(e.isInstanceOf[ArithmeticException])
-        assert(e.getMessage.contains("long overflow"))
+        // On JDK 25+, Math.multiplyExact may throw ArithmeticException 
without a message
+        assert(e.getMessage == null || e.getMessage.contains("long overflow"))
 
         checkEvaluation(
           TimestampAddInterval(
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
index b5b69a834037..e7f29f547fc4 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/DateTimeUtilsSuite.scala
@@ -832,7 +832,8 @@ class DateTimeUtilsSuite extends SparkFunSuite with 
Matchers with SQLHelper {
       val msg = intercept[ArithmeticException] {
         DateTimeUtils.localDateTimeToMicros(dt)
       }.getMessage
-      assert(msg == "long overflow")
+      // On JDK 25+, Math.multiplyExact may throw ArithmeticException without 
a message
+      assert(msg == null || msg == "long overflow")
     }
   }
 
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala
index a87d599711cf..c8a8a0c1444a 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/IntervalUtilsSuite.scala
@@ -590,7 +590,8 @@ class IntervalUtilsSuite extends SparkFunSuite with 
SQLHelper {
     val errMsg = intercept[ArithmeticException] {
       durationToMicros(Duration.ofDays(106751991 + 1))
     }.getMessage
-    assert(errMsg.contains("long overflow"))
+    // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a 
message
+    assert(errMsg == null || errMsg.contains("long overflow"))
   }
 
   test("SPARK-34615: period to months") {
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala
index 558d7eda78b4..b1f6fefc2735 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/util/TimestampFormatterSuite.scala
@@ -448,9 +448,10 @@ class TimestampFormatterSuite extends 
DatetimeFormatterSuite {
     assert(formatter.parse("294247") === date(294247))
     assert(formatter.parse("-290307") === date(-290307))
     val e1 = intercept[ArithmeticException](formatter.parse("294248"))
-    assert(e1.getMessage === "long overflow")
+    // On JDK 25+, Math.multiplyExact may throw ArithmeticException without a 
message
+    assert(e1.getMessage == null || e1.getMessage === "long overflow")
     val e2 = intercept[ArithmeticException](formatter.parse("-290308"))
-    assert(e2.getMessage === "long overflow")
+    assert(e2.getMessage == null || e2.getMessage === "long overflow")
   }
 
   test("SPARK-36418: default parsing w/o pattern") {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to