This is an automated email from the ASF dual-hosted git repository.

wenchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 43e610333fb [SPARK-38972][SQL] Support <param> in error-class messages
43e610333fb is described below

commit 43e610333fb78834a09cd82f3da32bad262564f3
Author: Serge Rielau <[email protected]>
AuthorDate: Thu Apr 21 21:53:28 2022 +0800

    [SPARK-38972][SQL] Support <param> in error-class messages
    
    ### What changes were proposed in this pull request?
    
    Use symbolic names for parameters in error messages which are substituted 
with %s before formatting the string.
    
    ### Why are the changes needed?
    Increase readability of error message docs (TBD)
    
    ### Does this PR introduce _any_ user-facing change?
    No
    
    ### How was this patch tested?
    
    SQL Project.
    
    Closes #36289 from srielau/symbolic-error-arg-names.
    
    Authored-by: Serge Rielau <[email protected]>
    Signed-off-by: Wenchen Fan <[email protected]>
---
 core/src/main/resources/error/error-classes.json   | 102 ++++++++++-----------
 .../main/scala/org/apache/spark/ErrorInfo.scala    |   3 +-
 2 files changed, 53 insertions(+), 52 deletions(-)

diff --git a/core/src/main/resources/error/error-classes.json 
b/core/src/main/resources/error/error-classes.json
index 6d070c35c74..d6e510f659c 100644
--- a/core/src/main/resources/error/error-classes.json
+++ b/core/src/main/resources/error/error-classes.json
@@ -1,18 +1,18 @@
 {
   "AMBIGUOUS_FIELD_NAME" : {
-    "message" : [ "Field name %s is ambiguous and has %s matching fields in 
the struct." ],
+    "message" : [ "Field name <fieldName> is ambiguous and has <n> matching 
fields in the struct." ],
     "sqlState" : "42000"
   },
   "ARITHMETIC_OVERFLOW" : {
-    "message" : [ "%s.%s If necessary set %s to false (except for ANSI 
interval type) to bypass this error.%s" ],
+    "message" : [ "<message>.<alternative> If necessary set <config> to false 
(except for ANSI interval type) to bypass this error.<context>" ],
     "sqlState" : "22003"
   },
   "CANNOT_CAST_DATATYPE" : {
-    "message" : [ "Cannot cast %s to %s." ],
+    "message" : [ "Cannot cast <sourceType> to <targetType>." ],
     "sqlState" : "22005"
   },
   "CANNOT_CHANGE_DECIMAL_PRECISION" : {
-    "message" : [ "%s cannot be represented as Decimal(%s, %s). If necessary 
set %s to false to bypass this error.%s" ],
+    "message" : [ "<value> cannot be represented as Decimal(<precision>, 
<scale>). If necessary set <config> to false to bypass this error.<details>" ],
     "sqlState" : "22005"
   },
   "CANNOT_PARSE_DECIMAL" : {
@@ -20,139 +20,139 @@
     "sqlState" : "42000"
   },
   "CANNOT_UP_CAST_DATATYPE" : {
-    "message" : [ "Cannot up cast %s from %s to %s.\n%s" ]
+    "message" : [ "Cannot up cast <value> from <sourceType> to 
<targetType>.\n<details>" ]
   },
   "CAST_CAUSES_OVERFLOW" : {
-    "message" : [ "Casting %s to %s causes overflow. To return NULL instead, 
use 'try_cast'. If necessary set %s to false to bypass this error." ],
+    "message" : [ "Casting <value> to <type> causes overflow. To return NULL 
instead, use 'try_cast'. If necessary set <config> to false to bypass this 
error." ],
     "sqlState" : "22005"
   },
   "CONCURRENT_QUERY" : {
     "message" : [ "Another instance of this query was just started by a 
concurrent session." ]
   },
   "DATETIME_OVERFLOW" : {
-    "message" : [ "Datetime operation overflow: %s." ],
+    "message" : [ "Datetime operation overflow: <operation>." ],
     "sqlState" : "22008"
   },
   "DIVIDE_BY_ZERO" : {
-    "message" : [ "divide by zero. To return NULL instead, use 'try_divide'. 
If necessary set %s to false (except for ANSI interval type) to bypass this 
error.%s" ],
+    "message" : [ "divide by zero. To return NULL instead, use 'try_divide'. 
If necessary set <config> to false (except for ANSI interval type) to bypass 
this error.<details>" ],
     "sqlState" : "22012"
   },
   "DUPLICATE_KEY" : {
-    "message" : [ "Found duplicate keys %s" ],
+    "message" : [ "Found duplicate keys <keyColumn>" ],
     "sqlState" : "23000"
   },
   "FAILED_EXECUTE_UDF" : {
-    "message" : [ "Failed to execute user defined function (%s: (%s) => %s)" ]
+    "message" : [ "Failed to execute user defined function (<functionName>: 
(<signature>) => <result>)" ]
   },
   "FAILED_RENAME_PATH" : {
-    "message" : [ "Failed to rename %s to %s as destination already exists" ],
+    "message" : [ "Failed to rename <sourcePath> to <targetPath> as 
destination already exists" ],
     "sqlState" : "22023"
   },
   "FAILED_SET_ORIGINAL_PERMISSION_BACK" : {
-    "message" : [ "Failed to set original permission %s back to the created 
path: %s. Exception: %s" ]
+    "message" : [ "Failed to set original permission <permission> back to the 
created path: <path>. Exception: <message>" ]
   },
   "FORBIDDEN_OPERATION" : {
-    "message" : [ "The operation %s is not allowed on %s: %s" ]
+    "message" : [ "The operation <statement> is not allowed on <objectType>: 
<objectName>" ]
   },
   "GRAPHITE_SINK_INVALID_PROTOCOL" : {
-    "message" : [ "Invalid Graphite protocol: %s" ]
+    "message" : [ "Invalid Graphite protocol: <protocol>" ]
   },
   "GRAPHITE_SINK_PROPERTY_MISSING" : {
-    "message" : [ "Graphite sink requires '%s' property." ]
+    "message" : [ "Graphite sink requires '<property>' property." ]
   },
   "GROUPING_COLUMN_MISMATCH" : {
-    "message" : [ "Column of grouping (%s) can't be found in grouping columns 
%s" ],
+    "message" : [ "Column of grouping (<grouping>) can't be found in grouping 
columns <groupingColumns>" ],
     "sqlState" : "42000"
   },
   "GROUPING_ID_COLUMN_MISMATCH" : {
-    "message" : [ "Columns of grouping_id (%s) does not match grouping columns 
(%s)" ],
+    "message" : [ "Columns of grouping_id (<groupingIdColumn>) does not match 
grouping columns (<groupByColumns>)" ],
     "sqlState" : "42000"
   },
   "GROUPING_SIZE_LIMIT_EXCEEDED" : {
-    "message" : [ "Grouping sets size cannot be greater than %s" ]
+    "message" : [ "Grouping sets size cannot be greater than <maxSize>" ]
   },
   "ILLEGAL_SUBSTRING" : {
-    "message" : [ "%s cannot contain %s." ]
+    "message" : [ "<subject> cannot contain <content>." ]
   },
   "INCOMPARABLE_PIVOT_COLUMN" : {
-    "message" : [ "Invalid pivot column '%s'. Pivot columns must be 
comparable." ],
+    "message" : [ "Invalid pivot column '<columnName>'. Pivot columns must be 
comparable." ],
     "sqlState" : "42000"
   },
   "INCOMPATIBLE_DATASOURCE_REGISTER" : {
-    "message" : [ "Detected an incompatible DataSourceRegister. Please remove 
the incompatible library from classpath or upgrade it. Error: %s" ]
+    "message" : [ "Detected an incompatible DataSourceRegister. Please remove 
the incompatible library from classpath or upgrade it. Error: <message>" ]
   },
   "INCONSISTENT_BEHAVIOR_CROSS_VERSION" : {
-    "message" : [ "You may get a different result due to the upgrading to 
Spark >= %s: %s" ]
+    "message" : [ "You may get a different result due to the upgrading to 
Spark >= <sparkVersion>: <details>" ]
   },
   "INDEX_OUT_OF_BOUNDS" : {
-    "message" : [ "Index %s must be between 0 and the length of the 
ArrayData." ],
+    "message" : [ "Index <indexValue> must be between 0 and the length of the 
ArrayData." ],
     "sqlState" : "22023"
   },
   "INTERNAL_ERROR" : {
-    "message" : [ "%s" ]
+    "message" : [ "<message>" ]
   },
   "INVALID_ARRAY_INDEX" : {
-    "message" : [ "Invalid index: %s, numElements: %s. If necessary set %s to 
false to bypass this error." ]
+    "message" : [ "Invalid index: <indexValue>, numElements: <arraySize>. If 
necessary set <config> to false to bypass this error." ]
   },
   "INVALID_ARRAY_INDEX_IN_ELEMENT_AT" : {
-    "message" : [ "Invalid index: %s, numElements: %s. To return NULL instead, 
use 'try_element_at'. If necessary set %s to false to bypass this error." ]
+    "message" : [ "Invalid index: <indexValue>, numElements: <arraySize>. To 
return NULL instead, use 'try_element_at'. If necessary set <config> to false 
to bypass this error." ]
   },
   "INVALID_FIELD_NAME" : {
-    "message" : [ "Field name %s is invalid: %s is not a struct." ],
+    "message" : [ "Field name <fieldName> is invalid: <path> is not a struct." 
],
     "sqlState" : "42000"
   },
   "INVALID_FRACTION_OF_SECOND" : {
-    "message" : [ "The fraction of sec must be zero. Valid range is [0, 60]. 
If necessary set %s to false to bypass this error. " ],
+    "message" : [ "The fraction of sec must be zero. Valid range is [0, 60]. 
If necessary set <config> to false to bypass this error. " ],
     "sqlState" : "22023"
   },
   "INVALID_JSON_SCHEMA_MAPTYPE" : {
-    "message" : [ "Input schema %s can only contain StringType as a key type 
for a MapType." ]
+    "message" : [ "Input schema <dataType> can only contain StringType as a 
key type for a MapType." ]
   },
   "INVALID_PANDAS_UDF_PLACEMENT" : {
-    "message" : [ "The group aggregate pandas UDF %s cannot be invoked 
together with as other, non-pandas aggregate functions." ]
+    "message" : [ "The group aggregate pandas UDF <functionName> cannot be 
invoked together with as other, non-pandas aggregate functions." ]
   },
   "INVALID_PARAMETER_VALUE" : {
-    "message" : [ "The value of parameter(s) '%s' in %s is invalid: %s" ],
+    "message" : [ "The value of parameter(s) '<parameter>' in <functionName> 
is invalid: <expected>" ],
     "sqlState" : "22023"
   },
   "INVALID_SQL_SYNTAX" : {
-    "message" : [ "Invalid SQL syntax: %s" ],
+    "message" : [ "Invalid SQL syntax: <inputString>" ],
     "sqlState" : "42000"
   },
   "INVALID_SYNTAX_FOR_CAST" : {
-    "message" : [ "Invalid input syntax for type %s: %s. To return NULL 
instead, use 'try_cast'. If necessary set %s to false to bypass this error.%s" 
],
+    "message" : [ "Invalid input syntax for type <typeName>: <value>. To 
return NULL instead, use 'try_cast'. If necessary set <config> to false to 
bypass this error.<details>" ],
     "sqlState" : "42000"
   },
   "MAP_KEY_DOES_NOT_EXIST" : {
-    "message" : [ "Key %s does not exist. To return NULL instead, use 
'try_element_at'. If necessary set %s to false to bypass this error.%s" ]
+    "message" : [ "Key <keyValue> does not exist. To return NULL instead, use 
'try_element_at'. If necessary set <config> to false to bypass this 
error.<details>" ]
   },
   "MISSING_COLUMN" : {
-    "message" : [ "Column '%s' does not exist. Did you mean one of the 
following? [%s]" ],
+    "message" : [ "Column '<columnName>' does not exist. Did you mean one of 
the following? [<proposal>]" ],
     "sqlState" : "42000"
   },
   "MISSING_STATIC_PARTITION_COLUMN" : {
-    "message" : [ "Unknown static partition column: %s" ],
+    "message" : [ "Unknown static partition column: <columnName>" ],
     "sqlState" : "42000"
   },
   "MULTI_UDF_INTERFACE_ERROR" : {
-    "message" : [ "Not allowed to implement multiple UDF interfaces, UDF class 
%s" ]
+    "message" : [ "Not allowed to implement multiple UDF interfaces, UDF class 
<class>" ]
   },
   "NON_LITERAL_PIVOT_VALUES" : {
-    "message" : [ "Literal expressions required for pivot values, found '%s'" 
],
+    "message" : [ "Literal expressions required for pivot values, found 
'<expression>'" ],
     "sqlState" : "42000"
   },
   "NON_PARTITION_COLUMN" : {
-    "message" : [ "PARTITION clause cannot contain a non-partition column 
name: %s" ],
+    "message" : [ "PARTITION clause cannot contain a non-partition column 
name: <columnName>" ],
     "sqlState" : "42000"
   },
   "NO_HANDLER_FOR_UDAF" : {
-    "message" : [ "No handler for UDAF '%s'. Use 
sparkSession.udf.register(...) instead." ]
+    "message" : [ "No handler for UDAF '<functionName>'. Use 
sparkSession.udf.register(...) instead." ]
   },
   "NO_UDF_INTERFACE_ERROR" : {
-    "message" : [ "UDF class %s doesn't implement any UDF interface" ]
+    "message" : [ "UDF class <class> doesn't implement any UDF interface" ]
   },
   "PARSE_CHAR_MISSING_LENGTH" : {
-    "message" : [ "DataType %s requires a length parameter, for example 
%s(10). Please specify the length." ],
+    "message" : [ "DataType <type> requires a length parameter, for example 
<type>(10). Please specify the length." ],
     "sqlState" : "42000"
   },
   "PARSE_EMPTY_STATEMENT" : {
@@ -160,41 +160,41 @@
     "sqlState" : "42000"
   },
   "PARSE_SYNTAX_ERROR" : {
-    "message" : [ "Syntax error at or near %s%s" ],
+    "message" : [ "Syntax error at or near <error><hint>" ],
     "sqlState" : "42000"
   },
   "PIVOT_VALUE_DATA_TYPE_MISMATCH" : {
-    "message" : [ "Invalid pivot value '%s': value data type %s does not match 
pivot column data type %s" ],
+    "message" : [ "Invalid pivot value '<value>': value data type <valueType> 
does not match pivot column data type <pivotType>" ],
     "sqlState" : "42000"
   },
   "RENAME_SRC_PATH_NOT_FOUND" : {
-    "message" : [ "Failed to rename as %s was not found" ],
+    "message" : [ "Failed to rename as <sourcePath> was not found" ],
     "sqlState" : "22023"
   },
   "SECOND_FUNCTION_ARGUMENT_NOT_INTEGER" : {
-    "message" : [ "The second argument of '%s' function needs to be an 
integer." ],
+    "message" : [ "The second argument of '<functionName>' function needs to 
be an integer." ],
     "sqlState" : "22023"
   },
   "UNABLE_TO_ACQUIRE_MEMORY" : {
-    "message" : [ "Unable to acquire %s bytes of memory, got %s" ]
+    "message" : [ "Unable to acquire <requestedBytes> bytes of memory, got 
<receivedBytes>" ]
   },
   "UNRECOGNIZED_SQL_TYPE" : {
-    "message" : [ "Unrecognized SQL type %s" ],
+    "message" : [ "Unrecognized SQL type <typeName>" ],
     "sqlState" : "42000"
   },
   "UNSUPPORTED_DATATYPE" : {
-    "message" : [ "Unsupported data type %s" ],
+    "message" : [ "Unsupported data type <typeName>" ],
     "sqlState" : "0A000"
   },
   "UNSUPPORTED_FEATURE" : {
-    "message" : [ "The feature is not supported: %s" ],
+    "message" : [ "The feature is not supported: <feature>" ],
     "sqlState" : "0A000"
   },
   "UNSUPPORTED_GROUPING_EXPRESSION" : {
     "message" : [ "grouping()/grouping_id() can only be used with 
GroupingSets/Cube/Rollup" ]
   },
   "UNSUPPORTED_OPERATION" : {
-    "message" : [ "The operation is not supported: %s" ]
+    "message" : [ "The operation is not supported: <operation>" ]
   },
   "UNTYPED_SCALA_UDF" : {
     "message" : [ "You're using untyped Scala UDF, which does not have the 
input type information. Spark may blindly pass null to the Scala closure with 
primitive-type argument, and the closure will see the default value of the Java 
type for the null argument, e.g. `udf((x: Int) => x, IntegerType)`, the result 
is 0 for null input. To get rid of this error, you could:\n1. use typed Scala 
UDF APIs(without return type parameter), e.g. `udf((x: Int) => x)`\n2. use Java 
UDF APIs, e.g. `udf(ne [...]
diff --git a/core/src/main/scala/org/apache/spark/ErrorInfo.scala 
b/core/src/main/scala/org/apache/spark/ErrorInfo.scala
index 0917085c01b..6cb8f4d8ed3 100644
--- a/core/src/main/scala/org/apache/spark/ErrorInfo.scala
+++ b/core/src/main/scala/org/apache/spark/ErrorInfo.scala
@@ -58,7 +58,8 @@ private[spark] object SparkThrowableHelper {
   def getMessage(errorClass: String, messageParameters: Array[String]): String 
= {
     val errorInfo = errorClassToInfoMap.getOrElse(errorClass,
       throw new IllegalArgumentException(s"Cannot find error class 
'$errorClass'"))
-    String.format(errorInfo.messageFormat, messageParameters: _*)
+    String.format(errorInfo.messageFormat.replaceAll("<[a-zA-Z0-9_-]+>", "%s"),
+      messageParameters: _*)
   }
 
   def getSqlState(errorClass: String): String = {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to