Skip to content
Snippets Groups Projects
Commit b1b4ee7f authored by Davies Liu's avatar Davies Liu Committed by Yin Huai
Browse files

[SPARK-12258][SQL] passing null into ScalaUDF

Check nullability and passing them into ScalaUDF.

Closes #10249

Author: Davies Liu <davies@databricks.com>

Closes #10259 from davies/udf_null.
parent 24d3357d
No related branches found
No related tags found
No related merge requests found
...@@ -1029,8 +1029,11 @@ case class ScalaUDF( ...@@ -1029,8 +1029,11 @@ case class ScalaUDF(
// such as IntegerType, its javaType is `int` and the returned type of user-defined // such as IntegerType, its javaType is `int` and the returned type of user-defined
// function is Object. Trying to convert an Object to `int` will cause casting exception. // function is Object. Trying to convert an Object to `int` will cause casting exception.
val evalCode = evals.map(_.code).mkString val evalCode = evals.map(_.code).mkString
val funcArguments = converterTerms.zip(evals).map { val funcArguments = converterTerms.zipWithIndex.map {
case (converter, eval) => s"$converter.apply(${eval.value})" case (converter, i) =>
val eval = evals(i)
val dt = children(i).dataType
s"$converter.apply(${eval.isNull} ? null : (${ctx.boxedType(dt)}) ${eval.value})"
}.mkString(",") }.mkString(",")
val callFunc = s"${ctx.boxedType(ctx.javaType(dataType))} $resultTerm = " + val callFunc = s"${ctx.boxedType(ctx.javaType(dataType))} $resultTerm = " +
s"(${ctx.boxedType(ctx.javaType(dataType))})${catalystConverterTerm}" + s"(${ctx.boxedType(ctx.javaType(dataType))})${catalystConverterTerm}" +
......
...@@ -1138,14 +1138,15 @@ class DataFrameSuite extends QueryTest with SharedSQLContext { ...@@ -1138,14 +1138,15 @@ class DataFrameSuite extends QueryTest with SharedSQLContext {
} }
test("SPARK-11725: correctly handle null inputs for ScalaUDF") { test("SPARK-11725: correctly handle null inputs for ScalaUDF") {
val df = Seq( val df = sparkContext.parallelize(Seq(
new java.lang.Integer(22) -> "John", new java.lang.Integer(22) -> "John",
null.asInstanceOf[java.lang.Integer] -> "Lucy").toDF("age", "name") null.asInstanceOf[java.lang.Integer] -> "Lucy")).toDF("age", "name")
// passing null into the UDF that could handle it
val boxedUDF = udf[java.lang.Integer, java.lang.Integer] { val boxedUDF = udf[java.lang.Integer, java.lang.Integer] {
(i: java.lang.Integer) => if (i == null) null else i * 2 (i: java.lang.Integer) => if (i == null) -10 else i * 2
} }
checkAnswer(df.select(boxedUDF($"age")), Row(44) :: Row(null) :: Nil) checkAnswer(df.select(boxedUDF($"age")), Row(44) :: Row(-10) :: Nil)
val primitiveUDF = udf((i: Int) => i * 2) val primitiveUDF = udf((i: Int) => i * 2)
checkAnswer(df.select(primitiveUDF($"age")), Row(44) :: Row(null) :: Nil) checkAnswer(df.select(primitiveUDF($"age")), Row(44) :: Row(null) :: Nil)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment