This is an automated email from the ASF dual-hosted git repository.
gengliangwang pushed a commit to branch branch-4.x
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/branch-4.x by this push:
new 68dae3699839 [SPARK-57169][SQL] Simplify NextDay codegen under ANSI
mode
68dae3699839 is described below
commit 68dae369983940ccd1bd896106fbad0af9889b2c
Author: Gengliang Wang <[email protected]>
AuthorDate: Mon Jun 1 09:43:08 2026 -0700
[SPARK-57169][SQL] Simplify NextDay codegen under ANSI mode
### What changes were proposed in this pull request?
Add `DateTimeExpressionUtils.getNextDateExact(int startDate, UTF8String
dayOfWeek)` and route `NextDay`'s ANSI (`failOnError = true`) eval and codegen
paths through it.
In ANSI mode the previous codegen emitted `try { ... } catch
(SparkIllegalArgumentException e) { throw e; }` -- a no-op catch that simply
rethrew the same exception. The ANSI branch now emits a single
`getNextDateExact(...)` call with no try/catch (the helper lets the
`SparkIllegalArgumentException` from `DateTimeUtils.getDayOfWeekFromString`
propagate, which is exactly the ANSI behavior). The non-ANSI branch keeps the
inline `try/catch -> isNull` form (matching the already-merged `Ma [...]
### Why are the changes needed?
Part of SPARK-56908 (umbrella). Dropping the dead try/catch wrapper (and
the two chained `DateTimeUtils` calls) in the ANSI path shrinks the generated
Java for `next_day`, helping with the JVM 64KB method / constant-pool limits,
Janino compile time, and JIT work.
### Does this PR introduce _any_ user-facing change?
No. The compiled behavior is identical; only the emitted Java source text
changes.
### How was this patch tested?
```
build/sbt "catalyst/testOnly *DateExpressionsSuite"
```
75/75 pass, including `next_day` (exercised both with and without
whole-stage codegen).
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 4.8)
Closes #56219 from gengliangwang/spark-next-day-codegen.
Authored-by: Gengliang Wang <[email protected]>
Signed-off-by: Gengliang Wang <[email protected]>
(cherry picked from commit c19056aabd5d195528f8dc5269fddc74ea48779d)
Signed-off-by: Gengliang Wang <[email protected]>
---
.../expressions/DateTimeExpressionUtils.java | 14 +++++++
.../catalyst/expressions/datetimeExpressions.scala | 46 +++++++++++-----------
2 files changed, 38 insertions(+), 22 deletions(-)
diff --git
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/expressions/DateTimeExpressionUtils.java
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/expressions/DateTimeExpressionUtils.java
index 16312cdb648a..8cde11c577d5 100644
---
a/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/expressions/DateTimeExpressionUtils.java
+++
b/sql/catalyst/src/main/java/org/apache/spark/sql/catalyst/expressions/DateTimeExpressionUtils.java
@@ -31,6 +31,7 @@ import org.apache.spark.sql.catalyst.util.TimestampFormatter;
import org.apache.spark.sql.errors.QueryExecutionErrors;
import org.apache.spark.sql.types.Decimal;
import org.apache.spark.unsafe.types.CalendarInterval;
+import org.apache.spark.unsafe.types.UTF8String;
/**
* Static helpers shared by date/time/interval expression {@code doGenCode}
@@ -165,4 +166,17 @@ public final class DateTimeExpressionUtils {
throw QueryExecutionErrors.ansiDateTimeParseError(e,
suggestedFuncOnFail);
}
}
+
+ /**
+ * Computes the first date after {@code startDate} that falls on the weekday
+ * named by {@code dayOfWeek} for {@code NextDay} (next_day) in ANSI mode
+ * ({@code failOnError = true}). The {@code SparkIllegalArgumentException}
+ * thrown by {@code DateTimeUtils.getDayOfWeekFromString} for an invalid
+ * day-of-week string propagates to the caller unchanged (in ANSI mode the
+ * caller wants exactly that exception), so no try/catch wrapper is emitted.
+ */
+ public static int getNextDateExact(int startDate, UTF8String dayOfWeek) {
+ int dow = DateTimeUtils.getDayOfWeekFromString(dayOfWeek);
+ return DateTimeUtils.getNextDateForDayOfWeek(startDate, dow);
+ }
}
diff --git
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
index 9b16a5685fb1..e7867b0ac6b4 100644
---
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
+++
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/datetimeExpressions.scala
@@ -1594,17 +1594,16 @@ case class NextDay(
override def nullable: Boolean = true
override def nullSafeEval(start: Any, dayOfW: Any): Any = {
- try {
- val dow =
DateTimeUtils.getDayOfWeekFromString(dayOfW.asInstanceOf[UTF8String])
- val sd = start.asInstanceOf[Int]
- DateTimeUtils.getNextDateForDayOfWeek(sd, dow)
- } catch {
- case e: SparkIllegalArgumentException =>
- if (failOnError) {
- throw e
- } else {
- null
- }
+ if (failOnError) {
+ DateTimeExpressionUtils.getNextDateExact(
+ start.asInstanceOf[Int], dayOfW.asInstanceOf[UTF8String])
+ } else {
+ try {
+ val dow =
DateTimeUtils.getDayOfWeekFromString(dayOfW.asInstanceOf[UTF8String])
+ DateTimeUtils.getNextDateForDayOfWeek(start.asInstanceOf[Int], dow)
+ } catch {
+ case _: SparkIllegalArgumentException => null
+ }
}
}
@@ -1615,19 +1614,22 @@ case class NextDay(
dayOfWeekTerm: String,
sd: String,
dowS: String): String = {
- val failOnErrorBranch = if (failOnError) {
- "throw e;"
+ if (failOnError) {
+ // In ANSI mode the only exception (SparkIllegalArgumentException for an
+ // invalid day-of-week) must propagate, so the previous catch merely
+ // rethrew it. Delegate to the helper and drop the no-op try/catch.
+ val utils = classOf[DateTimeExpressionUtils].getName
+ s"${ev.value} = $utils.getNextDateExact($sd, $dowS);"
} else {
- s"${ev.isNull} = true;"
+ s"""
+ |try {
+ | int $dayOfWeekTerm =
$dateTimeUtilClass.getDayOfWeekFromString($dowS);
+ | ${ev.value} = $dateTimeUtilClass.getNextDateForDayOfWeek($sd,
$dayOfWeekTerm);
+ |} catch (org.apache.spark.SparkIllegalArgumentException e) {
+ | ${ev.isNull} = true;
+ |}
+ |""".stripMargin
}
- s"""
- |try {
- | int $dayOfWeekTerm = $dateTimeUtilClass.getDayOfWeekFromString($dowS);
- | ${ev.value} = $dateTimeUtilClass.getNextDateForDayOfWeek($sd,
$dayOfWeekTerm);
- |} catch (org.apache.spark.SparkIllegalArgumentException e) {
- | $failOnErrorBranch
- |}
- |""".stripMargin
}
override protected def doGenCode(ctx: CodegenContext, ev: ExprCode):
ExprCode = {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]