@@ -153,27 +153,25 @@ object NullPropagation extends Rule[LogicalPlan] {
153153 case e @ GetItem (Literal (null , _), _) => Literal (null , e.dataType)
154154 case e @ GetItem (_, Literal (null , _)) => Literal (null , e.dataType)
155155 case e @ GetField (Literal (null , _), _) => Literal (null , e.dataType)
156- case e @ Coalesce (children) => {
157- val newChildren = children.filter(c => c match {
156+
157+ // For Coalesce, remove null literals.
158+ case e @ Coalesce (children) =>
159+ val newChildren = children.filter {
158160 case Literal (null , _) => false
159161 case _ => true
160- })
162+ }
161163 if (newChildren.length == 0 ) {
162164 Literal (null , e.dataType)
163165 } else if (newChildren.length == 1 ) {
164166 newChildren(0 )
165167 } else {
166168 Coalesce (newChildren)
167169 }
168- }
169- case e @ If (Literal (v, _), trueValue, falseValue) => if (v == true ) trueValue else falseValue
170- case e @ In (Literal (v, _), list) if (list.exists(c => c match {
171- case Literal (candidate, _) if candidate == v => true
172- case _ => false
173- })) => Literal (true , BooleanType )
170+
174171 case e @ Substring (Literal (null , _), _, _) => Literal (null , e.dataType)
175172 case e @ Substring (_, Literal (null , _), _) => Literal (null , e.dataType)
176173 case e @ Substring (_, _, Literal (null , _)) => Literal (null , e.dataType)
174+
177175 // Put exceptional cases above if any
178176 case e : BinaryArithmetic => e.children match {
179177 case Literal (null , _) :: right :: Nil => Literal (null , e.dataType)
@@ -201,9 +199,19 @@ object NullPropagation extends Rule[LogicalPlan] {
201199object ConstantFolding extends Rule [LogicalPlan ] {
202200 def apply (plan : LogicalPlan ): LogicalPlan = plan transform {
203201 case q : LogicalPlan => q transformExpressionsDown {
204- // Skip redundant folding of literals.
202+ // Skip redundant folding of literals. This rule is technically not necessary. Placing this
203+ // here avoids running the next rule for Literal values, which would create a new Literal
204+ // object and running eval unnecessarily.
205205 case l : Literal => l
206+
207+ // Fold expressions that are foldable.
206208 case e if e.foldable => Literal (e.eval(null ), e.dataType)
209+
210+ // Fold "literal in (item1, item2, ..., literal, ...)" into true directly.
211+ case In (Literal (v, _), list) if list.exists {
212+ case Literal (candidate, _) if candidate == v => true
213+ case _ => false
214+ } => Literal (true , BooleanType )
207215 }
208216 }
209217}
@@ -233,6 +241,9 @@ object BooleanSimplification extends Rule[LogicalPlan] {
233241 case (l, Literal (false , BooleanType )) => l
234242 case (_, _) => or
235243 }
244+
245+ // Turn "if (true) a else b" into "a", and if (false) a else b" into "b".
246+ case e @ If (Literal (v, _), trueValue, falseValue) => if (v == true ) trueValue else falseValue
236247 }
237248 }
238249}
@@ -254,12 +265,12 @@ object CombineFilters extends Rule[LogicalPlan] {
254265 */
255266object SimplifyFilters extends Rule [LogicalPlan ] {
256267 def apply (plan : LogicalPlan ): LogicalPlan = plan transform {
257- case Filter ( Literal ( true , BooleanType ), child) =>
258- child
259- case Filter ( Literal ( null , _), child) =>
260- LocalRelation (child.output)
261- case Filter (Literal (false , BooleanType ), child) =>
262- LocalRelation (child.output)
268+ // If the filter condition always evaluate to true, remove the filter.
269+ case Filter ( Literal ( true , BooleanType ), child) => child
270+ // If the filter condition always evaluate to null or false,
271+ // replace the input with an empty relation.
272+ case Filter (Literal (null , _ ), child) => LocalRelation (child.output, data = Seq .empty)
273+ case Filter ( Literal ( false , BooleanType ), child) => LocalRelation (child.output, data = Seq .empty )
263274 }
264275}
265276
@@ -301,7 +312,7 @@ object PushPredicateThroughJoin extends Rule[LogicalPlan] with PredicateHelper {
301312 /**
302313 * Splits join condition expressions into three categories based on the attributes required
303314 * to evaluate them.
304- * @returns (canEvaluateInLeft, canEvaluateInRight, haveToEvaluateInBoth)
315+ * @return (canEvaluateInLeft, canEvaluateInRight, haveToEvaluateInBoth)
305316 */
306317 private def split (condition : Seq [Expression ], left : LogicalPlan , right : LogicalPlan ) = {
307318 val (leftEvaluateCondition, rest) =
0 commit comments