Skip to content

Commit

Permalink
[SPARK-47977] DateTimeUtils.timestampDiff and DateTimeUtils.timestamp…
Browse files Browse the repository at this point in the history
…Add should not throw INTERNAL_ERROR exception

### What changes were proposed in this pull request?

Convert `INTERNAL_ERROR` for `timestampAdd` and `timestampDiff` to error with class. Reusing `INVALID_PARAMETER_VALUE.DATETIME_UNIT` used when parsing expressions.

The change is needed since `timestampDiff` and `timestampAdd` expressions could be constructed without going through parser - e.g. PySpark creates `timestampDiff` through PythonSQLUtils.

### Why are the changes needed?

Correct classification of errors

### Does this PR introduce _any_ user-facing change?

No

### How was this patch tested?

Existing unit tests updated with new error class

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

No

Closes #46210 from vitaliili-db/SPARK-47977.

Authored-by: Vitalii Li <[email protected]>
Signed-off-by: Gengliang Wang <[email protected]>
  • Loading branch information
vitaliili-db authored and gengliangwang committed Jun 3, 2024
1 parent 5d71ef0 commit 5baaa61
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ object DateTimeUtils extends SparkDateTimeUtils {
}
} catch {
case _: scala.MatchError =>
throw SparkException.internalError(s"Got the unexpected unit '$unit'.")
throw QueryExecutionErrors.invalidDatetimeUnitError("TIMESTAMPADD", unit)
case _: ArithmeticException | _: DateTimeException =>
throw QueryExecutionErrors.timestampAddOverflowError(micros, quantity, unit)
case e: Throwable =>
Expand Down Expand Up @@ -736,7 +736,7 @@ object DateTimeUtils extends SparkDateTimeUtils {
val endLocalTs = getLocalDateTime(endTs, zoneId)
timestampDiffMap(unitInUpperCase)(startLocalTs, endLocalTs)
} else {
throw SparkException.internalError(s"Got the unexpected unit '$unit'.")
throw QueryExecutionErrors.invalidDatetimeUnitError("TIMESTAMPDIFF", unit)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2782,4 +2782,15 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
)
)
}

def invalidDatetimeUnitError(
functionName: String,
invalidValue: String): Throwable = {
new SparkIllegalArgumentException(
errorClass = "INVALID_PARAMETER_VALUE.DATETIME_UNIT",
messageParameters = Map(
"functionName" -> toSQLId(functionName),
"parameter" -> toSQLId("unit"),
"invalidValue" -> s"'$invalidValue'"))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit
import org.scalatest.matchers.must.Matchers
import org.scalatest.matchers.should.Matchers._

import org.apache.spark.{SparkException, SparkFunSuite, SparkIllegalArgumentException}
import org.apache.spark.{SparkFunSuite, SparkIllegalArgumentException}
import org.apache.spark.sql.catalyst.plans.SQLHelper
import org.apache.spark.sql.catalyst.util.DateTimeConstants._
import org.apache.spark.sql.catalyst.util.DateTimeTestUtils._
Expand Down Expand Up @@ -1040,11 +1040,14 @@ class DateTimeUtilsSuite extends SparkFunSuite with Matchers with SQLHelper {
}

checkError(
exception = intercept[SparkException] {
exception = intercept[SparkIllegalArgumentException] {
timestampAdd("SECS", 1, date(1969, 1, 1, 0, 0, 0, 1, getZoneId("UTC")), getZoneId("UTC"))
},
errorClass = "INTERNAL_ERROR",
parameters = Map("message" -> "Got the unexpected unit 'SECS'."))
errorClass = "INVALID_PARAMETER_VALUE.DATETIME_UNIT",
parameters = Map(
"functionName" -> "`TIMESTAMPADD`",
"parameter" -> "`unit`",
"invalidValue" -> "'SECS'"))
}

test("SPARK-38284: difference between two timestamps in units") {
Expand Down Expand Up @@ -1092,14 +1095,17 @@ class DateTimeUtilsSuite extends SparkFunSuite with Matchers with SQLHelper {
}

checkError(
exception = intercept[SparkException] {
exception = intercept[SparkIllegalArgumentException] {
timestampDiff(
"SECS",
date(1969, 1, 1, 0, 0, 0, 1, getZoneId("UTC")),
date(2022, 1, 1, 0, 0, 0, 1, getZoneId("UTC")),
getZoneId("UTC"))
},
errorClass = "INTERNAL_ERROR",
parameters = Map("message" -> "Got the unexpected unit 'SECS'."))
errorClass = "INVALID_PARAMETER_VALUE.DATETIME_UNIT",
parameters =
Map("functionName" -> "`TIMESTAMPDIFF`",
"parameter" -> "`unit`",
"invalidValue" -> "'SECS'"))
}
}

0 comments on commit 5baaa61

Please sign in to comment.