This is an automated email from the ASF dual-hosted git repository.

yangjie01 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 a84e2b1eee3 [SPARK-44525][SQL] Improve error message when Invoke 
method is not found
a84e2b1eee3 is described below

commit a84e2b1eee3bb868f140bffeba4e19b1a56fa3fb
Author: Cheng Pan <cheng...@apache.org>
AuthorDate: Wed Jul 26 16:34:08 2023 +0800

    [SPARK-44525][SQL] Improve error message when Invoke method is not found
    
    ### What changes were proposed in this pull request?
    
    This PR aims to improve the error message when `Invoke`'s `method` is not 
found.
    
    ### Why are the changes needed?
    
    Currently, the error message is not clear when `Invoke`'s `method` is not 
found.
    
    There is one error message I have encountered, which is not much helpful to 
find the root cause.
    ```
    org.apache.spark.SparkException: [INTERNAL_ERROR] A method named "invoke" 
is not declared in any enclosing class nor any supertype
            at 
org.apache.spark.SparkException$.internalError(SparkException.scala:77)
            at 
org.apache.spark.SparkException$.internalError(SparkException.scala:81)
            at 
org.apache.spark.sql.errors.QueryExecutionErrors$.methodNotDeclaredError(QueryExecutionErrors.scala:452)
            at 
org.apache.spark.sql.catalyst.expressions.objects.InvokeLike.findMethod(objects.scala:173)
            at 
org.apache.spark.sql.catalyst.expressions.objects.InvokeLike.findMethod$(objects.scala:170)
            at 
org.apache.spark.sql.catalyst.expressions.objects.Invoke.findMethod(objects.scala:363)
            at 
org.apache.spark.sql.catalyst.expressions.objects.Invoke.method$lzycompute(objects.scala:391)
            at 
org.apache.spark.sql.catalyst.expressions.objects.Invoke.method(objects.scala:389)
            at 
org.apache.spark.sql.catalyst.expressions.objects.Invoke.eval(objects.scala:401)
            at 
org.apache.spark.sql.catalyst.expressions.HashExpression.eval(hash.scala:292)
            at 
org.apache.spark.sql.catalyst.expressions.Pmod.eval(arithmetic.scala:1054)
    ```
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes, Spark returns a more clear error message.
    
    ### How was this patch tested?
    
    Add UT.
    
    Closes #42128 from pan3793/SPARK-44525.
    
    Authored-by: Cheng Pan <cheng...@apache.org>
    Signed-off-by: yangjie01 <yangji...@baidu.com>
---
 .../sql/catalyst/expressions/objects/objects.scala |  2 +-
 .../spark/sql/errors/QueryExecutionErrors.scala    |  9 ++++++
 .../expressions/ObjectExpressionsSuite.scala       | 34 +++++++++++++++++++++-
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/objects/objects.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/objects/objects.scala
index fec60aef1bf..32bcdaf8609 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/objects/objects.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/objects/objects.scala
@@ -185,7 +185,7 @@ trait InvokeLike extends Expression with NonSQLExpression 
with ImplicitCastInput
   final def findMethod(cls: Class[_], functionName: String, argClasses: 
Seq[Class[_]]): Method = {
     val method = MethodUtils.getMatchingAccessibleMethod(cls, functionName, 
argClasses: _*)
     if (method == null) {
-      throw QueryExecutionErrors.methodNotDeclaredError(functionName)
+      throw QueryExecutionErrors.methodNotFoundError(cls, functionName, 
argClasses)
     } else {
       method
     }
diff --git 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
index 3fb14cd079f..7ddb6ee982e 100644
--- 
a/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
+++ 
b/sql/catalyst/src/main/scala/org/apache/spark/sql/errors/QueryExecutionErrors.scala
@@ -464,6 +464,15 @@ private[sql] object QueryExecutionErrors extends 
QueryErrorsBase {
       s"""A method named "$name" is not declared in any enclosing class nor 
any supertype""")
   }
 
+  def methodNotFoundError(
+      cls: Class[_],
+      functionName: String,
+      argClasses: Seq[Class[_]]): Throwable = {
+    SparkException.internalError(
+      s"Couldn't find method $functionName with arguments " +
+        s"${argClasses.mkString("(", ", ", ")")} on $cls.")
+  }
+
   def constructorNotFoundError(cls: String): SparkRuntimeException = {
     new SparkRuntimeException(
       errorClass = "_LEGACY_ERROR_TEMP_2020",
diff --git 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ObjectExpressionsSuite.scala
 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ObjectExpressionsSuite.scala
index 63edba80ec8..73da5f4d3af 100644
--- 
a/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ObjectExpressionsSuite.scala
+++ 
b/sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/ObjectExpressionsSuite.scala
@@ -25,7 +25,7 @@ import scala.reflect.ClassTag
 import scala.reflect.runtime.universe.TypeTag
 import scala.util.Random
 
-import org.apache.spark.{SparkConf, SparkFunSuite, SparkRuntimeException}
+import org.apache.spark.{SparkConf, SparkException, SparkFunSuite, 
SparkRuntimeException}
 import org.apache.spark.serializer.{JavaSerializer, KryoSerializer}
 import org.apache.spark.sql.{RandomDataGenerator, Row}
 import org.apache.spark.sql.catalyst.{CatalystTypeConverters, InternalRow, 
ScalaReflection, ScroogeLikeExample}
@@ -73,6 +73,38 @@ class ObjectExpressionsSuite extends SparkFunSuite with 
ExpressionEvalHelper {
     checkEvaluationWithMutableProjection(invoke, null, inputRow)
   }
 
+  test("SPARK-44525: Invoke could not find method") {
+    val inputRow = InternalRow(new Object)
+    val inputObject = BoundReference(0, ObjectType(classOf[Object]), nullable 
= false)
+
+    checkError(
+      exception = intercept[SparkException] {
+        Invoke(inputObject, "zeroArgNotExistMethod", 
IntegerType).eval(inputRow)
+      },
+      errorClass = "INTERNAL_ERROR",
+      parameters = Map("message" ->
+        ("Couldn't find method zeroArgNotExistMethod with arguments " +
+          "() on class java.lang.Object.")
+      )
+    )
+
+    checkError(
+      exception = intercept[SparkException] {
+        Invoke(
+          inputObject,
+          "oneArgNotExistMethod",
+          IntegerType,
+          Seq(Literal.fromObject(UTF8String.fromString("dummyInputString"))),
+          Seq(StringType)).eval(inputRow)
+      },
+      errorClass = "INTERNAL_ERROR",
+      parameters = Map("message" ->
+        ("Couldn't find method oneArgNotExistMethod with arguments " +
+          "(class org.apache.spark.unsafe.types.UTF8String) on class 
java.lang.Object.")
+      )
+    )
+  }
+
   test("MapObjects should make copies of unsafe-backed data") {
     // test UnsafeRow-backed data
     val structEncoder = ExpressionEncoder[Array[Tuple2[java.lang.Integer, 
java.lang.Integer]]]


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

Reply via email to