Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
94ebcae
[SPARK-39349] Add checkError()
srielau May 26, 2022
a167d04
Convert more tests
srielau Jun 2, 2022
8a0bba1
QueryCompilationErrors
srielau Jun 2, 2022
1074063
Fix review comment
srielau Jun 3, 2022
5de5082
Fix EncoderResolutionSuite
srielau Jun 3, 2022
561a15f
Update core/src/main/java/org/apache/spark/SparkThrowable.java
srielau Jun 6, 2022
811201f
Update core/src/main/scala/org/apache/spark/SparkException.scala
srielau Jun 6, 2022
5c75aa5
Update core/src/main/scala/org/apache/spark/SparkException.scala
srielau Jun 6, 2022
b09a962
Update core/src/main/java/org/apache/spark/SparkThrowable.java
srielau Jun 6, 2022
1ed0943
Update core/src/test/scala/org/apache/spark/SparkFunSuite.scala
gengliangwang Jun 6, 2022
7ce6b37
Update core/src/test/scala/org/apache/spark/SparkFunSuite.scala
gengliangwang Jun 6, 2022
313fbe2
Remove clutter from outofmemoryerror
srielau Jun 6, 2022
53ed4c8
Update core/src/main/java/org/apache/spark/SparkThrowable.java
srielau Jun 7, 2022
c266b85
Update core/src/main/resources/error/error-classes.json
srielau Jun 7, 2022
a48ee85
Update core/src/test/scala/org/apache/spark/SparkFunSuite.scala
srielau Jun 7, 2022
080c7ed
Update core/src/test/scala/org/apache/spark/SparkFunSuite.scala
srielau Jun 7, 2022
f4f7b0d
Merge branch 'master' into textless-error-check
srielau Jun 7, 2022
8a2faea
Address comments by Wenchen
srielau Jun 7, 2022
7d2f53e
Update core/src/main/scala/org/apache/spark/SparkException.scala
srielau Jun 8, 2022
5a10108
Address more Wenchen comments
srielau Jun 8, 2022
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
13 changes: 13 additions & 0 deletions core/src/main/java/org/apache/spark/SparkThrowable.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ public interface SparkThrowable {
// If null, error class is not set
String getErrorClass();

default String getErrorSubClass() {
return null;
}

// Portable error identifier across SQL engines
// If null, error class or SQLSTATE is not set
default String getSqlState() {
Expand All @@ -46,4 +50,13 @@ default String getSqlState() {
default boolean isInternalError() {
return SparkThrowableHelper.isInternalError(this.getErrorClass());
}

default String[] getMessageParameters() {
return new String[]{};
}

// Returns a string array of all parameters that need to be passed to this error message.
default String[] getParameterNames() {
return SparkThrowableHelper.getParameterNames(this.getErrorClass(), this.getErrorSubClass());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ public SparkOutOfMemoryError(OutOfMemoryError e) {
}

public SparkOutOfMemoryError(String errorClass, String[] messageParameters) {
super(SparkThrowableHelper.getMessage(errorClass, messageParameters, ""));
super(SparkThrowableHelper.getMessage(errorClass, null,
messageParameters, ""));
this.errorClass = errorClass;
this.messageParameters = messageParameters;
}

@Override
public String[] getMessageParameters() {
return messageParameters;
}

@Override
public String getErrorClass() {
return errorClass;
Expand Down
37 changes: 18 additions & 19 deletions core/src/main/resources/error/error-classes.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@
},
"CANNOT_UP_CAST_DATATYPE" : {
"message" : [
"Cannot up cast <value> from <sourceType> to <targetType>.",
"Cannot up cast <expression> from <sourceType> to <targetType>.",
"<details>"
]
},
"CAST_INVALID_INPUT" : {
"message" : [
"The value <value> of the type <sourceType> cannot be cast to <targetType> because it is malformed. Correct the value as per the syntax, or change its target type. Use `try_cast` to tolerate malformed input and return NULL instead. If necessary set <config> to \"false\" to bypass this error."
"The value <expression> of the type <sourceType> cannot be cast to <targetType> because it is malformed. Correct the value as per the syntax, or change its target type. Use `try_cast` to tolerate malformed input and return NULL instead. If necessary set <ansiConfig> to \"false\" to bypass this error."
],
"sqlState" : "42000"
},
"CAST_OVERFLOW" : {
"message" : [
"The value <value> of the type <sourceType> cannot be cast to <targetType> due to an overflow. Use `try_cast` to tolerate overflow and return NULL instead. If necessary set <config> to \"false\" to bypass this error."
"The value <value> of the type <sourceType> cannot be cast to <targetType> due to an overflow. Use `try_cast` to tolerate overflow and return NULL instead. If necessary set <ansiConfig> to \"false\" to bypass this error."
],
"sqlState" : "22005"
},
Expand Down Expand Up @@ -83,7 +83,7 @@
},
"FORBIDDEN_OPERATION" : {
"message" : [
"The operation <statement> is not allowed on <objectType>: <objectName>"
"The operation <statement> is not allowed on the <objectType>: <objectName>"
]
},
"GRAPHITE_SINK_INVALID_PROTOCOL" : {
Expand Down Expand Up @@ -157,8 +157,7 @@
"See more details in SPARK-31404. You can set the SQL config <config> or",
"the datasource option <option> to \"LEGACY\" to rebase the datetime values",
"w.r.t. the calendar difference during reading. To read the datetime values",
"as it is, set the SQL config <config> or the datasource option <option>",
"to \"CORRECTED\"."
"as it is, set the SQL config or the datasource option to \"CORRECTED\"."
]
},
"WRITE_ANCIENT_DATETIME" : {
Expand All @@ -170,7 +169,7 @@
"is different from Spark 3.0+'s Proleptic Gregorian calendar. See more",
"details in SPARK-31404. You can set <config> to \"LEGACY\" to rebase the",
"datetime values w.r.t. the calendar difference during writing, to get maximum",
"interoperability. Or set <config> to \"CORRECTED\" to write the datetime",
"interoperability. Or set the config to \"CORRECTED\" to write the datetime",
"values as it is, if you are sure that the written files will only be read by",
"Spark 3.0+ or other systems that use Proleptic Gregorian calendar."
]
Expand All @@ -190,12 +189,12 @@
},
"INVALID_ARRAY_INDEX" : {
"message" : [
"The index <indexValue> is out of bounds. The array has <arraySize> elements. If necessary set <config> to \"false\" to bypass this error."
"The index <indexValue> is out of bounds. The array has <arraySize> elements. If necessary set <ansiConfig> to \"false\" to bypass this error."
]
},
"INVALID_ARRAY_INDEX_IN_ELEMENT_AT" : {
"message" : [
"The index <indexValue> is out of bounds. The array has <arraySize> elements. Use `try_element_at` to tolerate accessing element at invalid index and return NULL instead. If necessary set <config> to \"false\" to bypass this error."
"The index <indexValue> is out of bounds. The array has <arraySize> elements. Use `try_element_at` to tolerate accessing element at invalid index and return NULL instead. If necessary set <ansiConfig> to \"false\" to bypass this error."
]
},
"INVALID_BUCKET_FILE" : {
Expand All @@ -211,7 +210,7 @@
},
"INVALID_FRACTION_OF_SECOND" : {
"message" : [
"The fraction of sec must be zero. Valid range is [0, 60]. If necessary set <config> to \"false\" to bypass this error."
"The fraction of sec must be zero. Valid range is [0, 60]. If necessary set <ansiConfig> to \"false\" to bypass this error."
],
"sqlState" : "22023"
},
Expand All @@ -222,7 +221,7 @@
},
"INVALID_PANDAS_UDF_PLACEMENT" : {
"message" : [
"The group aggregate pandas UDF <functionName> cannot be invoked together with as other, non-pandas aggregate functions."
"The group aggregate pandas UDF <functionList> cannot be invoked together with as other, non-pandas aggregate functions."
]
},
"INVALID_PARAMETER_VALUE" : {
Expand Down Expand Up @@ -266,7 +265,7 @@
},
"MULTI_UDF_INTERFACE_ERROR" : {
"message" : [
"Not allowed to implement multiple UDF interfaces, UDF class <class>"
"Not allowed to implement multiple UDF interfaces, UDF class <className>"
]
},
"MULTI_VALUE_SUBQUERY_ERROR" : {
Expand All @@ -293,7 +292,7 @@
},
"NO_UDF_INTERFACE_ERROR" : {
"message" : [
"UDF class <class> doesn't implement any UDF interface"
"UDF class <className> doesn't implement any UDF interface"
]
},
"PARSE_CHAR_MISSING_LENGTH" : {
Expand Down Expand Up @@ -333,7 +332,7 @@
},
"SECOND_FUNCTION_ARGUMENT_NOT_INTEGER" : {
"message" : [
"The second argument of '<functionName>' function needs to be an integer."
"The second argument of <functionName> function needs to be an integer."
],
"sqlState" : "22023"
},
Expand Down Expand Up @@ -361,7 +360,7 @@
"subClass" : {
"DATA_TYPE_MISMATCH" : {
"message" : [
"need <quantifier> <desiredType> field but got <dataType>."
"need a(n) <desiredType> field but got <dataType>."
]
},
"FIELD_NUMBER_MISMATCH" : {
Expand Down Expand Up @@ -473,7 +472,7 @@
},
"TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS" : {
"message" : [
"UDF class with <n> type arguments."
"UDF class with <num> type arguments."
]
},
"TRANSFORM_DISTINCT_ALL" : {
Expand All @@ -496,17 +495,17 @@
"subClass" : {
"MULTI_GENERATOR" : {
"message" : [
"only one generator allowed per <clause> clause but found <size>: <generators>"
"only one generator allowed per <clause> clause but found <num>: <generators>"
]
},
"NESTED_IN_EXPRESSIONS" : {
"message" : [
"nested in expressions <expressions>"
"nested in expressions <expression>"
]
},
"NOT_GENERATOR" : {
"message" : [
"<name> is expected to be a generator. However, its class is <classCanonicalName>, which is not a generator."
"<functionName> is expected to be a generator. However, its class is <classCanonicalName>, which is not a generator."
]
},
"OUTSIDE_SELECT" : {
Expand Down
36 changes: 31 additions & 5 deletions core/src/main/scala/org/apache/spark/ErrorInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,21 @@ private[spark] object SparkThrowableHelper {

def getMessage(
errorClass: String,
errorSubClass: String,
messageParameters: Array[String],
queryContext: String = ""): String = {
val errorInfo = errorClassToInfoMap.getOrElse(errorClass,
throw new IllegalArgumentException(s"Cannot find error class '$errorClass'"))
val (displayClass, displayMessageParameters, displayFormat) = if (errorInfo.subClass.isEmpty) {
(errorClass, messageParameters, errorInfo.messageFormat)
} else {
val subClass = errorInfo.subClass.get
val subErrorClass = messageParameters.head
val errorSubInfo = subClass.getOrElse(subErrorClass,
throw new IllegalArgumentException(s"Cannot find sub error class '$subErrorClass'"))
(errorClass + "." + subErrorClass, messageParameters.tail,
val subClasses = errorInfo.subClass.get
if (errorSubClass == null) {
throw new IllegalArgumentException(s"Subclass required for error class '$errorClass'")
}
val errorSubInfo = subClasses.getOrElse(errorSubClass,
throw new IllegalArgumentException(s"Cannot find sub error class '$errorSubClass'"))
(errorClass + "." + errorSubClass, messageParameters,
errorInfo.messageFormat + " " + errorSubInfo.messageFormat)
}
val displayMessage = String.format(
Expand All @@ -98,6 +101,29 @@ private[spark] object SparkThrowableHelper {
s"[$displayClass] $displayMessage$displayQueryContext"
}

def getParameterNames(errorClass: String, errorSubCLass: String): Array[String] = {
val errorInfo = errorClassToInfoMap.getOrElse(errorClass,
throw new IllegalArgumentException(s"Cannot find error class '$errorClass'"))
if (errorInfo.subClass.isEmpty && errorSubCLass != null) {
throw new IllegalArgumentException(s"'$errorClass' has no subclass")
}
if (errorInfo.subClass.isDefined && errorSubCLass == null) {
throw new IllegalArgumentException(s"'$errorClass' requires subclass")
}
var parameterizedMessage = errorInfo.messageFormat
if (errorInfo.subClass.isDefined) {
val givenSubClass = errorSubCLass
val errorSubInfo = errorInfo.subClass.get.getOrElse(givenSubClass,
throw new IllegalArgumentException(s"Cannot find sub error class '$givenSubClass'"))
parameterizedMessage = parameterizedMessage + errorSubInfo.messageFormat
}
val pattern = "<[a-zA-Z0-9_-]+>".r
val matches = pattern.findAllIn(parameterizedMessage)
val parameterSeq = matches.toArray
val parameterNames = parameterSeq.map(p => p.stripPrefix("<").stripSuffix(">"))
parameterNames
}

def getSqlState(errorClass: String): String = {
Option(errorClass).flatMap(errorClassToInfoMap.get).flatMap(_.sqlState).orNull
}
Expand Down
Loading