diff --git a/core/src/main/resources/error/error-classes.json b/core/src/main/resources/error/error-classes.json index d6e510f659c99..9587d494dda3f 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: " ], + "message" : [ "The feature is not supported: " ], + "subClass" : { + "AES_MODE" : { + "message" : [ "AES- with the padding by the function." ] + }, + "DISTRIBUTE_BY" : { + "message" : [ "DISTRIBUTE BY clause." ] + }, + "INSERT_PARTITION_SPEC_IF_NOT_EXISTS" : { + "message" : [ "INSERT INTO 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" : [ " 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 '' of ." ] + }, + "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 '' of the column data type ." ] + }, + "PYTHON_UDF_IN_ON_CLAUSE" : { + "message" : [ "Python UDF in the ON clause of a JOIN." ] + }, + "REPEATED_PIVOT" : { + "message" : [ "Repeated PIVOT operation." ] + }, + "TOO_MANY_TYPE_ARGUMENTS_FOR_UDF_CLASS" : { + "message" : [ "UDF class with 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 bed05b7ab39f9..a21f33e8833a1 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 e40c3ba0d6479..52f8814b26999 100644 --- a/python/pyspark/sql/tests/test_udf.py +++ b/python/pyspark/sql/tests/test_udf.py @@ -258,8 +258,7 @@ def test_udf_not_supported_in_join_condition(self): 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 586f32dd4fc05..7f212ed5891c8 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 c73b78b264c55..6deb657794806 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 @@ -231,14 +231,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 = { @@ -757,8 +757,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 = { @@ -1884,13 +1883,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") @@ -1907,8 +1906,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 06030fb53f32f..ed5773f4f8240 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 f69f782a0a7de..b862416ff0718 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 77fa99b14509b..b8c57753209c3 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 7b00ab1cb92ce..625607a8db067 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 3d0fdc81b3614..6d7d112b35224 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 9fedf14a2a1dc..f51ec15dce573 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 862255b7d12a1..0145457aed87b 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 2c2fe188e245a..eb7871d5559e5 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 418b5d211d6c2..5c73ff21eca18 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".""", 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 6ff737ec64753..39bf469553f74 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 1f431e173b3c7..200314dd57ea1 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.")) } } }