-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-10049][SPARKR] Support collecting data of ArraryType in DataFrame. #8458
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
1f7ab95
e3af422
9b5bd05
02c64eb
2bc97ad
a1f4fcb
1e223e0
adde91f
a7aa017
afad2c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…ame.
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,29 +125,41 @@ private[r] class RBackendHandler(server: RBackend) | |
| val methods = cls.getMethods | ||
| val selectedMethods = methods.filter(m => m.getName == methodName) | ||
| if (selectedMethods.length > 0) { | ||
| val methods = selectedMethods.filter { x => | ||
| matchMethod(numArgs, args, x.getParameterTypes) | ||
| } | ||
| if (methods.isEmpty) { | ||
| val (index, convertedArgs) = matchMethod( | ||
| selectedMethods.map(_.getParameterTypes), | ||
| args) | ||
|
|
||
| if (index.isEmpty) { | ||
| logWarning(s"cannot find matching method ${cls}.$methodName. " | ||
| + s"Candidates are:") | ||
| selectedMethods.foreach { method => | ||
| logWarning(s"$methodName(${method.getParameterTypes.mkString(",")})") | ||
| } | ||
| throw new Exception(s"No matched method found for $cls.$methodName") | ||
| } | ||
| val ret = methods.head.invoke(obj, args : _*) | ||
|
|
||
| val ret = selectedMethods(index.get).invoke(obj, convertedArgs : _*) | ||
|
|
||
| // Write status bit | ||
| writeInt(dos, 0) | ||
| writeObject(dos, ret.asInstanceOf[AnyRef]) | ||
| } else if (methodName == "<init>") { | ||
| // methodName should be "<init>" for constructor | ||
| val ctor = cls.getConstructors.filter { x => | ||
| matchMethod(numArgs, args, x.getParameterTypes) | ||
| }.head | ||
| val ctors = cls.getConstructors | ||
| val (index, convertedArgs) = matchMethod( | ||
| ctors.map(_.getParameterTypes), | ||
| args) | ||
|
|
||
| if (index.isEmpty) { | ||
| logWarning(s"cannot find matching constructor for ${cls}. " | ||
| + s"Candidates are:") | ||
| ctors.foreach { ctor => | ||
| logWarning(s"$cls(${ctor.getParameterTypes.mkString(",")})") | ||
| } | ||
| throw new Exception(s"No matched constructor found for $cls") | ||
| } | ||
|
|
||
| val obj = ctor.newInstance(args : _*) | ||
| val obj = ctors(index.get).newInstance(convertedArgs : _*) | ||
|
|
||
| writeInt(dos, 0) | ||
| writeObject(dos, obj.asInstanceOf[AnyRef]) | ||
|
|
@@ -171,35 +183,53 @@ private[r] class RBackendHandler(server: RBackend) | |
| }.toArray | ||
| } | ||
|
|
||
| // Checks if the arguments passed in args matches the parameter types. | ||
| // NOTE: Currently we do exact match. We may add type conversions later. | ||
| // Find a matching method in all methods of the same name of a class | ||
| // according to the passed arguments. | ||
| def matchMethod( | ||
| numArgs: Int, | ||
| args: Array[java.lang.Object], | ||
| parameterTypes: Array[Class[_]]): Boolean = { | ||
| if (parameterTypes.length != numArgs) { | ||
| return false | ||
| } | ||
| parameterTypesOfMethods: Array[Array[Class[_]]], | ||
| args: Array[Object]): (Option[Int], Array[Object]) = { | ||
| val numArgs = args.length | ||
|
|
||
| for (index <- 0 to parameterTypesOfMethods.length - 1) { | ||
|
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. 0 until xxx
Contributor
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. fixed |
||
| val parameterTypes = parameterTypesOfMethods(index) | ||
|
|
||
| if (parameterTypes.length == numArgs) { | ||
| val convertedArgs = new Array[Object](numArgs) | ||
|
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. Is there any reason we shouldn't modify
Contributor
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. Arg is checked and converted one by one when matching a method. It is possible that after some args were converted, an arg fails, then all args have to be reverted to the original ones for matching next method. It could be possible for now that checking all args for one method, and only after the checking passes, then do conversion, thus we can modify args in place. I will refine the code. |
||
| Array.copy(args, 0, convertedArgs, 0, numArgs) | ||
|
|
||
| var argMatched = true | ||
| var i = 0 | ||
| while (i < numArgs && argMatched) { | ||
| val parameterType = parameterTypes(i) | ||
| var parameterWrapperType = parameterType | ||
|
|
||
| // Convert native parameters to Object types as args is Array[Object] here | ||
| if (parameterType.isPrimitive) { | ||
| parameterWrapperType = parameterType match { | ||
| case java.lang.Integer.TYPE => classOf[java.lang.Integer] | ||
| case java.lang.Long.TYPE => classOf[java.lang.Integer] | ||
| case java.lang.Double.TYPE => classOf[java.lang.Double] | ||
| case java.lang.Boolean.TYPE => classOf[java.lang.Boolean] | ||
| case _ => parameterType | ||
| } | ||
| } else if (parameterType == classOf[Seq[Any]] && args(i).getClass.isArray) { | ||
| // Convert a Java array to scala Seq | ||
| convertedArgs(i) = args(i).asInstanceOf[Array[_]].toSeq | ||
| } | ||
| if (!parameterWrapperType.isInstance(convertedArgs(i))) { | ||
| argMatched = false | ||
| } | ||
| i = i + 1 | ||
| } | ||
|
|
||
| for (i <- 0 to numArgs - 1) { | ||
| val parameterType = parameterTypes(i) | ||
| var parameterWrapperType = parameterType | ||
|
|
||
| // Convert native parameters to Object types as args is Array[Object] here | ||
| if (parameterType.isPrimitive) { | ||
| parameterWrapperType = parameterType match { | ||
| case java.lang.Integer.TYPE => classOf[java.lang.Integer] | ||
| case java.lang.Long.TYPE => classOf[java.lang.Integer] | ||
| case java.lang.Double.TYPE => classOf[java.lang.Double] | ||
| case java.lang.Boolean.TYPE => classOf[java.lang.Boolean] | ||
| case _ => parameterType | ||
| if (argMatched) { | ||
| // For now, we return the first matching method. | ||
| // TODO: find best method in matching methods. | ||
| return (Some(index), convertedArgs) | ||
| } | ||
| } | ||
| if (!parameterWrapperType.isInstance(args(i))) { | ||
| return false | ||
| } | ||
| } | ||
| true | ||
| (None, args) | ||
| } | ||
| } | ||
|
|
||
|
|
||
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.
Could you also document what the returned objects are for this method ?
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.
sure. will add.