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 6f4e7b6894b [SPARK-38985][SQL] Add sub error classes 6f4e7b6894b is described below commit 6f4e7b6894b6e1649adc6ec829266be6ff96624e Author: Serge Rielau <srie...@users.noreply.github.com> AuthorDate: Wed Apr 27 09:30:23 2022 +0800 [SPARK-38985][SQL] Add sub error classes ### What changes were proposed in this pull request? We support nesting an optional map of "sub error classes" in error-classes.json. Each sub class has a distinct message and independent parameters. ### Why are the changes needed? A select subset of error classes have a large variety of error messages which cannot be easily tokenized. But we do not want to split them because the conditions are often temporary. An example is UNSUPPORTED_FEATURE. Supporting nested error classes allows us to keep the variety of messages without exploding the number of error classes. ### Does this PR introduce _any_ user-facing change? Yes, we will change the error message texts ### How was this patch tested? Run all affected error test suites. Closes #36307 from srielau/SPARK-38985-sub-error-classes. Lead-authored-by: Serge Rielau <srie...@users.noreply.github.com> Co-authored-by: Serge Rielau <serge.rie...@databricks.com> Signed-off-by: Wenchen Fan <wenc...@databricks.com> --- core/src/main/resources/error/error-classes.json | 55 +++++++++++++++++++++- .../main/scala/org/apache/spark/ErrorInfo.scala | 35 ++++++++++++-- python/pyspark/sql/tests/test_udf.py | 3 +- .../spark/sql/errors/QueryCompilationErrors.scala | 13 ++--- .../spark/sql/errors/QueryExecutionErrors.scala | 16 +++---- .../spark/sql/errors/QueryParsingErrors.scala | 14 +++--- .../ExtractPythonUDFFromJoinConditionSuite.scala | 4 +- .../sql/catalyst/parser/PlanParserSuite.scala | 2 +- .../sql-tests/results/join-lateral.sql.out | 4 +- .../resources/sql-tests/results/transform.sql.out | 4 +- .../errors/QueryCompilationErrorsDSv2Suite.scala | 3 +- .../sql/errors/QueryCompilationErrorsSuite.scala | 9 ++-- .../spark/sql/errors/QueryErrorsSuiteBase.scala | 19 ++++++-- .../sql/errors/QueryExecutionErrorsSuite.scala | 13 +++-- .../spark/sql/errors/QueryParsingErrorsSuite.scala | 18 ++++--- .../execution/SparkScriptTransformationSuite.scala | 2 +- 16 files changed, 157 insertions(+), 57 deletions(-) diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index 9cb4cb222aa..673866e6c35 100644 --- a/core/src/main/resources/error/error-classes.json +++ b/core/src/main/resources/error/error-classes.json @@ -187,7 +187,60 @@ "sqlState" : "0A000" }, "UNSUPPORTED_FEATURE" : { - "message" : [ "The feature is not supported: <feature>" ], + "message" : [ "The feature is not supported: " ], + "subClass" : { + "AES_MODE" : { + "message" : [ "AES-<mode> with the padding <padding> by the <functionName> function." ] + }, + "DISTRIBUTE_BY" : { + "message" : [ "DISTRIBUTE BY clause." ] + }, + "INSERT_PARTITION_SPEC_IF_NOT_EXISTS" : { + "message" : [ "INSERT INTO <tableName> IF NOT EXISTS in the PARTITION spec." ] + }, + "JDBC_TRANSACTION" : { + "message" : [ "The target JDBC server does not support transactions and can only support ALTER TABLE with a single action." ] + }, + "LATERAL_JOIN_OF_TYPE" : { + "message" : [ "<joinType> JOIN with LATERAL correlation." ] + }, + "LATERAL_JOIN_USING" : { + "message" : [ "JOIN USING with LATERAL correlation." ] + }, + "LATERAL_NATURAL_JOIN" : { + "message" : [ "NATURAL join with LATERAL correlation." ] + }, + "LITERAL_TYPE" : { + "message" : [ "Literal for '<value>' of <type>." ] + }, + "NATURAL_CROSS_JOIN" : { + "message" : [ "NATURAL CROSS JOIN." ] + }, + "PANDAS_UDAF_IN_PIVOT" : { + "message" : [ "Pandas user defined aggregate function in the PIVOT clause." ] + }, + "PIVOT_AFTER_GROUP_BY" : { + "message" : [ "PIVOT clause following a GROUP BY clause." ] + }, + "PIVOT_TYPE" : { + "message" : [ "Pivoting by the value '<value>' of the column data type <type>." ] + }, + "PYTHON_UDF_IN_ON_CLAUSE" : { + "message" : [ "Python UDF in the ON clause of a <joinType> JOIN." ] + }, + "REPEATED_PIVOT" : { + "message" : [ "Repeated PIVOT operation." ] + }, + "TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS" : { + "message" : [ "UDF class with <n> type arguments." ] + }, + "TRANSFORM_DISTINCT_ALL" : { + "message" : [ "TRANSFORM with the DISTINCT/ALL clause." ] + }, + "TRANSFORM_NON_HIVE" : { + "message" : [ "TRANSFORM with SERDE is only supported in hive mode." ] + } + }, "sqlState" : "0A000" }, "UNSUPPORTED_GROUPING_EXPRESSION" : { diff --git a/core/src/main/scala/org/apache/spark/ErrorInfo.scala b/core/src/main/scala/org/apache/spark/ErrorInfo.scala index bed05b7ab39..a21f33e8833 100644 --- a/core/src/main/scala/org/apache/spark/ErrorInfo.scala +++ b/core/src/main/scala/org/apache/spark/ErrorInfo.scala @@ -28,14 +28,30 @@ import com.fasterxml.jackson.module.scala.DefaultScalaModule import org.apache.spark.util.Utils +/** + * Information associated with an error subclass. + * + * @param subClass SubClass associated with this class. + * @param message C-style message format compatible with printf. + * The error message is constructed by concatenating the lines with newlines. + */ +private[spark] case class ErrorSubInfo(message: Seq[String]) { + // For compatibility with multi-line error messages + @JsonIgnore + val messageFormat: String = message.mkString("\n") +} + /** * Information associated with an error class. * * @param sqlState SQLSTATE associated with this class. + * @param subClass A sequence of subclasses * @param message C-style message format compatible with printf. * The error message is constructed by concatenating the lines with newlines. */ -private[spark] case class ErrorInfo(message: Seq[String], sqlState: Option[String]) { +private[spark] case class ErrorInfo(message: Seq[String], + subClass: Option[Map[String, ErrorSubInfo]], + sqlState: Option[String]) { // For compatibility with multi-line error messages @JsonIgnore val messageFormat: String = message.mkString("\n") @@ -58,9 +74,20 @@ 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'")) - "[" + errorClass + "] " + String.format( - errorInfo.messageFormat.replaceAll("<[a-zA-Z0-9_-]+>", "%s"), - messageParameters: _*) + if (errorInfo.subClass.isDefined) { + val subClass = errorInfo.subClass.get + val subErrorClass = messageParameters.head + val errorSubInfo = subClass.getOrElse(subErrorClass, + throw new IllegalArgumentException(s"Cannot find sub error class '$subErrorClass'")) + val subMessageParameters = messageParameters.tail + "[" + errorClass + "." + subErrorClass + "] " + errorInfo.messageFormat + + String.format(errorSubInfo.messageFormat.replaceAll("<[a-zA-Z0-9_-]+>", "%s"), + subMessageParameters: _*) + } else { + "[" + errorClass + "] " + String.format( + errorInfo.messageFormat.replaceAll("<[a-zA-Z0-9_-]+>", "%s"), + messageParameters: _*) + } } def getSqlState(errorClass: String): String = { diff --git a/python/pyspark/sql/tests/test_udf.py b/python/pyspark/sql/tests/test_udf.py index e40c3ba0d64..52f8814b269 100644 --- a/python/pyspark/sql/tests/test_udf.py +++ b/python/pyspark/sql/tests/test_udf.py @@ -258,8 +258,7 @@ class UDFTests(ReusedSQLTestCase): def runWithJoinType(join_type, type_string): with self.assertRaisesRegex( AnalysisException, - """Using PythonUDF in join condition of join type "%s" is not supported""" - % type_string, + """Python UDF in the ON clause of a "%s" JOIN.""" % type_string, ): left.join(right, [f("a", "b"), left.a1 == right.b1], join_type).collect() diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala index 586f32dd4fc..7f212ed5891 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryCompilationErrors.scala @@ -94,9 +94,8 @@ object QueryCompilationErrors extends QueryErrorsBase { def unsupportedIfNotExistsError(tableName: String): Throwable = { new AnalysisException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array( - s"${toSQLStmt("IF NOT EXISTS")} for the table ${toSQLId(tableName)} " + - s"by ${toSQLStmt("INSERT INTO")}.")) + messageParameters = Array("INSERT_PARTITION_SPEC_IF_NOT_EXISTS", + toSQLId(tableName))) } def nonPartitionColError(partitionName: String): Throwable = { @@ -202,7 +201,7 @@ object QueryCompilationErrors extends QueryErrorsBase { def pandasUDFAggregateNotSupportedInPivotError(): Throwable = { new AnalysisException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array("Pandas UDF aggregate expressions don't support pivot.")) + messageParameters = Array("PANDAS_UDAF_IN_PIVOT")) } def aggregateExpressionRequiredForPivotError(sql: String): Throwable = { @@ -1588,9 +1587,7 @@ object QueryCompilationErrors extends QueryErrorsBase { def usePythonUDFInJoinConditionUnsupportedError(joinType: JoinType): Throwable = { new AnalysisException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array( - "Using PythonUDF in join condition of join type " + - s"${toSQLStmt(joinType.sql)} is not supported.")) + messageParameters = Array("PYTHON_UDF_IN_ON_CLAUSE", s"${toSQLStmt(joinType.sql)}")) } def conflictingAttributesInJoinConditionError( @@ -2336,7 +2333,7 @@ object QueryCompilationErrors extends QueryErrorsBase { def udfClassWithTooManyTypeArgumentsError(n: Int): Throwable = { new AnalysisException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"UDF class with $n type arguments")) + messageParameters = Array("TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS", s"$n")) } def classWithoutPublicNonArgumentConstructorError(className: String): Throwable = { diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala index dd45f62ac09..fe44a0ff54d 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala @@ -240,14 +240,14 @@ object QueryExecutionErrors extends QueryErrorsBase { def literalTypeUnsupportedError(v: Any): RuntimeException = { new SparkRuntimeException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"literal for '${v.toString}' of ${v.getClass.toString}.")) + messageParameters = Array("LITERAL_TYPE", s"${v.toString}", s"${v.getClass.toString}")) } def pivotColumnUnsupportedError(v: Any, dataType: DataType): RuntimeException = { new SparkRuntimeException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array( - s"pivoting by the value '${v.toString}' of the column data type ${toSQLType(dataType)}.")) + messageParameters = Array("PIVOT_TYPE", + s"${v.toString}", s"${toSQLType(dataType)}")) } def noDefaultForDataTypeError(dataType: DataType): RuntimeException = { @@ -766,8 +766,7 @@ object QueryExecutionErrors extends QueryErrorsBase { def transactionUnsupportedByJdbcServerError(): Throwable = { new SparkSQLFeatureNotSupportedException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array("the target JDBC server does not support transaction and " + - "can only support ALTER TABLE with a single action.")) + messageParameters = Array("JDBC_TRANSACTION")) } def dataTypeUnsupportedYetError(dataType: DataType): Throwable = { @@ -1892,13 +1891,13 @@ object QueryExecutionErrors extends QueryErrorsBase { def repeatedPivotsUnsupportedError(): Throwable = { new SparkUnsupportedOperationException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"Repeated ${toSQLStmt("pivot")}s.")) + messageParameters = Array("REPEATED_PIVOT")) } def pivotNotAfterGroupByUnsupportedError(): Throwable = { new SparkUnsupportedOperationException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"${toSQLStmt("pivot")} not after a ${toSQLStmt("group by")}.")) + messageParameters = Array("PIVOT_AFTER_GROUP_BY")) } private val aesFuncName = toSQLId("aes_encrypt") + "/" + toSQLId("aes_decrypt") @@ -1915,8 +1914,7 @@ object QueryExecutionErrors extends QueryErrorsBase { def aesModeUnsupportedError(mode: String, padding: String): RuntimeException = { new SparkRuntimeException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array( - s"AES-$mode with the padding $padding by the $aesFuncName function.")) + messageParameters = Array("AES_MODE", mode, padding, aesFuncName)) } def aesCryptoError(detailMessage: String): RuntimeException = { diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala index 06030fb53f3..ed5773f4f82 100644 --- a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala +++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryParsingErrors.scala @@ -92,16 +92,14 @@ object QueryParsingErrors extends QueryErrorsBase { def transformNotSupportQuantifierError(ctx: ParserRuleContext): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"${toSQLStmt("TRANSFORM")} does not support" + - s" ${toSQLStmt("DISTINCT")}/${toSQLStmt("ALL")} in inputs"), + messageParameters = Array("TRANSFORM_DISTINCT_ALL"), ctx) } def transformWithSerdeUnsupportedError(ctx: ParserRuleContext): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array( - s"${toSQLStmt("TRANSFORM")} with serde is only supported in hive mode"), + messageParameters = Array("TRANSFORM_NON_HIVE"), ctx) } @@ -112,21 +110,21 @@ object QueryParsingErrors extends QueryErrorsBase { def lateralJoinWithNaturalJoinUnsupportedError(ctx: ParserRuleContext): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"${toSQLStmt("LATERAL")} join with ${toSQLStmt("NATURAL")} join."), + messageParameters = Array("LATERAL_NATURAL_JOIN"), ctx) } def lateralJoinWithUsingJoinUnsupportedError(ctx: ParserRuleContext): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"${toSQLStmt("LATERAL")} join with ${toSQLStmt("USING")} join."), + messageParameters = Array("LATERAL_JOIN_USING"), ctx) } def unsupportedLateralJoinTypeError(ctx: ParserRuleContext, joinType: String): Throwable = { new ParseException( errorClass = "UNSUPPORTED_FEATURE", - messageParameters = Array(s"${toSQLStmt("LATERAL")} join type ${toSQLStmt(joinType)}."), + messageParameters = Array("LATERAL_JOIN_OF_TYPE", s"${toSQLStmt(joinType)}"), ctx) } @@ -153,7 +151,7 @@ object QueryParsingErrors extends QueryErrorsBase { } def naturalCrossJoinUnsupportedError(ctx: RelationContext): Throwable = { - new ParseException("UNSUPPORTED_FEATURE", Array(toSQLStmt("NATURAL CROSS JOIN") + "."), ctx) + new ParseException("UNSUPPORTED_FEATURE", Array("NATURAL_CROSS_JOIN"), ctx) } def emptyInputForTableSampleError(ctx: ParserRuleContext): Throwable = { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ExtractPythonUDFFromJoinConditionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ExtractPythonUDFFromJoinConditionSuite.scala index f69f782a0a7..b862416ff07 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ExtractPythonUDFFromJoinConditionSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/optimizer/ExtractPythonUDFFromJoinConditionSuite.scala @@ -188,8 +188,8 @@ class ExtractPythonUDFFromJoinConditionSuite extends PlanTest { Optimize.execute(query.analyze) } assert(e.message == - "[UNSUPPORTED_FEATURE] The feature is not supported: " + - s"""Using PythonUDF in join condition of join type "${joinType.sql}" is not supported.""") + "[UNSUPPORTED_FEATURE.PYTHON_UDF_IN_ON_CLAUSE] The feature is not supported: " + + s"""Python UDF in the ON clause of a "${joinType.sql}" JOIN.""") val query2 = testRelationLeft.join( testRelationRight, diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala index 77fa99b1450..b8c57753209 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/parser/PlanParserSuite.scala @@ -1253,7 +1253,7 @@ class PlanParserSuite extends AnalysisTest { | "escapeChar" = "\\") |FROM testData """.stripMargin, - "\"TRANSFORM\" with serde is only supported in hive mode") + "TRANSFORM with SERDE is only supported in hive mode.") } diff --git a/sql/core/src/test/resources/sql-tests/results/join-lateral.sql.out b/sql/core/src/test/resources/sql-tests/results/join-lateral.sql.out index 7b00ab1cb92..625607a8db0 100644 --- a/sql/core/src/test/resources/sql-tests/results/join-lateral.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/join-lateral.sql.out @@ -153,7 +153,7 @@ struct<> -- !query output org.apache.spark.sql.catalyst.parser.ParseException -[UNSUPPORTED_FEATURE] The feature is not supported: "LATERAL" join with "NATURAL" join.(line 1, pos 14) +[UNSUPPORTED_FEATURE.LATERAL_NATURAL_JOIN] The feature is not supported: NATURAL join with LATERAL correlation.(line 1, pos 14) == SQL == SELECT * FROM t1 NATURAL JOIN LATERAL (SELECT c1 + c2 AS c2) @@ -167,7 +167,7 @@ struct<> -- !query output org.apache.spark.sql.catalyst.parser.ParseException -[UNSUPPORTED_FEATURE] The feature is not supported: "LATERAL" join with "USING" join.(line 1, pos 14) +[UNSUPPORTED_FEATURE.LATERAL_JOIN_USING] The feature is not supported: JOIN USING with LATERAL correlation.(line 1, pos 14) == SQL == SELECT * FROM t1 JOIN LATERAL (SELECT c1 + c2 AS c2) USING (c2) diff --git a/sql/core/src/test/resources/sql-tests/results/transform.sql.out b/sql/core/src/test/resources/sql-tests/results/transform.sql.out index 3d0fdc81b36..6d7d112b352 100644 --- a/sql/core/src/test/resources/sql-tests/results/transform.sql.out +++ b/sql/core/src/test/resources/sql-tests/results/transform.sql.out @@ -719,7 +719,7 @@ struct<> -- !query output org.apache.spark.sql.catalyst.parser.ParseException -[UNSUPPORTED_FEATURE] The feature is not supported: "TRANSFORM" does not support "DISTINCT"/"ALL" in inputs(line 1, pos 17) +[UNSUPPORTED_FEATURE.TRANSFORM_DISTINCT_ALL] The feature is not supported: TRANSFORM with the DISTINCT/ALL clause.(line 1, pos 17) == SQL == SELECT TRANSFORM(DISTINCT b, a, c) @@ -739,7 +739,7 @@ struct<> -- !query output org.apache.spark.sql.catalyst.parser.ParseException -[UNSUPPORTED_FEATURE] The feature is not supported: "TRANSFORM" does not support "DISTINCT"/"ALL" in inputs(line 1, pos 17) +[UNSUPPORTED_FEATURE.TRANSFORM_DISTINCT_ALL] The feature is not supported: TRANSFORM with the DISTINCT/ALL clause.(line 1, pos 17) == SQL == SELECT TRANSFORM(ALL b, a, c) diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsDSv2Suite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsDSv2Suite.scala index 9fedf14a2a1..f51ec15dce5 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsDSv2Suite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsDSv2Suite.scala @@ -53,8 +53,9 @@ class QueryCompilationErrorsDSv2Suite checkErrorClass( exception = e, errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("INSERT_PARTITION_SPEC_IF_NOT_EXISTS"), msg = "The feature is not supported: " + - s""""IF NOT EXISTS" for the table `testcat`.`ns1`.`ns2`.`tbl` by "INSERT INTO".""", + s"""INSERT INTO `testcat`.`ns1`.`ns2`.`tbl` IF NOT EXISTS in the PARTITION spec.""", sqlState = Some("0A000")) } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala index f1325a68366..39f4414b493 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryCompilationErrorsSuite.scala @@ -165,8 +165,9 @@ class QueryCompilationErrorsSuite checkErrorClass( exception = e, errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("PYTHON_UDF_IN_ON_CLAUSE"), msg = "The feature is not supported: " + - "Using PythonUDF in join condition of join type \"LEFT OUTER\" is not supported.", + "Python UDF in the ON clause of a \"LEFT OUTER\" JOIN.", sqlState = Some("0A000")) } @@ -188,8 +189,9 @@ class QueryCompilationErrorsSuite checkErrorClass( exception = e, errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("PANDAS_UDAF_IN_PIVOT"), msg = "The feature is not supported: " + - "Pandas UDF aggregate expressions don't support pivot.", + "Pandas user defined aggregate function in the PIVOT clause.", sqlState = Some("0A000")) } @@ -270,7 +272,8 @@ class QueryCompilationErrorsSuite checkErrorClass( exception = e, errorClass = "UNSUPPORTED_FEATURE", - msg = "The feature is not supported: UDF class with 24 type arguments", + errorSubClass = Some("TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS"), + msg = "The feature is not supported: UDF class with 24 type arguments.", sqlState = Some("0A000")) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryErrorsSuiteBase.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryErrorsSuiteBase.scala index 2c2fe188e24..eb7871d5559 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryErrorsSuiteBase.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryErrorsSuiteBase.scala @@ -25,28 +25,41 @@ trait QueryErrorsSuiteBase extends SharedSparkSession { def checkErrorClass( exception: Exception with SparkThrowable, errorClass: String, + errorSubClass: Option[String] = None, msg: String, sqlState: Option[String] = None, matchMsg: Boolean = false): Unit = { assert(exception.getErrorClass === errorClass) sqlState.foreach(state => exception.getSqlState === state) + val fullErrorClass = if (errorSubClass.isDefined) { + errorClass + "." + errorSubClass.get + } else { + errorClass + } if (matchMsg) { - assert(exception.getMessage.matches(s"""\\[$errorClass\\] """ + msg)) + assert(exception.getMessage.matches(s"""\\[$fullErrorClass\\] """ + msg)) } else { - assert(exception.getMessage === s"""[$errorClass] """ + msg) + assert(exception.getMessage === s"""[$fullErrorClass] """ + msg) } } def validateParsingError( sqlText: String, errorClass: String, + errorSubClass: Option[String] = None, sqlState: String, message: String): Unit = { val e = intercept[ParseException] { sql(sqlText) } + + val fullErrorClass = if (errorSubClass.isDefined) { + errorClass + "." + errorSubClass.get + } else { + errorClass + } assert(e.getErrorClass === errorClass) assert(e.getSqlState === sqlState) - assert(e.getMessage === s"""\n[$errorClass] """ + message) + assert(e.getMessage === s"""\n[$fullErrorClass] """ + message) } } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala index f84f159f6f0..1105503e138 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryExecutionErrorsSuite.scala @@ -121,6 +121,7 @@ class QueryExecutionErrorsSuite df.collect }.getCause.asInstanceOf[SparkRuntimeException], errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("AES_MODE"), msg = """The feature is not supported: AES-\w+ with the padding \w+""" + " by the `aes_encrypt`/`aes_decrypt` function.", @@ -143,7 +144,8 @@ class QueryExecutionErrorsSuite checkErrorClass( exception = intercept[SparkRuntimeException] { lit(v) }, errorClass = "UNSUPPORTED_FEATURE", - msg = """The feature is not supported: literal for '.+' of .+\.""", + errorSubClass = Some("LITERAL_TYPE"), + msg = """The feature is not supported: Literal for '.+' of .+\.""", sqlState = Some("0A000"), matchMsg = true) } @@ -160,7 +162,8 @@ class QueryExecutionErrorsSuite checkErrorClass( exception = e2, errorClass = "UNSUPPORTED_FEATURE", - msg = "The feature is not supported: pivoting by the value" + + errorSubClass = Some("PIVOT_TYPE"), + msg = "The feature is not supported: Pivoting by the value" + """ '[dotnet,Dummies]' of the column data type "STRUCT<col1: STRING, training: STRING>".""", sqlState = Some("0A000")) } @@ -177,7 +180,8 @@ class QueryExecutionErrorsSuite checkErrorClass( exception = e1, errorClass = "UNSUPPORTED_FEATURE", - msg = """The feature is not supported: Repeated "PIVOT"s.""", + errorSubClass = Some("REPEATED_PIVOT"), + msg = "The feature is not supported: Repeated PIVOT operation.", sqlState = Some("0A000")) val e2 = intercept[SparkUnsupportedOperationException] { @@ -190,7 +194,8 @@ class QueryExecutionErrorsSuite checkErrorClass( exception = e2, errorClass = "UNSUPPORTED_FEATURE", - msg = """The feature is not supported: "PIVOT" not after a "GROUP BY".""", + errorSubClass = Some("PIVOT_AFTER_GROUP_BY"), + msg = "The feature is not supported: PIVOT clause following a GROUP BY clause.", sqlState = Some("0A000")) } diff --git a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala index 6ff737ec647..39bf469553f 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/errors/QueryParsingErrorsSuite.scala @@ -27,9 +27,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { validateParsingError( sqlText = "SELECT * FROM t1 NATURAL JOIN LATERAL (SELECT c1 + c2 AS c2)", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("LATERAL_NATURAL_JOIN"), sqlState = "0A000", message = - """The feature is not supported: "LATERAL" join with "NATURAL" join.(line 1, pos 14) + """The feature is not supported: NATURAL join with LATERAL correlation.(line 1, pos 14) | |== SQL == |SELECT * FROM t1 NATURAL JOIN LATERAL (SELECT c1 + c2 AS c2) @@ -41,9 +42,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { validateParsingError( sqlText = "SELECT * FROM t1 JOIN LATERAL (SELECT c1 + c2 AS c2) USING (c2)", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("LATERAL_JOIN_USING"), sqlState = "0A000", message = - """The feature is not supported: "LATERAL" join with "USING" join.(line 1, pos 14) + """The feature is not supported: JOIN USING with LATERAL correlation.(line 1, pos 14) | |== SQL == |SELECT * FROM t1 JOIN LATERAL (SELECT c1 + c2 AS c2) USING (c2) @@ -56,9 +58,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { validateParsingError( sqlText = s"SELECT * FROM t1 $joinType JOIN LATERAL (SELECT c1 + c2 AS c3) ON c2 = c3", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("LATERAL_JOIN_OF_TYPE"), sqlState = "0A000", message = - s"""The feature is not supported: "LATERAL" join type "$joinType".(line 1, pos 14) + s"""The feature is not supported: "$joinType" JOIN with LATERAL correlation.(line 1, pos 14) | |== SQL == |SELECT * FROM t1 $joinType JOIN LATERAL (SELECT c1 + c2 AS c3) ON c2 = c3 @@ -94,9 +97,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { validateParsingError( sqlText = "SELECT * FROM a NATURAL CROSS JOIN b", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("NATURAL_CROSS_JOIN"), sqlState = "0A000", message = - """The feature is not supported: "NATURAL CROSS JOIN".(line 1, pos 14) + """The feature is not supported: NATURAL CROSS JOIN.(line 1, pos 14) | |== SQL == |SELECT * FROM a NATURAL CROSS JOIN b @@ -150,9 +154,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { validateParsingError( sqlText = "SELECT TRANSFORM(DISTINCT a) USING 'a' FROM t", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("TRANSFORM_DISTINCT_ALL"), sqlState = "0A000", message = - """The feature is not supported: "TRANSFORM" does not support "DISTINCT"/"ALL" in inputs(line 1, pos 17) + """The feature is not supported: TRANSFORM with the DISTINCT/ALL clause.(line 1, pos 17) | |== SQL == |SELECT TRANSFORM(DISTINCT a) USING 'a' FROM t @@ -165,9 +170,10 @@ class QueryParsingErrorsSuite extends QueryTest with QueryErrorsSuiteBase { sqlText = "SELECT TRANSFORM(a) ROW FORMAT SERDE " + "'org.apache.hadoop.hive.serde2.OpenCSVSerde' USING 'a' FROM t", errorClass = "UNSUPPORTED_FEATURE", + errorSubClass = Some("TRANSFORM_NON_HIVE"), sqlState = "0A000", message = - """The feature is not supported: "TRANSFORM" with serde is only supported in hive mode(line 1, pos 0) + """The feature is not supported: TRANSFORM with SERDE is only supported in hive mode.(line 1, pos 0) | |== SQL == |SELECT TRANSFORM(a) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' USING 'a' FROM t diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkScriptTransformationSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkScriptTransformationSuite.scala index 1f431e173b3..200314dd57e 100644 --- a/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkScriptTransformationSuite.scala +++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/SparkScriptTransformationSuite.scala @@ -56,7 +56,7 @@ class SparkScriptTransformationSuite extends BaseScriptTransformationSuite with |FROM v """.stripMargin) }.getMessage - assert(e.contains("\"TRANSFORM\" with serde is only supported in hive mode")) + assert(e.contains("TRANSFORM with SERDE is only supported in hive mode.")) } } } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org For additional commands, e-mail: commits-h...@spark.apache.org