-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-23593][SQL] Add interpreted execution for InitializeJavaBean expression #20756
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 4 commits
978080b
0c48a9b
b8f171e
b51303a
6372f04
970ed6c
e20c207
f3fdf57
1a78334
e7640e1
0d6b3d3
2954e8d
96a8fe6
573db59
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 |
|---|---|---|
|
|
@@ -1261,8 +1261,31 @@ case class InitializeJavaBean(beanInstance: Expression, setters: Map[String, Exp | |
| override def children: Seq[Expression] = beanInstance +: setters.values.toSeq | ||
| override def dataType: DataType = beanInstance.dataType | ||
|
|
||
| override def eval(input: InternalRow): Any = | ||
| throw new UnsupportedOperationException("Only code-generated evaluation is supported.") | ||
| private lazy val resolvedSetters = { | ||
| val ObjectType(beanClass) = beanInstance.dataType | ||
|
|
||
| setters.map { case (setterMethod, fieldExpr) => | ||
| val foundMethods = beanClass.getMethods.filter { method => | ||
|
||
| method.getName == setterMethod && Modifier.isPublic(method.getModifiers) && | ||
| method.getParameterTypes.length == 1 | ||
| } | ||
| assert(foundMethods.length == 1, | ||
| throw new RuntimeException("The Java Bean class should have only one " + | ||
| s"setter $setterMethod method, but ${foundMethods.length} methods found.")) | ||
| (foundMethods.head, fieldExpr) | ||
| } | ||
| } | ||
|
|
||
| override def eval(input: InternalRow): Any = { | ||
| val instance = beanInstance.eval(input).asInstanceOf[Object] | ||
|
||
| if (instance != null) { | ||
| resolvedSetters.foreach { case (setterMethod, fieldExpr) => | ||
| val fieldValue = fieldExpr.eval(input).asInstanceOf[Object] | ||
| setterMethod.invoke(instance, fieldValue) | ||
| } | ||
| } | ||
| instance | ||
| } | ||
|
|
||
| override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = { | ||
| val instanceGen = beanInstance.genCode(ctx) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,7 +49,8 @@ trait ExpressionEvalHelper extends GeneratorDrivenPropertyChecks { | |
| expression: => Expression, expected: Any, inputRow: InternalRow = EmptyRow): Unit = { | ||
| val serializer = new JavaSerializer(new SparkConf()).newInstance | ||
| val resolver = ResolveTimeZone(new SQLConf) | ||
| val expr = resolver.resolveTimeZones(serializer.deserialize(serializer.serialize(expression))) | ||
| // Make it as method to obtain fresh expression everytime. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this change?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The content of bean instance will be changed after first evaluation of interpreted execution. For example, in the added unit test, the input bean of the later evaluation will become
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we using a literal? Ok, makes sense. |
||
| def expr = resolver.resolveTimeZones(serializer.deserialize(serializer.serialize(expression))) | ||
| val catalystValue = CatalystTypeConverters.convertToCatalyst(expected) | ||
| checkEvaluationWithoutCodegen(expr, catalystValue, inputRow) | ||
| checkEvaluationWithGeneratedMutableProjection(expr, catalystValue, inputRow) | ||
|
|
||
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.
better to put
assert(beanInstance.dataType.isInstanceOf[ObjectType])in the constructor?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.
Ok.