You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by ma...@apache.org on 2022/10/29 15:13:43 UTC
[spark] branch master updated: [SPARK-40752][SQL] Migrate type check failures of misc expressions onto error classes
This is an automated email from the ASF dual-hosted git repository.
maxgekk 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 2cc4e3f19bc [SPARK-40752][SQL] Migrate type check failures of misc expressions onto error classes
2cc4e3f19bc is described below
commit 2cc4e3f19bcda73fa904470842ca229762753956
Author: panbingkun <pb...@gmail.com>
AuthorDate: Sat Oct 29 18:13:00 2022 +0300
[SPARK-40752][SQL] Migrate type check failures of misc expressions onto error classes
### What changes were proposed in this pull request?
This pr replaces TypeCheckFailure by DataTypeMismatch in type checks in the misc expressions, includes:
1. Coalesce [nullExpressions.scala#L60](https://github.com/apache/spark/blob/1431975723d8df30a25b2333eddcfd0bb6c57677/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/nullExpressions.scala#L60)
2. SortOrder [SortOrder.scala#L75](https://github.com/apache/spark/blob/1431975723d8df30a25b2333eddcfd0bb6c57677/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/SortOrder.scala#L75)
3. UnwrapUDT [UnwrapUDT.scala#L36](https://github.com/apache/spark/blob/1431975723d8df30a25b2333eddcfd0bb6c57677/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDT.scala#L36)
4. ParseUrl [urlExpressions.scala#L185](https://github.com/apache/spark/blob/1431975723d8df30a25b2333eddcfd0bb6c57677/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/urlExpressions.scala#L185)
5. XPathExtract [xpath.scala#L45](https://github.com/apache/spark/blob/a241256ed0778005245253fb147db8a16105f75c/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/xml/xpath.scala#L45)
### Why are the changes needed?
Migration onto error classes unifies Spark SQL error messages.
### Does this PR introduce _any_ user-facing change?
Yes. The PR changes user-facing error messages.
### How was this patch tested?
1. Add new UT
2. Update existed UT
3. Pass GA
Closes #38350 from panbingkun/SPARK-40752.
Authored-by: panbingkun <pb...@gmail.com>
Signed-off-by: Max Gekk <ma...@gmail.com>
---
.../spark/sql/catalyst/expressions/SortOrder.scala | 10 ++---
.../spark/sql/catalyst/expressions/UnwrapUDT.scala | 12 ++++--
.../sql/catalyst/expressions/nullExpressions.scala | 13 +++++--
.../sql/catalyst/expressions/urlExpressions.scala | 9 ++++-
.../spark/sql/catalyst/expressions/xml/xpath.scala | 12 +++++-
.../sql/catalyst/analysis/AnalysisErrorSuite.scala | 8 +++-
.../analysis/ExpressionTypeCheckingSuite.scala | 12 +++++-
.../expressions/SortOrderExpressionsSuite.scala | 12 ++++++
.../expressions/StringExpressionsSuite.scala | 43 +++++++++++++++++++---
.../expressions/UnwrapUDTExpressionSuite.scala | 39 ++++++++++++++++++++
.../expressions/xml/XPathExpressionSuite.scala | 9 ++++-
.../apache/spark/sql/DataFrameFunctionsSuite.scala | 34 +++++++++++++----
12 files changed, 180 insertions(+), 33 deletions(-)
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/SortOrder.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/SortOrder.scala
index 4d35d37a414..824024a84cb 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/SortOrder.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/SortOrder.scala
@@ -21,6 +21,7 @@ import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult
import org.apache.spark.sql.catalyst.expressions.codegen.{CodegenContext, ExprCode}
import org.apache.spark.sql.catalyst.expressions.codegen.Block._
+import org.apache.spark.sql.catalyst.util.TypeUtils
import org.apache.spark.sql.types._
import org.apache.spark.unsafe.types.UTF8String
import org.apache.spark.util.collection.unsafe.sort.PrefixComparators._
@@ -68,13 +69,8 @@ case class SortOrder(
override def children: Seq[Expression] = child +: sameOrderExpressions
- override def checkInputDataTypes(): TypeCheckResult = {
- if (RowOrdering.isOrderable(dataType)) {
- TypeCheckResult.TypeCheckSuccess
- } else {
- TypeCheckResult.TypeCheckFailure(s"cannot sort data type ${dataType.catalogString}")
- }
- }
+ override def checkInputDataTypes(): TypeCheckResult =
+ TypeUtils.checkForOrderingExpr(dataType, prettyName)
override def dataType: DataType = child.dataType
override def nullable: Boolean = child.nullable
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDT.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDT.scala
index cb740672af3..d6b754a297d 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDT.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDT.scala
@@ -18,10 +18,11 @@
package org.apache.spark.sql.catalyst.expressions
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
+import org.apache.spark.sql.catalyst.expressions.Cast._
import org.apache.spark.sql.catalyst.expressions.codegen.{CodegenContext, ExprCode}
import org.apache.spark.sql.types.{DataType, UserDefinedType}
-
/**
* Unwrap UDT data type column into its underlying type.
*/
@@ -33,8 +34,13 @@ case class UnwrapUDT(child: Expression) extends UnaryExpression with NonSQLExpre
if (child.dataType.isInstanceOf[UserDefinedType[_]]) {
TypeCheckResult.TypeCheckSuccess
} else {
- TypeCheckResult.TypeCheckFailure(
- s"Input type should be UserDefinedType but got ${child.dataType.catalogString}")
+ DataTypeMismatch(
+ errorSubClass = "UNEXPECTED_INPUT_TYPE",
+ messageParameters = Map(
+ "paramIndex" -> "1",
+ "requiredType" -> toSQLType("UserDefinedType"),
+ "inputSql" -> toSQLExpr(child),
+ "inputType" -> toSQLType(child.dataType)))
}
}
override def dataType: DataType = child.dataType.asInstanceOf[UserDefinedType[_]].sqlType
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/nullExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/nullExpressions.scala
index 1e6cc356173..5e22225db1a 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/nullExpressions.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/nullExpressions.scala
@@ -19,13 +19,14 @@ package org.apache.spark.sql.catalyst.expressions
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
+import org.apache.spark.sql.catalyst.expressions.Cast._
import org.apache.spark.sql.catalyst.expressions.codegen._
import org.apache.spark.sql.catalyst.expressions.codegen.Block._
import org.apache.spark.sql.catalyst.trees.TreePattern.{COALESCE, NULL_CHECK, TreePattern}
import org.apache.spark.sql.catalyst.util.TypeUtils
import org.apache.spark.sql.types._
-
/**
* An expression that is evaluated to the first non-null input.
*
@@ -57,8 +58,14 @@ case class Coalesce(children: Seq[Expression])
override def checkInputDataTypes(): TypeCheckResult = {
if (children.length < 1) {
- TypeCheckResult.TypeCheckFailure(
- s"input to function $prettyName requires at least one argument")
+ DataTypeMismatch(
+ errorSubClass = "WRONG_NUM_ARGS",
+ messageParameters = Map(
+ "functionName" -> toSQLId(prettyName),
+ "expectedNum" -> "> 0",
+ "actualNum" -> children.length.toString
+ )
+ )
} else {
TypeUtils.checkForSameTypeInputExpr(children.map(_.dataType), prettyName)
}
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/urlExpressions.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/urlExpressions.scala
index de5fde27f6a..ac31292f032 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/urlExpressions.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/urlExpressions.scala
@@ -22,6 +22,8 @@ import java.util.regex.Pattern
import org.apache.spark.sql.catalyst.InternalRow
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
+import org.apache.spark.sql.catalyst.expressions.Cast._
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
import org.apache.spark.sql.catalyst.expressions.objects.StaticInvoke
import org.apache.spark.sql.catalyst.trees.UnaryLike
@@ -182,7 +184,12 @@ case class ParseUrl(children: Seq[Expression], failOnError: Boolean = SQLConf.ge
override def checkInputDataTypes(): TypeCheckResult = {
if (children.size > 3 || children.size < 2) {
- TypeCheckResult.TypeCheckFailure(s"$prettyName function requires two or three arguments")
+ DataTypeMismatch(
+ errorSubClass = "WRONG_NUM_ARGS",
+ messageParameters = Map(
+ "functionName" -> toSQLId(prettyName),
+ "expectedNum" -> "[2, 3]",
+ "actualNum" -> children.length.toString))
} else {
super[ExpectsInputTypes].checkInputDataTypes()
}
diff --git a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/xml/xpath.scala b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/xml/xpath.scala
index de9d1523bd3..2ed13944be9 100644
--- a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/xml/xpath.scala
+++ b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/xml/xpath.scala
@@ -18,8 +18,9 @@
package org.apache.spark.sql.catalyst.expressions.xml
import org.apache.spark.sql.catalyst.analysis.{FunctionRegistry, TypeCheckResult}
-import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.TypeCheckFailure
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
import org.apache.spark.sql.catalyst.expressions._
+import org.apache.spark.sql.catalyst.expressions.Cast._
import org.apache.spark.sql.catalyst.expressions.codegen.CodegenFallback
import org.apache.spark.sql.catalyst.util.GenericArrayData
import org.apache.spark.sql.types._
@@ -42,7 +43,14 @@ abstract class XPathExtract
override def checkInputDataTypes(): TypeCheckResult = {
if (!path.foldable) {
- TypeCheckFailure("path should be a string literal")
+ DataTypeMismatch(
+ errorSubClass = "NON_FOLDABLE_INPUT",
+ messageParameters = Map(
+ "inputName" -> "path",
+ "inputType" -> toSQLType(StringType),
+ "inputExpr" -> toSQLExpr(path)
+ )
+ )
} else {
super.checkInputDataTypes()
}
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala
index b718f410be6..d530be5f5e4 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/AnalysisErrorSuite.scala
@@ -327,10 +327,14 @@ class AnalysisErrorSuite extends AnalysisTest {
testRelation2.groupBy($"a")(sum(UnresolvedStar(None))),
"Invalid usage of '*' in expression 'sum'." :: Nil)
- errorTest(
+ errorClassTest(
"sorting by unsupported column types",
mapRelation.orderBy($"map".asc),
- "sort" :: "type" :: "map<int,int>" :: Nil)
+ errorClass = "DATATYPE_MISMATCH.INVALID_ORDERING_TYPE",
+ messageParameters = Map(
+ "sqlExpr" -> "\"map ASC NULLS FIRST\"",
+ "functionName" -> "`sortorder`",
+ "dataType" -> "\"MAP<INT, INT>\""))
errorClassTest(
"sorting by attributes are not from grouping expressions",
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
index a7cdd589606..9bc765df75e 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/analysis/ExpressionTypeCheckingSuite.scala
@@ -440,7 +440,17 @@ class ExpressionTypeCheckingSuite extends SparkFunSuite with SQLHelper with Quer
)
)
- assertError(Coalesce(Nil), "function coalesce requires at least one argument")
+ val coalesce = Coalesce(Nil)
+ checkError(
+ exception = intercept[AnalysisException] {
+ assertSuccess(coalesce)
+ },
+ errorClass = "DATATYPE_MISMATCH.WRONG_NUM_ARGS",
+ parameters = Map(
+ "sqlExpr" -> "\"coalesce()\"",
+ "functionName" -> toSQLId(coalesce.prettyName),
+ "expectedNum" -> "> 0",
+ "actualNum" -> "0"))
val murmur3Hash = new Murmur3Hash(Nil)
checkError(
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/SortOrderExpressionsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/SortOrderExpressionsSuite.scala
index 4e6976f76ea..9332ef55953 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/SortOrderExpressionsSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/SortOrderExpressionsSuite.scala
@@ -20,6 +20,7 @@ package org.apache.spark.sql.catalyst.expressions
import java.sql.Timestamp
import org.apache.spark.SparkFunSuite
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
import org.apache.spark.sql.types._
import org.apache.spark.unsafe.types.UTF8String
import org.apache.spark.util.collection.unsafe.sort.PrefixComparators._
@@ -83,4 +84,15 @@ class SortOrderExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper
checkEvaluation(SortPrefix(SortOrder(list1, Ascending)), 0L)
checkEvaluation(SortPrefix(SortOrder(nullVal, Ascending)), null)
}
+
+ test("Cannot sort map type") {
+ val m = Literal.create(Map(), MapType(StringType, StringType, valueContainsNull = false))
+ val sortOrderExpression = SortOrder(m, Ascending)
+ assert(sortOrderExpression.checkInputDataTypes() ==
+ DataTypeMismatch(
+ errorSubClass = "INVALID_ORDERING_TYPE",
+ messageParameters = Map(
+ "functionName" -> "`sortorder`",
+ "dataType" -> "\"MAP<STRING, STRING>\"")))
+ }
}
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/StringExpressionsSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/StringExpressionsSuite.scala
index f9726c4a6dd..804d9351c7f 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/StringExpressionsSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/StringExpressionsSuite.scala
@@ -1497,12 +1497,43 @@ class StringExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {
}
// arguments checking
- assert(ParseUrl(Seq(Literal("1"))).checkInputDataTypes().isFailure)
- assert(ParseUrl(Seq(Literal("1"), Literal("2"), Literal("3"), Literal("4")))
- .checkInputDataTypes().isFailure)
- assert(ParseUrl(Seq(Literal("1"), Literal(2))).checkInputDataTypes().isFailure)
- assert(ParseUrl(Seq(Literal(1), Literal("2"))).checkInputDataTypes().isFailure)
- assert(ParseUrl(Seq(Literal("1"), Literal("2"), Literal(3))).checkInputDataTypes().isFailure)
+ assert(ParseUrl(Seq(Literal("1"))).checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "WRONG_NUM_ARGS",
+ messageParameters = Map(
+ "functionName" -> "`parse_url`",
+ "expectedNum" -> "[2, 3]",
+ "actualNum" -> "1")
+ ))
+ assert(ParseUrl(Seq(Literal("1"), Literal("2"), Literal("3"),
+ Literal("4"))).checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "WRONG_NUM_ARGS",
+ messageParameters = Map(
+ "functionName" -> "`parse_url`",
+ "expectedNum" -> "[2, 3]",
+ "actualNum" -> "4")
+ ))
+ assert(ParseUrl(Seq(Literal("1"), Literal(2))).checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "UNEXPECTED_INPUT_TYPE",
+ messageParameters = Map(
+ "paramIndex" -> "2",
+ "requiredType" -> "\"STRING\"",
+ "inputSql" -> "\"2\"",
+ "inputType" -> "\"INT\"")))
+ assert(ParseUrl(Seq(Literal(1), Literal("2"))).checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "UNEXPECTED_INPUT_TYPE",
+ messageParameters = Map(
+ "paramIndex" -> "1",
+ "requiredType" -> "\"STRING\"",
+ "inputSql" -> "\"1\"",
+ "inputType" -> "\"INT\"")))
+ assert(ParseUrl(Seq(Literal("1"), Literal("2"),
+ Literal(3))).checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "UNEXPECTED_INPUT_TYPE",
+ messageParameters = Map(
+ "paramIndex" -> "3",
+ "requiredType" -> "\"STRING\"",
+ "inputSql" -> "\"3\"",
+ "inputType" -> "\"INT\"")))
// Test escaping of arguments
GenerateUnsafeProjection.generate(ParseUrl(Seq(Literal("\"quote"), Literal("\"quote"))) :: Nil)
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDTExpressionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDTExpressionSuite.scala
new file mode 100644
index 00000000000..d1b13a4bec9
--- /dev/null
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/UnwrapUDTExpressionSuite.scala
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spark.sql.catalyst.expressions
+
+import org.apache.spark.SparkFunSuite
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
+import org.apache.spark.sql.catalyst.expressions.Cast.toSQLType
+import org.apache.spark.sql.types.BooleanType
+
+class UnwrapUDTExpressionSuite extends SparkFunSuite with ExpressionEvalHelper {
+
+ test("Input type should be UserDefinedType") {
+ val b1 = Literal.create(false, BooleanType)
+ val unwrapUDTExpression = UnwrapUDT(b1)
+ assert(unwrapUDTExpression.checkInputDataTypes() ==
+ DataTypeMismatch(
+ errorSubClass = "UNEXPECTED_INPUT_TYPE",
+ messageParameters = Map(
+ "paramIndex" -> "1",
+ "requiredType" -> toSQLType("UserDefinedType"),
+ "inputSql" -> "\"false\"",
+ "inputType" -> "\"BOOLEAN\"")))
+ }
+}
diff --git a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/xml/XPathExpressionSuite.scala b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/xml/XPathExpressionSuite.scala
index c6f6d3abb86..8d9f90a1a87 100644
--- a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/xml/XPathExpressionSuite.scala
+++ b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/xml/XPathExpressionSuite.scala
@@ -18,6 +18,7 @@
package org.apache.spark.sql.catalyst.expressions.xml
import org.apache.spark.SparkFunSuite
+import org.apache.spark.sql.catalyst.analysis.TypeCheckResult.DataTypeMismatch
import org.apache.spark.sql.catalyst.expressions._
import org.apache.spark.sql.types.StringType
@@ -195,7 +196,13 @@ class XPathExpressionSuite extends SparkFunSuite with ExpressionEvalHelper {
// Validate that non-foldable paths are not supported.
val nonLitPath = exprCtor(Literal("abcd"), NonFoldableLiteral("/"))
- assert(nonLitPath.checkInputDataTypes().isFailure)
+ assert(nonLitPath.checkInputDataTypes() == DataTypeMismatch(
+ errorSubClass = "NON_FOLDABLE_INPUT",
+ messageParameters = Map(
+ "inputName" -> "path",
+ "inputType" -> "\"STRING\"",
+ "inputExpr" -> "\"nonfoldableliteral()\"")
+ ))
}
testExpr(XPathBoolean)
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameFunctionsSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameFunctionsSuite.scala
index 3adf1751818..fe843c236c3 100644
--- a/sql/core/src/test/scala/org/apache/spark/sql/DataFrameFunctionsSuite.scala
+++ b/sql/core/src/test/scala/org/apache/spark/sql/DataFrameFunctionsSuite.scala
@@ -4270,13 +4270,33 @@ class DataFrameFunctionsSuite extends QueryTest with SharedSparkSession {
test("SPARK-21281 fails if functions have no argument") {
val df = Seq(1).toDF("a")
- val funcsMustHaveAtLeastOneArg =
- ("coalesce", (df: DataFrame) => df.select(coalesce())) ::
- ("coalesce", (df: DataFrame) => df.selectExpr("coalesce()")) :: Nil
- funcsMustHaveAtLeastOneArg.foreach { case (name, func) =>
- val errMsg = intercept[AnalysisException] { func(df) }.getMessage
- assert(errMsg.contains(s"input to function $name requires at least one argument"))
- }
+ checkError(
+ exception = intercept[AnalysisException] {
+ df.select(coalesce())
+ },
+ errorClass = "DATATYPE_MISMATCH.WRONG_NUM_ARGS",
+ sqlState = None,
+ parameters = Map(
+ "sqlExpr" -> "\"coalesce()\"",
+ "functionName" -> "`coalesce`",
+ "expectedNum" -> "> 0",
+ "actualNum" -> "0"))
+
+ checkError(
+ exception = intercept[AnalysisException] {
+ df.selectExpr("coalesce()")
+ },
+ errorClass = "DATATYPE_MISMATCH.WRONG_NUM_ARGS",
+ sqlState = None,
+ parameters = Map(
+ "sqlExpr" -> "\"coalesce()\"",
+ "functionName" -> "`coalesce`",
+ "expectedNum" -> "> 0",
+ "actualNum" -> "0"),
+ context = ExpectedContext(
+ fragment = "coalesce()",
+ start = 0,
+ stop = 9))
checkError(
exception = intercept[AnalysisException] {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org