-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-32243][SQL]HiveSessionCatalog call super.makeFunctionExpression should throw earlier when got Spark UDAF Invalid arguments number error #29054
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
5dd3169
4e6b506
91ceea0
8c3faed
b813656
1397c66
7f9900b
9ae1614
918aea4
3df37d2
766c931
a8549c4
95cfebe
34a3b98
2db41fc
3d9b6e3
42064d7
36229e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,49 +69,56 @@ private[sql] class HiveSessionCatalog( | |
| // Current thread context classloader may not be the one loaded the class. Need to switch | ||
| // context classloader to initialize instance properly. | ||
| Utils.withContextClassLoader(clazz.getClassLoader) { | ||
| Try(super.makeFunctionExpression(name, clazz, input)).getOrElse { | ||
| var udfExpr: Option[Expression] = None | ||
| try { | ||
| // When we instantiate hive UDF wrapper class, we may throw exception if the input | ||
| // expressions don't satisfy the hive UDF, such as type mismatch, input number | ||
| // mismatch, etc. Here we catch the exception and throw AnalysisException instead. | ||
| if (classOf[UDF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveSimpleUDF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[GenericUDF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveGenericUDF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[AbstractGenericUDAFResolver].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveUDAFFunction(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[UDAF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveUDAFFunction( | ||
| name, | ||
| new HiveFunctionWrapper(clazz.getName), | ||
| input, | ||
| isUDAFBridgeRequired = true)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[GenericUDTF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveGenericUDTF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.asInstanceOf[HiveGenericUDTF].elementSchema // Force it to check data types. | ||
| Try(super.makeFunctionExpression(name, clazz, input)) match { | ||
|
||
| case Success(value) => value | ||
| case Failure(exception) => | ||
| val superError = | ||
| s"Make Expression failed in SessionCatalog for function name = ${name}:" + | ||
| s" ${exception.getMessage}" | ||
| var udfExpr: Option[Expression] = None | ||
|
||
| try { | ||
| // When we instantiate hive UDF wrapper class, we may throw exception if the input | ||
| // expressions don't satisfy the hive UDF, such as type mismatch, input number | ||
| // mismatch, etc. Here we catch the exception and throw AnalysisException instead. | ||
| if (classOf[UDF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveSimpleUDF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[GenericUDF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveGenericUDF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[AbstractGenericUDAFResolver].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveUDAFFunction(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[UDAF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveUDAFFunction( | ||
| name, | ||
| new HiveFunctionWrapper(clazz.getName), | ||
| input, | ||
| isUDAFBridgeRequired = true)) | ||
| udfExpr.get.dataType // Force it to check input data types. | ||
| } else if (classOf[GenericUDTF].isAssignableFrom(clazz)) { | ||
| udfExpr = Some(HiveGenericUDTF(name, new HiveFunctionWrapper(clazz.getName), input)) | ||
| // Force it to check data types. | ||
| udfExpr.get.asInstanceOf[HiveGenericUDTF].elementSchema | ||
| } | ||
| } catch { | ||
| case NonFatal(e) => | ||
| val noHandlerMsg = s"No handler for UDF/UDAF/UDTF '${clazz.getCanonicalName}': $e" | ||
| val errorMsg = | ||
| if (classOf[GenericUDTF].isAssignableFrom(clazz)) { | ||
| s"$noHandlerMsg\nPlease make sure your function overrides " + | ||
| "`public StructObjectInspector initialize(ObjectInspector[] args)`." | ||
| } else { | ||
| noHandlerMsg | ||
| } | ||
| val analysisException = new AnalysisException(s"1. $superError\n2. $errorMsg") | ||
| analysisException.setStackTrace(e.getStackTrace) | ||
| throw analysisException | ||
| } | ||
| udfExpr.getOrElse { | ||
| throw new AnalysisException( | ||
| s"1. $superError\n2. No handler for UDF/UDAF/UDTF '${clazz.getCanonicalName}'") | ||
| } | ||
| } catch { | ||
| case NonFatal(e) => | ||
| val noHandlerMsg = s"No handler for UDF/UDAF/UDTF '${clazz.getCanonicalName}': $e" | ||
| val errorMsg = | ||
| if (classOf[GenericUDTF].isAssignableFrom(clazz)) { | ||
| s"$noHandlerMsg\nPlease make sure your function overrides " + | ||
| "`public StructObjectInspector initialize(ObjectInspector[] args)`." | ||
| } else { | ||
| noHandlerMsg | ||
| } | ||
| val analysisException = new AnalysisException(errorMsg) | ||
| analysisException.setStackTrace(e.getStackTrace) | ||
| throw analysisException | ||
| } | ||
| udfExpr.getOrElse { | ||
| throw new AnalysisException(s"No handler for UDF/UDAF/UDTF '${clazz.getCanonicalName}'") | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -161,6 +161,21 @@ class HiveUDAFSuite extends QueryTest | |
| checkAnswer(sql("select histogram_numeric(a,2) from abc where a=3"), Row(null)) | ||
| } | ||
| } | ||
|
|
||
| test("Hive mode use spark udaf should show error") { | ||
|
||
| val functionName = "longProductSum" | ||
| val functionClass = "org.apache.spark.sql.hive.execution.LongProductSum" | ||
| withUserDefinedFunction(functionName -> true) { | ||
| sql(s"CREATE TEMPORARY FUNCTION $functionName AS '$functionClass'") | ||
| val e1 = intercept[AnalysisException] { | ||
|
||
| sql(s"SELECT $functionName(100)") | ||
| }.getMessage | ||
| assert( | ||
| Seq(s"Invalid number of arguments for function $functionName. Expected: 2; Found: 1;", | ||
| "No handler for UDF/UDAF/UDTF 'org.apache.spark.sql.hive.execution.LongProductSum';") | ||
| .forall(e1.contains)) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AngersZhuuuu, can you get rid of this unrelated diffs?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about current change, it won't change indentation. cc @maropu