Skip to content

Conversation

@vinodkc
Copy link
Contributor

@vinodkc vinodkc commented Dec 7, 2025

What changes were proposed in this pull request?

Implemented whole-stage codegen for TIME conversion functions (IntegralToTimeBase, TimeFromSeconds, TimeToSeconds) by removing CodegenFallback

Why are the changes needed?

Performance: CodegenFallback is 10-50x slower than generated code
Pattern consistency: Follows existing Spark patterns (IntegralToTimestampBase)

Does this PR introduce any user-facing change?

No. performance optimization with identical results.

How was this patch tested?

All existing tests pass
Generated code inspection confirms optimizations

Was this patch authored or co-authored using generative AI tooling?

No

@github-actions github-actions bot added the SQL label Dec 7, 2025
@vinodkc vinodkc changed the title [SPARK-54442][SQL][FOLLOWUP]Add codegen for TIME numeric conversion functions [SPARK-54442][SQL][FOLLOWUP] Add codegen for TIME numeric conversion functions Dec 7, 2025
@HyukjinKwon
Copy link
Member

cc @cloud-fan


override def replacement: Expression = StaticInvoke(
classOf[DateTimeUtils.type],
DecimalType(14, 6),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DecimalType(14, 6),
dataType,

to avoid duplication

case e: DateTimeException =>
throw QueryExecutionErrors.ansiDateTimeArgumentOutOfRange(e)
case e: ArithmeticException =>
val wrapped = new DateTimeException(s"Overflow in TIME conversion: ${e.getMessage}", e)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val wrapped = new DateTimeException(s"Overflow in TIME conversion: ${e.getMessage}", e)
val wrapped = new DateTimeException(s"Overflow in TIME conversion", e)

do not duplicate the info in the causedBy error

* @param seconds Seconds (0 to 86399.999999)
* @return Nanoseconds since midnight
*/
def timeFromSeconds(seconds: Float): Long = withTimeConversionErrorHandling {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need the float version? the double version can cover it.

if (seconds.isNaN || seconds.isInfinite) {
throw new DateTimeException("Cannot convert NaN or Infinite value to TIME")
}
(seconds * NANOS_PER_SECOND).toLong
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to consider overflow here when calling toLong?

* @param nanos Nanoseconds since midnight
* @return Seconds as Decimal(14, 6)
*/
def timeToSeconds(nanos: Long): Decimal = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall we wrap with withTimeConversionErrorHandling?

SELECT time_from_seconds(-1);
SELECT time_from_seconds(86400);
SELECT time_from_seconds(90000);
SELECT time_from_seconds(-1); -- invalid: negative → exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SELECT time_from_seconds(-1); -- invalid: negative exception
SELECT time_from_seconds(-1); -- invalid: negative -> exception

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's avoid unicode

"errorClass" : "DATETIME_FIELD_OUT_OF_BOUNDS.WITH_SUGGESTION",
"sqlState" : "22023",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the full message? why do we mention ansi conf?

@vinodkc vinodkc force-pushed the br_time_numeric_conversion_followup branch 2 times, most recently from 907abae to f921fcf Compare December 11, 2025 06:28
@vinodkc vinodkc force-pushed the br_time_numeric_conversion_followup branch from f921fcf to ec99c46 Compare December 11, 2025 06:41
if (seconds.isNaN || seconds.isInfinite) {
throw new DateTimeException("Cannot convert NaN or Infinite value to TIME")
}
(seconds * NANOS_PER_SECOND).toLong
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to consider overflow here when calling toLong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants