Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added more informations for error message & regen
  • Loading branch information
itholic committed Oct 2, 2024
commit 260145e4479f9d89a2e5f2a3913bf220df1230df
Original file line number Diff line number Diff line change
Expand Up @@ -1085,7 +1085,7 @@
},
"DATE_TIME_FIELD_OUT_OF_BOUNDS" : {
"message" : [
"Invalid value for datetime field. If necessary set <ansiConfig> to false to bypass this error."
"The value '<badValue>' you entered for <unit> is not valid. Please provide a value between <range>. To disable strict validation, you can turn off ANSI mode by setting <ansiConfig> to false."
Copy link
Contributor Author

Choose a reason for hiding this comment

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

cc @srielau updated the error message including more parameters such as unit, range and badValue

],
"sqlState" : "22008"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,38 @@ private[sql] object QueryExecutionErrors extends QueryErrorsBase with ExecutionE
}

def ansiDateTimeError(e: Exception): SparkDateTimeException = {
def extractDateTimeErrorInfo(e: Exception): (String, String, String) = {
val errorMessage = e.getMessage

val pattern = "Invalid value for ([A-Za-z]+) \\(valid values (.+)\\): (.+)".r

errorMessage match {
Copy link
Contributor

Choose a reason for hiding this comment

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

@srielau If I understood @MaxGekk we want to get away from this message creation in the specific calls of the error, but actually keep all the info in error-conditions.json. This will make it really hard to sync with other APIs, especially as we are expanding these endless number of exception messages that we can get from the java library. Also, since this is external dependancy, who is to guarantee that this message format will stay the same when java updates.

Copy link
Contributor

Choose a reason for hiding this comment

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

The guarantee is the tests we write against them. I'm not opposed to having catch all for the "unforeseen".
Simply put: We should be able to rip out Java and replace it with C and messages should stay the same.

Copy link
Contributor

Choose a reason for hiding this comment

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

Agree, but are we really going for this over getting as much information as we can provide to the user? For example there is a specific exception that is returning leap year error, but we will just say this should be in range. If I got a message like this, tbh I would be confused as to why it is not working when my value actually is in 1...28/31 range (29th february). We could do this changing for errors that we know for sure how they behave, but for all others, I lean to leaving the java message, as it provides sufficient info on why it is failing and end goal should be providing user with sufficient info to fix the error imo.

case pattern(field, range, badValue) =>
val unit = field match {
case "Year" => "YEAR"
case "MonthOfYear" => "MONTH"
case "DayOfMonth" => "DAY"
case "Hour" => "HOUR"
case "Minute" => "MINUTE"
case "Second" => "SECOND"
case _ => field
}
(unit, range, badValue)
}
Copy link
Member

Choose a reason for hiding this comment

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

@itholic Do you expect that it should match to both the cases above. What if not? I would add a default case.

Copy link
Member

Choose a reason for hiding this comment

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

For example, toInstant can raise:

        if (seconds < MIN_SECOND || seconds > MAX_SECOND) {
            throw new DateTimeException("Instant exceeds minimum or maximum instant");
        }

How does your code handles this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point.

I think DATETIME_FIELD_OUT_OF_BOUNDS is not very proper error class to cover the example case, so let me leave the existing _LEGACY_ERROR_TEMP_2000 as it is for default case.

We may need introduce several new error classes to cover the all potential exception cases along with more test cases in a separate ticket.

}
val (unit, range, badValue) = extractDateTimeErrorInfo(e)
new SparkDateTimeException(
errorClass = "DATE_TIME_FIELD_OUT_OF_BOUNDS",
messageParameters = Map(
"ansiConfig" -> toSQLConf(SQLConf.ANSI_ENABLED.key)),
"ansiConfig" -> toSQLConf(SQLConf.ANSI_ENABLED.key),
"unit" -> unit,
"range" -> range,
"badValue" -> badValue
),
context = Array.empty,
summary = "",
cause = Some(e))
cause = Some(e)
)
}

def ansiIllegalArgumentError(): SparkException = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1145,15 +1145,30 @@ class DateExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
checkErrorInExpression[SparkDateTimeException](
MakeDate(Literal(Int.MaxValue), Literal(13), Literal(19)),
"DATE_TIME_FIELD_OUT_OF_BOUNDS",
Map("ansiConfig" -> "\"spark.sql.ansi.enabled\""))
Map(
"ansiConfig" -> "\"spark.sql.ansi.enabled\"",
"unit" -> "YEAR",
"range" -> "-999999999 - 999999999",
"badValue" -> "2147483647")
)
checkErrorInExpression[SparkDateTimeException](
MakeDate(Literal(2019), Literal(13), Literal(19)),
"DATE_TIME_FIELD_OUT_OF_BOUNDS",
Map("ansiConfig" -> "\"spark.sql.ansi.enabled\""))
Map(
"ansiConfig" -> "\"spark.sql.ansi.enabled\"",
"unit" -> "MONTH",
"range" -> "1 - 12",
"badValue" -> "13")
)
checkErrorInExpression[SparkDateTimeException](
MakeDate(Literal(2019), Literal(7), Literal(32)),
"DATE_TIME_FIELD_OUT_OF_BOUNDS",
Map("ansiConfig" -> "\"spark.sql.ansi.enabled\""))
Map(
"ansiConfig" -> "\"spark.sql.ansi.enabled\"",
"unit" -> "DAY",
"range" -> "1 - 28/31",
"badValue" -> "32")
)
}

// non-ansi test
Expand Down
10 changes: 8 additions & 2 deletions sql/core/src/test/resources/sql-tests/results/ansi/date.sql.out
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "13",
"range" : "1 - 12",
"unit" : "MONTH"
}
}

Expand All @@ -71,7 +74,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "33",
"range" : "1 - 28/31",
"unit" : "DAY"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "61",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand Down Expand Up @@ -188,7 +191,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "99",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand All @@ -203,7 +209,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "999",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,12 @@ select make_date(2013, 2, 30)
-- !query schema
struct<>
-- !query output
org.apache.spark.SparkDateTimeException
org.apache.spark.SparkException
{
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"errorClass" : "INTERNAL_ERROR",
"sqlState" : "XX000",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"message" : "The Spark SQL phase optimization failed with an internal error. You hit a bug in Spark or the Spark plugins you use. Please, report this bug to the corresponding communities or vendors, and provide the full stack trace."
}
}

Expand All @@ -705,7 +705,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "13",
"range" : "1 - 12",
"unit" : "MONTH"
}
}

Expand All @@ -720,7 +723,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "-1",
"range" : "1 - 28/31",
"unit" : "DAY"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "61",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand Down Expand Up @@ -188,7 +191,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "99",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand All @@ -203,7 +209,10 @@ org.apache.spark.SparkDateTimeException
"errorClass" : "DATE_TIME_FIELD_OUT_OF_BOUNDS",
"sqlState" : "22008",
"messageParameters" : {
"ansiConfig" : "\"spark.sql.ansi.enabled\""
"ansiConfig" : "\"spark.sql.ansi.enabled\"",
"badValue" : "999",
"range" : "0 - 59",
"unit" : "SecondOfMinute"
}
}

Expand Down