Skip to content

Commit 27850af

Browse files
committed
[SPARK-9462][SQL] Initialize nondeterministic expressions in code gen fallback mode.
Author: Reynold Xin <[email protected]> Closes #7767 from rxin/SPARK-9462 and squashes the following commits: ef3e2d9 [Reynold Xin] Removed println 713ac3a [Reynold Xin] More unit tests. bb5c334 [Reynold Xin] [SPARK-9462][SQL] Initialize nondeterministic expressions in code gen fallback mode.
1 parent 07fd7d3 commit 27850af

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodegenFallback.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,19 @@
1717

1818
package org.apache.spark.sql.catalyst.expressions.codegen
1919

20-
import org.apache.spark.sql.catalyst.expressions.Expression
20+
import org.apache.spark.sql.catalyst.expressions.{Nondeterministic, Expression}
2121

2222
/**
2323
* A trait that can be used to provide a fallback mode for expression code generation.
2424
*/
2525
trait CodegenFallback extends Expression {
2626

2727
protected def genCode(ctx: CodeGenContext, ev: GeneratedExpressionCode): String = {
28+
foreach {
29+
case n: Nondeterministic => n.setInitialValues()
30+
case _ =>
31+
}
32+
2833
ctx.references += this
2934
val objectTerm = ctx.freshName("obj")
3035
s"""

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/codegen/CodegenExpressionCachingSuite.scala

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,40 @@ package org.apache.spark.sql.catalyst.expressions.codegen
1919

2020
import org.apache.spark.SparkFunSuite
2121
import org.apache.spark.sql.catalyst.InternalRow
22-
import org.apache.spark.sql.catalyst.expressions.{UnsafeProjection, LeafExpression}
22+
import org.apache.spark.sql.catalyst.expressions._
2323
import org.apache.spark.sql.types.{BooleanType, DataType}
2424

2525
/**
2626
* A test suite that makes sure code generation handles expression internally states correctly.
2727
*/
2828
class CodegenExpressionCachingSuite extends SparkFunSuite {
2929

30-
test("GenerateUnsafeProjection") {
30+
test("GenerateUnsafeProjection should initialize expressions") {
31+
// Use an Add to wrap two of them together in case we only initialize the top level expressions.
32+
val expr = And(NondeterministicExpression(), NondeterministicExpression())
33+
val instance = UnsafeProjection.create(Seq(expr))
34+
assert(instance.apply(null).getBoolean(0) === false)
35+
}
36+
37+
test("GenerateProjection should initialize expressions") {
38+
val expr = And(NondeterministicExpression(), NondeterministicExpression())
39+
val instance = GenerateProjection.generate(Seq(expr))
40+
assert(instance.apply(null).getBoolean(0) === false)
41+
}
42+
43+
test("GenerateMutableProjection should initialize expressions") {
44+
val expr = And(NondeterministicExpression(), NondeterministicExpression())
45+
val instance = GenerateMutableProjection.generate(Seq(expr))()
46+
assert(instance.apply(null).getBoolean(0) === false)
47+
}
48+
49+
test("GeneratePredicate should initialize expressions") {
50+
val expr = And(NondeterministicExpression(), NondeterministicExpression())
51+
val instance = GeneratePredicate.generate(expr)
52+
assert(instance.apply(null) === false)
53+
}
54+
55+
test("GenerateUnsafeProjection should not share expression instances") {
3156
val expr1 = MutableExpression()
3257
val instance1 = UnsafeProjection.create(Seq(expr1))
3358
assert(instance1.apply(null).getBoolean(0) === false)
@@ -39,7 +64,7 @@ class CodegenExpressionCachingSuite extends SparkFunSuite {
3964
assert(instance2.apply(null).getBoolean(0) === true)
4065
}
4166

42-
test("GenerateProjection") {
67+
test("GenerateProjection should not share expression instances") {
4368
val expr1 = MutableExpression()
4469
val instance1 = GenerateProjection.generate(Seq(expr1))
4570
assert(instance1.apply(null).getBoolean(0) === false)
@@ -51,7 +76,7 @@ class CodegenExpressionCachingSuite extends SparkFunSuite {
5176
assert(instance2.apply(null).getBoolean(0) === true)
5277
}
5378

54-
test("GenerateMutableProjection") {
79+
test("GenerateMutableProjection should not share expression instances") {
5580
val expr1 = MutableExpression()
5681
val instance1 = GenerateMutableProjection.generate(Seq(expr1))()
5782
assert(instance1.apply(null).getBoolean(0) === false)
@@ -63,7 +88,7 @@ class CodegenExpressionCachingSuite extends SparkFunSuite {
6388
assert(instance2.apply(null).getBoolean(0) === true)
6489
}
6590

66-
test("GeneratePredicate") {
91+
test("GeneratePredicate should not share expression instances") {
6792
val expr1 = MutableExpression()
6893
val instance1 = GeneratePredicate.generate(expr1)
6994
assert(instance1.apply(null) === false)
@@ -77,6 +102,17 @@ class CodegenExpressionCachingSuite extends SparkFunSuite {
77102

78103
}
79104

105+
/**
106+
* An expression that's non-deterministic and doesn't support codegen.
107+
*/
108+
case class NondeterministicExpression()
109+
extends LeafExpression with Nondeterministic with CodegenFallback {
110+
override protected def initInternal(): Unit = { }
111+
override protected def evalInternal(input: InternalRow): Any = false
112+
override def nullable: Boolean = false
113+
override def dataType: DataType = BooleanType
114+
}
115+
80116

81117
/**
82118
* An expression with mutable state so we can change it freely in our test suite.

0 commit comments

Comments
 (0)