Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,9 @@ object FunctionRegistry {
val validParametersCount = constructors
.filter(_.getParameterTypes.forall(_ == classOf[Expression]))
Copy link
Member

Choose a reason for hiding this comment

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

If we remove this line, what is the outcome?

In this PR, the logic is to add a special case. When unable to find a constructor whose parameters are all Expressions, we use the remaining constructors. [Note, headOption means we only choose the first one] Could you please check whether we should list all of them in the error messages?

Copy link
Member Author

Choose a reason for hiding this comment

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

If we remove this line, it works fine. I did this in the first commit of the pr, discussed with HyukjinKwon here

Copy link
Member

Choose a reason for hiding this comment

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

No, It doesn't work fine.
We should only recognise the constructor with expressions because those are only able to be used in SQL. Otherwise, it shows incorrect information about possible argument combination which partially reverts #21226.

Copy link
Member

Choose a reason for hiding this comment

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

The problem is that we have function registered in but that's unable/not supposed to to call via in(...) currently. Possibly there might be more cases like this.

.map(_.getParameterCount).distinct.sorted
val expectedNumberOfParameters = if (validParametersCount.length == 1) {
val expectedNumberOfParameters = if (validParametersCount.isEmpty) {
constructors.headOption.map(_.getParameterCount).getOrElse(0).toString
Copy link
Member

@gatorsmile gatorsmile Jul 22, 2019

Choose a reason for hiding this comment

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

Using headIption is hacky. We should follow the same logic what we are doing here.

} else if (validParametersCount.length == 1) {
Copy link
Member

Choose a reason for hiding this comment

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

@yaooqinn, can you show the error message before and after this change, and fix the PR description and title? I think this PR now targets throw a better exception for the expression that has no constructors to call.

validParametersCount.head.toString
} else {
validParametersCount.init.mkString("one of ", ", ", " and ") +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ class SQLQuerySuite extends QueryTest with SharedSQLContext {
checkKeywordsExist(sql("describe functioN abcadf"), "Function: abcadf not found.")
}

test("SPARK-28143: IN expression missing attribute should throw analysis exception") {
// missing attribute, which actually might be `select 1 where a in ()`
val query = "select 1 where in ()"
val e = intercept[AnalysisException](sql(query))
assert(e.getMessage.startsWith("Invalid number of arguments for function in"))
}

test("SPARK-14415: All functions should have own descriptions") {
for (f <- spark.sessionState.functionRegistry.listFunction()) {
if (!Seq("cube", "grouping", "grouping_id", "rollup", "window").contains(f.unquotedString)) {
Expand Down