@@ -19,15 +19,40 @@ package org.apache.spark.sql.catalyst.expressions.codegen
1919
2020import org .apache .spark .SparkFunSuite
2121import org .apache .spark .sql .catalyst .InternalRow
22- import org .apache .spark .sql .catalyst .expressions .{ UnsafeProjection , LeafExpression }
22+ import org .apache .spark .sql .catalyst .expressions ._
2323import org .apache .spark .sql .types .{BooleanType , DataType }
2424
2525/**
2626 * A test suite that makes sure code generation handles expression internally states correctly.
2727 */
2828class 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