Skip to content

Commit 4cb2ff9

Browse files
kiszkueshin
authored andcommitted
[SPARK-25310][SQL] ArraysOverlap may throw a CompilationException
## What changes were proposed in this pull request? This PR fixes a problem that `ArraysOverlap` function throws a `CompilationException` with non-nullable array type. The following is the stack trace of the original problem: ``` Code generation of arrays_overlap([1,2,3], [4,5,3]) failed: java.util.concurrent.ExecutionException: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 56, Column 11: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 56, Column 11: Expression "isNull_0" is not an rvalue java.util.concurrent.ExecutionException: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 56, Column 11: failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 56, Column 11: Expression "isNull_0" is not an rvalue at com.google.common.util.concurrent.AbstractFuture$Sync.getValue(AbstractFuture.java:306) at com.google.common.util.concurrent.AbstractFuture$Sync.get(AbstractFuture.java:293) at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:116) at com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly(Uninterruptibles.java:135) at com.google.common.cache.LocalCache$Segment.getAndRecordStats(LocalCache.java:2410) at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2380) at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2342) at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2257) at com.google.common.cache.LocalCache.get(LocalCache.java:4000) at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4004) at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4874) at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator$.compile(CodeGenerator.scala:1305) at org.apache.spark.sql.catalyst.expressions.codegen.GenerateMutableProjection$.create(GenerateMutableProjection.scala:143) at org.apache.spark.sql.catalyst.expressions.codegen.GenerateMutableProjection$.create(GenerateMutableProjection.scala:48) at org.apache.spark.sql.catalyst.expressions.codegen.GenerateMutableProjection$.create(GenerateMutableProjection.scala:32) at org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator.generate(CodeGenerator.scala:1260) ``` ## How was this patch tested? Added test in `CollectionExpressionSuite`. Closes apache#22317 from kiszk/SPARK-25310. Authored-by: Kazuaki Ishizaki <[email protected]> Signed-off-by: Takuya UESHIN <[email protected]>
1 parent b60ee3a commit 4cb2ff9

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/collectionOperations.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,12 +1636,13 @@ case class ArraysOverlap(left: Expression, right: Expression)
16361636
val set = ctx.freshName("set")
16371637
val addToSetFromSmallerCode = nullSafeElementCodegen(
16381638
smaller, i, s"$set.add($getFromSmaller);", s"${ev.isNull} = true;")
1639+
val setIsNullCode = if (nullable) s"${ev.isNull} = false;" else ""
16391640
val elementIsInSetCode = nullSafeElementCodegen(
16401641
bigger,
16411642
i,
16421643
s"""
16431644
|if ($set.contains($getFromBigger)) {
1644-
| ${ev.isNull} = false;
1645+
| $setIsNullCode
16451646
| ${ev.value} = true;
16461647
| break;
16471648
|}
@@ -1666,12 +1667,13 @@ case class ArraysOverlap(left: Expression, right: Expression)
16661667
val j = ctx.freshName("j")
16671668
val getFromSmaller = CodeGenerator.getValue(smaller, elementType, j)
16681669
val getFromBigger = CodeGenerator.getValue(bigger, elementType, i)
1670+
val setIsNullCode = if (nullable) s"${ev.isNull} = false;" else ""
16691671
val compareValues = nullSafeElementCodegen(
16701672
smaller,
16711673
j,
16721674
s"""
16731675
|if (${ctx.genEqual(elementType, getFromSmaller, getFromBigger)}) {
1674-
| ${ev.isNull} = false;
1676+
| $setIsNullCode
16751677
| ${ev.value} = true;
16761678
|}
16771679
""".stripMargin,

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CollectionExpressionsSuite.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ class CollectionExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper
449449
val a4 = Literal.create(Seq[String](null, ""), ArrayType(StringType))
450450
val a5 = Literal.create(Seq[String]("", "abc"), ArrayType(StringType))
451451
val a6 = Literal.create(Seq[String]("def", "ghi"), ArrayType(StringType))
452+
val a7 = Literal.create(Seq(1, 2, 3), ArrayType(IntegerType, containsNull = false))
452453

453454
val emptyIntArray = Literal.create(Seq.empty[Int], ArrayType(IntegerType))
454455

@@ -463,6 +464,7 @@ class CollectionExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper
463464
checkEvaluation(ArraysOverlap(a4, a5), true)
464465
checkEvaluation(ArraysOverlap(a4, a6), null)
465466
checkEvaluation(ArraysOverlap(a5, a6), false)
467+
checkEvaluation(ArraysOverlap(a7, a7), true)
466468

467469
// null handling
468470
checkEvaluation(ArraysOverlap(emptyIntArray, a2), false)
@@ -481,9 +483,12 @@ class CollectionExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper
481483
ArrayType(BinaryType))
482484
val b2 = Literal.create(Seq[Array[Byte]](Array[Byte](2, 1), Array[Byte](4, 3)),
483485
ArrayType(BinaryType))
486+
val b3 = Literal.create(Seq[Array[Byte]](Array[Byte](1, 2), Array[Byte](3, 4)),
487+
ArrayType(BinaryType, containsNull = false))
484488

485489
checkEvaluation(ArraysOverlap(b0, b1), true)
486490
checkEvaluation(ArraysOverlap(b0, b2), false)
491+
checkEvaluation(ArraysOverlap(b3, b3), true)
487492

488493
// arrays of complex data types
489494
val aa0 = Literal.create(Seq[Array[String]](Array[String]("a", "b"), Array[String]("c", "d")),

0 commit comments

Comments
 (0)