Repository: spark
Updated Branches:
  refs/heads/master 5f3441e54 -> 1f7e22c72


[SPARK-24951][SQL] Table valued functions should throw AnalysisException

## What changes were proposed in this pull request?
Previously TVF resolution could throw IllegalArgumentException if the data type 
is null type. This patch replaces that exception with AnalysisException, 
enriched with positional information, to improve error message reporting and to 
be more consistent with rest of Spark SQL.

## How was this patch tested?
Updated the test case in table-valued-functions.sql.out, which is how I 
identified this problem in the first place.

Author: Reynold Xin <r...@databricks.com>

Closes #21934 from rxin/SPARK-24951.


Project: http://git-wip-us.apache.org/repos/asf/spark/repo
Commit: http://git-wip-us.apache.org/repos/asf/spark/commit/1f7e22c7
Tree: http://git-wip-us.apache.org/repos/asf/spark/tree/1f7e22c7
Diff: http://git-wip-us.apache.org/repos/asf/spark/diff/1f7e22c7

Branch: refs/heads/master
Commit: 1f7e22c72c89fc2c0e729dde0948bc6bdf8f7628
Parents: 5f3441e
Author: Reynold Xin <r...@databricks.com>
Authored: Tue Jul 31 22:25:40 2018 -0700
Committer: Xiao Li <gatorsm...@gmail.com>
Committed: Tue Jul 31 22:25:40 2018 -0700

----------------------------------------------------------------------
 .../analysis/ResolveTableValuedFunctions.scala  | 34 ++++++++++++++------
 .../results/table-valued-functions.sql.out      |  9 ++++--
 2 files changed, 32 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/spark/blob/1f7e22c7/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveTableValuedFunctions.scala
----------------------------------------------------------------------
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveTableValuedFunctions.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveTableValuedFunctions.scala
index 7358f9e..983e4b0 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveTableValuedFunctions.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/analysis/ResolveTableValuedFunctions.scala
@@ -19,6 +19,7 @@ package org.apache.spark.sql.catalyst.analysis
 
 import java.util.Locale
 
+import org.apache.spark.sql.AnalysisException
 import org.apache.spark.sql.catalyst.expressions.{Alias, Expression}
 import org.apache.spark.sql.catalyst.plans.logical.{LogicalPlan, Project, 
Range}
 import org.apache.spark.sql.catalyst.rules._
@@ -68,9 +69,11 @@ object ResolveTableValuedFunctions extends Rule[LogicalPlan] 
{
       : (ArgumentList, Seq[Any] => LogicalPlan) = {
     (ArgumentList(args: _*),
      pf orElse {
-       case args =>
-         throw new IllegalArgumentException(
-           "Invalid arguments for resolved function: " + args.mkString(", "))
+       case arguments =>
+         // This is caught again by the apply function and rethrow with richer 
information about
+         // position, etc, for a better error message.
+         throw new AnalysisException(
+           "Invalid arguments for resolved function: " + arguments.mkString(", 
"))
      })
   }
 
@@ -105,22 +108,35 @@ object ResolveTableValuedFunctions extends 
Rule[LogicalPlan] {
 
   override def apply(plan: LogicalPlan): LogicalPlan = plan resolveOperators {
     case u: UnresolvedTableValuedFunction if u.functionArgs.forall(_.resolved) 
=>
+      // The whole resolution is somewhat difficult to understand here due to 
too much abstractions.
+      // We should probably rewrite the following at some point. Reynold was 
just here to improve
+      // error messages and didn't have time to do a proper rewrite.
       val resolvedFunc = 
builtinFunctions.get(u.functionName.toLowerCase(Locale.ROOT)) match {
         case Some(tvf) =>
+
+          def failAnalysis(): Nothing = {
+            val argTypes = u.functionArgs.map(_.dataType.typeName).mkString(", 
")
+            u.failAnalysis(
+              s"""error: table-valued function ${u.functionName} with 
alternatives:
+                 |${tvf.keys.map(_.toString).toSeq.sorted.map(x => s" 
($x)").mkString("\n")}
+                 |cannot be applied to: ($argTypes)""".stripMargin)
+          }
+
           val resolved = tvf.flatMap { case (argList, resolver) =>
             argList.implicitCast(u.functionArgs) match {
               case Some(casted) =>
-                Some(resolver(casted.map(_.eval())))
+                try {
+                  Some(resolver(casted.map(_.eval())))
+                } catch {
+                  case e: AnalysisException =>
+                    failAnalysis()
+                }
               case _ =>
                 None
             }
           }
           resolved.headOption.getOrElse {
-            val argTypes = u.functionArgs.map(_.dataType.typeName).mkString(", 
")
-            u.failAnalysis(
-              s"""error: table-valued function ${u.functionName} with 
alternatives:
-                |${tvf.keys.map(_.toString).toSeq.sorted.map(x => s" 
($x)").mkString("\n")}
-                |cannot be applied to: (${argTypes})""".stripMargin)
+            failAnalysis()
           }
         case _ =>
           u.failAnalysis(s"could not resolve `${u.functionName}` to a 
table-valued function")

http://git-wip-us.apache.org/repos/asf/spark/blob/1f7e22c7/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
----------------------------------------------------------------------
diff --git 
a/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out 
b/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
index a8bc6fa..94af918 100644
--- 
a/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
+++ 
b/sql/core/src/test/resources/sql-tests/results/table-valued-functions.sql.out
@@ -83,8 +83,13 @@ select * from range(1, null)
 -- !query 6 schema
 struct<>
 -- !query 6 output
-java.lang.IllegalArgumentException
-Invalid arguments for resolved function: 1, null
+org.apache.spark.sql.AnalysisException
+error: table-valued function range with alternatives:
+ (end: long)
+ (start: long, end: long)
+ (start: long, end: long, step: long)
+ (start: long, end: long, step: long, numPartitions: integer)
+cannot be applied to: (integer, null); line 1 pos 14
 
 
 -- !query 7


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@spark.apache.org
For additional commands, e-mail: commits-h...@spark.apache.org

Reply via email to