diff --git a/common/utils/src/main/resources/error/error-conditions.json b/common/utils/src/main/resources/error/error-conditions.json index b8722f26105df..31c10f9b9aaca 100644 --- a/common/utils/src/main/resources/error/error-conditions.json +++ b/common/utils/src/main/resources/error/error-conditions.json @@ -4641,6 +4641,18 @@ ], "sqlState" : "42K09" }, + "TUPLE_IS_EMPTY" : { + "message" : [ + "Due to Scala's limited support of tuple, empty tuple is not supported." + ], + "sqlState" : "22004" + }, + "TUPLE_SIZE_EXCEEDS_LIMIT" : { + "message" : [ + "Due to Scala's limited support of tuple, tuples with more than 22 elements are not supported." + ], + "sqlState" : "54011" + }, "UDTF_ALIAS_NUMBER_MISMATCH" : { "message" : [ "The number of aliases supplied in the AS clause does not match the number of columns output by the UDTF.", @@ -7249,11 +7261,6 @@ "null value found but field is not nullable." ] }, - "_LEGACY_ERROR_TEMP_2150" : { - "message" : [ - "Due to Scala's limited support of tuple, tuple with more than 22 elements are not supported." - ] - }, "_LEGACY_ERROR_TEMP_2154" : { "message" : [ "Failed to get outer pointer for ." diff --git a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/encoders/AgnosticEncoder.scala b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/encoders/AgnosticEncoder.scala index 10f734b3f84ed..9ae7de97abf58 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/catalyst/encoders/AgnosticEncoder.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/catalyst/encoders/AgnosticEncoder.scala @@ -139,7 +139,9 @@ object AgnosticEncoders { encoders: Seq[AgnosticEncoder[_]], elementsCanBeNull: Boolean = false): AgnosticEncoder[_] = { val numElements = encoders.size - if (numElements < 1 || numElements > MAX_TUPLE_ELEMENTS) { + if (numElements < 1) { + throw ExecutionErrors.emptyTupleNotSupportedError() + } else if (numElements > MAX_TUPLE_ELEMENTS) { throw ExecutionErrors.elementsOfTupleExceedLimitError() } val fields = encoders.zipWithIndex.map { case (e, id) => diff --git a/sql/api/src/main/scala/org/apache/spark/sql/errors/ExecutionErrors.scala b/sql/api/src/main/scala/org/apache/spark/sql/errors/ExecutionErrors.scala index 0ee1d7037d438..8620677654472 100644 --- a/sql/api/src/main/scala/org/apache/spark/sql/errors/ExecutionErrors.scala +++ b/sql/api/src/main/scala/org/apache/spark/sql/errors/ExecutionErrors.scala @@ -228,7 +228,11 @@ private[sql] trait ExecutionErrors extends DataTypeErrorsBase { } def elementsOfTupleExceedLimitError(): SparkUnsupportedOperationException = { - new SparkUnsupportedOperationException("_LEGACY_ERROR_TEMP_2150") + new SparkUnsupportedOperationException("TUPLE_SIZE_EXCEEDS_LIMIT") + } + + def emptyTupleNotSupportedError(): SparkUnsupportedOperationException = { + new SparkUnsupportedOperationException("TUPLE_IS_EMPTY") } def invalidAgnosticEncoderError(encoder: AnyRef): Throwable = { diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/encoders/ExpressionEncoderSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/encoders/ExpressionEncoderSuite.scala index 3b5cbed2cc527..77c9672fd9574 100644 --- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/encoders/ExpressionEncoderSuite.scala +++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/encoders/ExpressionEncoderSuite.scala @@ -518,7 +518,18 @@ class ExpressionEncoderSuite extends CodegenInterpretedPlanTest with AnalysisTes exception = intercept[SparkUnsupportedOperationException] { Encoders.tupleEncoder(encoders: _*) }, - condition = "_LEGACY_ERROR_TEMP_2150", + condition = "TUPLE_SIZE_EXCEEDS_LIMIT", + parameters = Map.empty) + } + + test("throw exception for empty tuple") { + val encoders = Seq.empty[Encoder[Int]] + + checkError( + exception = intercept[SparkUnsupportedOperationException] { + Encoders.tupleEncoder(encoders: _*) + }, + condition = "TUPLE_IS_EMPTY", parameters = Map.empty) }