1717
1818package org .apache .spark .sql .catalyst .optimizer
1919
20+ import org .apache .spark .sql .Row
2021import org .apache .spark .sql .catalyst .analysis ._
2122import org .apache .spark .sql .catalyst .catalog .{InMemoryCatalog , SessionCatalog }
2223import org .apache .spark .sql .catalyst .dsl .expressions ._
@@ -26,7 +27,7 @@ import org.apache.spark.sql.catalyst.plans.PlanTest
2627import org .apache .spark .sql .catalyst .plans .logical ._
2728import org .apache .spark .sql .catalyst .rules ._
2829import org .apache .spark .sql .internal .SQLConf
29- import org .apache .spark .sql .Row
30+ import org .apache .spark .sql .types . BooleanType
3031
3132class BooleanSimplificationSuite extends PlanTest with PredicateHelper {
3233
@@ -37,14 +38,24 @@ class BooleanSimplificationSuite extends PlanTest with PredicateHelper {
3738 Batch (" Constant Folding" , FixedPoint (50 ),
3839 NullPropagation (conf),
3940 ConstantFolding ,
41+ SimplifyConditionals ,
4042 BooleanSimplification ,
4143 PruneFilters (conf)) :: Nil
4244 }
4345
44- val testRelation = LocalRelation (' a .int, ' b .int, ' c .int, ' d .string)
46+ val testRelation = LocalRelation (' a .int, ' b .int, ' c .int, ' d .string,
47+ ' e .boolean, ' f .boolean, ' g .boolean, ' h .boolean)
4548
4649 val testRelationWithData = LocalRelation .fromExternalRows(
47- testRelation.output, Seq (Row (1 , 2 , 3 , " abc" ))
50+ testRelation.output, Seq (Row (1 , 2 , 3 , " abc" , true , null , true , null ))
51+ )
52+
53+ val testNotNullableRelation = LocalRelation (' a .int.notNull, ' b .int.notNull, ' c .int.notNull,
54+ ' d .string.notNull, ' e .boolean.notNull, ' f .boolean.notNull, ' g .boolean.notNull,
55+ ' h .boolean.notNull)
56+
57+ val testNotNullableRelationWithData = LocalRelation .fromExternalRows(
58+ testNotNullableRelation.output, Seq (Row (1 , 2 , 3 , " abc" , true , false , true , false ))
4859 )
4960
5061 private def checkCondition (input : Expression , expected : LogicalPlan ): Unit = {
@@ -60,6 +71,13 @@ class BooleanSimplificationSuite extends PlanTest with PredicateHelper {
6071 comparePlans(actual, correctAnswer)
6172 }
6273
74+ private def checkConditionInNotNullableRelation (
75+ input : Expression , expected : LogicalPlan ): Unit = {
76+ val plan = testNotNullableRelationWithData.where(input).analyze
77+ val actual = Optimize .execute(plan)
78+ comparePlans(actual, expected)
79+ }
80+
6381 test(" a && a => a" ) {
6482 checkCondition(Literal (1 ) < ' a && Literal (1 ) < ' a , Literal (1 ) < ' a )
6583 checkCondition(Literal (1 ) < ' a && Literal (1 ) < ' a && Literal (1 ) < ' a , Literal (1 ) < ' a )
@@ -173,10 +191,30 @@ class BooleanSimplificationSuite extends PlanTest with PredicateHelper {
173191 }
174192
175193 test(" Complementation Laws" ) {
176- checkCondition(' a && ! ' a , testRelation)
177- checkCondition(! ' a && ' a , testRelation)
194+ checkConditionInNotNullableRelation(' e && ! ' e , testNotNullableRelation)
195+ checkConditionInNotNullableRelation(! ' e && ' e , testNotNullableRelation)
196+
197+ checkConditionInNotNullableRelation(' e || ! ' e , testNotNullableRelationWithData)
198+ checkConditionInNotNullableRelation(! ' e || ' e , testNotNullableRelationWithData)
199+ }
200+
201+ test(" Complementation Laws - null handling" ) {
202+ checkCondition(' e && ! ' e ,
203+ testRelationWithData.where(If (' e .isNull, Literal .create(null , BooleanType ), false )).analyze)
204+ checkCondition(! ' e && ' e ,
205+ testRelationWithData.where(If (' e .isNull, Literal .create(null , BooleanType ), false )).analyze)
206+
207+ checkCondition(' e || ! ' e ,
208+ testRelationWithData.where(If (' e .isNull, Literal .create(null , BooleanType ), true )).analyze)
209+ checkCondition(! ' e || ' e ,
210+ testRelationWithData.where(If (' e .isNull, Literal .create(null , BooleanType ), true )).analyze)
211+ }
212+
213+ test(" Complementation Laws - negative case" ) {
214+ checkCondition(' e && ! ' f , testRelationWithData.where(' e && ! ' f ).analyze)
215+ checkCondition(! ' f && ' e , testRelationWithData.where(! ' f && ' e ).analyze)
178216
179- checkCondition(' a || ! ' a , testRelationWithData)
180- checkCondition(! ' a || ' a , testRelationWithData)
217+ checkCondition(' e || ! ' f , testRelationWithData.where( ' e || ! ' f ).analyze )
218+ checkCondition(! ' f || ' e , testRelationWithData.where( ! ' f || ' e ).analyze )
181219 }
182220}
0 commit comments