jiangxt2 opened a new pull request, #58028:
URL: https://github.com/apache/spark/pull/58028

   ### What changes were proposed in this pull request?
   
   When casting a large Double or Float value to Timestamp, the seconds value 
is multiplied by MICROS_PER_SECOND and then converted to a Long. If the product 
falls outside the Long range, the JVM saturates the conversion to 
Long.MAX_VALUE or Long.MIN_VALUE, so an out-of-range input silently produces an 
extreme but valid-looking timestamp instead of NULL. This PR fixes the silent 
overflow clamping for Double and Float to Timestamp casts in non-ANSI mode.
   
   The fix checks the microsecond product against the Long bounds before the 
conversion, in both the interpreted and codegen paths. The negative bound keeps 
Long.MinValue inclusive, and the positive bound treats the rounded 2^63 
boundary as overflow because Long.MaxValue is not exactly representable as a 
Double. Out-of-range values now return NULL in non-ANSI mode. ANSI mode keeps 
throwing CAST_OVERFLOW; the ANSI helper is also aligned to reject the exact 
2^63 boundary, which previously slipped through the existing bounds check and 
was silently clamped to Long.MAX_VALUE. NaN and Infinity keep their existing 
behavior: NULL in non-ANSI mode and the datetime invalid-input exception in 
ANSI mode. Decimal to Timestamp conversion is unchanged.
   
   ### Why are the changes needed?
   
   The silent clamping is a correctness bug: `CAST(1e20 AS TIMESTAMP)` 
currently returns `+294247-01-10 04:00:54.775807` (the clamped Long.MAX_VALUE) 
instead of NULL, hiding the fact that the input is out of range. See 
[SPARK-58235](https://issues.apache.org/jira/browse/SPARK-58235).
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. Under non-ANSI mode, casting an overflowing Double or Float to 
Timestamp now returns NULL instead of a wrong timestamp produced by numeric 
overflow. The SQL migration guide is updated accordingly. ANSI mode behavior is 
unchanged except that the exact 2^63 boundary now throws CAST_OVERFLOW as the 
documented contract requires, instead of silently clamping to Long.MAX_VALUE.
   
   ### How was this patch tested?
   
   Added tests to CastWithAnsiOffSuite and CastWithAnsiOnSuite covering 
positive and negative overflow, the Long bounds (including the exact -2^63 
boundary and the rounded 2^63 boundary), NaN, Infinity, Double, Float and 
normal values. Verified results: CastWithAnsiOffSuite 138 tests passed, 
CastWithAnsiOnSuite 136 tests passed, SQLQueryTestSuite cast.sql 6 tests 
passed, full catalyst/test 10,559 ScalaTest tests and 10,938 JUnit tests passed 
with 5 ignored, and git diff --check passed. The Spark PR pre-check reported 0 
failures and 1 warning (a mechanical golden-file notice; no golden update is 
needed since no finite overflow input changes existing test output). The full 
sql/test module could not be completed locally: the Python planner worker and 
the Ivy dependency resolution are blocked in the current environment, which is 
unrelated to this change.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Codex and Claude AI
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to