Skip to content
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions core/src/main/resources/error/error-classes.json
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,11 @@
],
"sqlState" : "22023"
},
"INVALID_FUNCTION_ARGS" : {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about to introduce sub-classes of WRONG_NUM_ARGS:

  • WITHOUT_SUGGESTION
  • WITH_SUGGESTION

And declare in the common message template that

Invalid number of arguments for the function <funcName>.

"message" : [
"Invalid arguments for function <name>."
]
},
"INVALID_IDENTIFIER" : {
"message" : [
"The identifier <ident> is invalid. Please, consider quoting it with back-quotes as `<ident>`."
Expand Down Expand Up @@ -2006,11 +2011,6 @@
"Undefined function <name>."
]
},
"_LEGACY_ERROR_TEMP_1043" : {
"message" : [
"Invalid arguments for function <name>."
]
},
"_LEGACY_ERROR_TEMP_1045" : {
"message" : [
"ALTER TABLE SET LOCATION does not support partition for v2 tables."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,10 +649,10 @@ private[sql] object QueryCompilationErrors extends QueryErrorsBase {

def invalidFunctionArgumentNumberError(
validParametersCount: Seq[Int], name: String, actualNumber: Int): Throwable = {
if (validParametersCount.length == 0) {
if (validParametersCount.isEmpty) {
new AnalysisException(
errorClass = "_LEGACY_ERROR_TEMP_1043",
messageParameters = Map("name" -> name))
errorClass = "INVALID_FUNCTION_ARGS",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MaxGekk This should be an internal exception?

@LuciferYang LuciferYang Dec 8, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be triggered by the user action, such as SELECT CAST(1) in UDFSuite.scala

messageParameters = Map("name" -> toSQLId(name)))
} else {
val expectedNumberOfParameters = if (validParametersCount.length == 1) {
validParametersCount.head.toString
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ class DateFunctionsSuite extends QueryTest with SharedSparkSession {
sql("""SELECT CURDATE()""").collect().head.getDate(0))
val d4 = DateTimeUtils.currentDate(ZoneId.systemDefault())
assert(d0 <= d1 && d1 <= d2 && d2 <= d3 && d3 <= d4 && d4 - d0 <= 1)

checkError(
exception = intercept[AnalysisException] {
sql("SELECT CURDATE(1)")
},
errorClass = "INVALID_FUNCTION_ARGS",
parameters = Map(
"name" -> "`curdate`"
),
context = ExpectedContext("", "", 7, 16, "CURDATE(1)")
)
}

test("function current_timestamp and now") {
Expand Down
14 changes: 10 additions & 4 deletions sql/core/src/test/scala/org/apache/spark/sql/UDFSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -638,10 +638,16 @@ class UDFSuite extends QueryTest with SharedSparkSession {
}

test("SPARK-28521 error message for CAST(parameter types contains DataType)") {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this test to QueryCompilationsErrorsSuite

val e = intercept[AnalysisException] {
spark.sql("SELECT CAST(1)")
}
assert(e.getMessage.contains("Invalid arguments for function cast"))
checkError(
exception = intercept[AnalysisException] {
sql("SELECT CAST(1)")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Otherwise, find a constructor method that matches the number of arguments, and use that.
val params = Seq.fill(expressions.size)(classOf[Expression])
val f = constructors.find(_.getParameterTypes.toSeq == params).getOrElse {
val validParametersCount = constructors
.filter(_.getParameterTypes.forall(_ == classOf[Expression]))
.map(_.getParameterCount).distinct.sorted
throw QueryCompilationErrors.invalidFunctionArgumentNumberError(
validParametersCount, name, params.length)

In this scenario, the validParametersCount is also empty, so WRONG_NUM_ARGS cannot be reused now

@LuciferYang LuciferYang Dec 7, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any suggestions on the calculation way of validParametersCount @MaxGekk ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code above is not correct actually in some cases. One more example is TimestampAdd:

case class TimestampAdd(
unit: String,
quantity: Expression,
timestamp: Expression,

},
errorClass = "INVALID_FUNCTION_ARGS",
parameters = Map(
"name" -> "`cast`"
),
context = ExpectedContext("", "", 7, 13, "CAST(1)")
)
}

test("only one case class parameter") {
Expand Down