@@ -25,7 +25,7 @@ import org.apache.spark.sql.catalyst.expressions.Literal
2525import org .apache .spark .sql .catalyst .plans ._
2626import org .apache .spark .sql .catalyst .plans .logical .{LocalRelation , LogicalPlan , Project }
2727import org .apache .spark .sql .catalyst .rules .RuleExecutor
28- import org .apache .spark .sql .types .StructType
28+ import org .apache .spark .sql .types .{ IntegerType , StructType }
2929
3030class PropagateEmptyRelationSuite extends PlanTest {
3131 object Optimize extends RuleExecutor [LogicalPlan ] {
@@ -37,7 +37,8 @@ class PropagateEmptyRelationSuite extends PlanTest {
3737 ReplaceIntersectWithSemiJoin ,
3838 PushDownPredicate ,
3939 PruneFilters ,
40- PropagateEmptyRelation ) :: Nil
40+ PropagateEmptyRelation ,
41+ CollapseProject ) :: Nil
4142 }
4243
4344 object OptimizeWithoutPropagateEmptyRelation extends RuleExecutor [LogicalPlan ] {
@@ -48,7 +49,8 @@ class PropagateEmptyRelationSuite extends PlanTest {
4849 ReplaceExceptWithAntiJoin ,
4950 ReplaceIntersectWithSemiJoin ,
5051 PushDownPredicate ,
51- PruneFilters ) :: Nil
52+ PruneFilters ,
53+ CollapseProject ) :: Nil
5254 }
5355
5456 val testRelation1 = LocalRelation .fromExternalRows(Seq (' a .int), data = Seq (Row (1 )))
@@ -79,18 +81,21 @@ class PropagateEmptyRelationSuite extends PlanTest {
7981
8082 (true , false , Inner , Some (LocalRelation (' a .int, ' b .int))),
8183 (true , false , Cross , Some (LocalRelation (' a .int, ' b .int))),
82- (true , false , LeftOuter , Some (Project (Seq (' a , Literal (null ).as(' b )), testRelation1).analyze)),
84+ (true , false , LeftOuter ,
85+ Some (Project (Seq (' a , Literal (null ).cast(IntegerType ).as(' b )), testRelation1).analyze)),
8386 (true , false , RightOuter , Some (LocalRelation (' a .int, ' b .int))),
84- (true , false , FullOuter , Some (Project (Seq (' a , Literal (null ).as(' b )), testRelation1).analyze)),
87+ (true , false , FullOuter ,
88+ Some (Project (Seq (' a , Literal (null ).cast(IntegerType ).as(' b )), testRelation1).analyze)),
8589 (true , false , LeftAnti , Some (testRelation1)),
8690 (true , false , LeftSemi , Some (LocalRelation (' a .int))),
8791
8892 (false , true , Inner , Some (LocalRelation (' a .int, ' b .int))),
8993 (false , true , Cross , Some (LocalRelation (' a .int, ' b .int))),
9094 (false , true , LeftOuter , Some (LocalRelation (' a .int, ' b .int))),
9195 (false , true , RightOuter ,
92- Some (Project (Seq (Literal (null ).as(' a ), ' b ), testRelation2).analyze)),
93- (false , true , FullOuter , Some (Project (Seq (Literal (null ).as(' a ), ' b ), testRelation2).analyze)),
96+ Some (Project (Seq (Literal (null ).cast(IntegerType ).as(' a ), ' b ), testRelation2).analyze)),
97+ (false , true , FullOuter ,
98+ Some (Project (Seq (Literal (null ).cast(IntegerType ).as(' a ), ' b ), testRelation2).analyze)),
9499 (false , true , LeftAnti , Some (LocalRelation (' a .int))),
95100 (false , true , LeftSemi , Some (LocalRelation (' a .int))),
96101
@@ -209,4 +214,11 @@ class PropagateEmptyRelationSuite extends PlanTest {
209214
210215 comparePlans(optimized, correctAnswer)
211216 }
217+
218+ test(" propagate empty relation keeps the plan resolved" ) {
219+ val query = testRelation1.join(
220+ LocalRelation (' a .int, ' b .int), UsingJoin (FullOuter , " a" :: Nil ), None )
221+ val optimized = Optimize .execute(query.analyze)
222+ assert(optimized.resolved)
223+ }
212224}
0 commit comments