Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ object SimplifyConditionals extends Rule[LogicalPlan] with PredicateHelper {
if cond.deterministic && trueValue.semanticEquals(falseValue) => trueValue
case If(cond, l @ Literal(null, _), FalseLiteral) if !cond.nullable => And(cond, l)
case If(cond, l @ Literal(null, _), TrueLiteral) if !cond.nullable => Or(Not(cond), l)
case If(cond, FalseLiteral, l @ Literal(null, _)) if !cond.nullable => And(Not(cond), l)
case If(cond, TrueLiteral, l @ Literal(null, _)) if !cond.nullable => Or(cond, l)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor, can we call l as nullLiteral?

      case If(cond, nullLiteral @ Literal(null, _), FalseLiteral) if !cond.nullable => And(cond, nullLiteral)
      case If(cond, nullLiteral @ Literal(null, _), TrueLiteral) if !cond.nullable => Or(Not(cond), nullLiteral)
      case If(cond, FalseLiteral, nullLiteral @ Literal(null, _)) if !cond.nullable => And(Not(cond), nullLiteral)
      case If(cond, TrueLiteral, nullLiteral @ Literal(null, _)) if !cond.nullable => Or(cond, nullLiteral)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm that will break each of these into two lines which may affect readability, also I think given these are already Literal(null, _), naming the variable to nullLiteral doesn't add much value maybe?


case e @ CaseWhen(branches, elseValue) if branches.exists(x => falseOrNullLiteral(x._1)) =>
// If there are branches that are always false, remove them.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,29 +166,37 @@ class SimplifyConditionalSuite extends PlanTest with ExpressionEvalHelper with P
)
}

test("simplify if when then clause is null and else clause is boolean") {
test("simplify if when one clause is null and another is boolean") {
val p = IsNull('a)
val nullLiteral = Literal(null, BooleanType)
assertEquivalent(If(p, nullLiteral, FalseLiteral), And(p, nullLiteral))
assertEquivalent(If(p, nullLiteral, TrueLiteral), Or(IsNotNull('a), nullLiteral))
assertEquivalent(If(p, FalseLiteral, nullLiteral), And(IsNotNull('a), nullLiteral))
assertEquivalent(If(p, TrueLiteral, nullLiteral), Or(p, nullLiteral))

// the rule should not apply to nullable predicate
Seq(TrueLiteral, FalseLiteral).foreach { b =>
assertEquivalent(If(GreaterThan('a, 42), nullLiteral, b),
If(GreaterThan('a, 42), nullLiteral, b))
assertEquivalent(If(GreaterThan('a, 42), b, nullLiteral),
If(GreaterThan('a, 42), b, nullLiteral))
}

// check evaluation also
Seq(TrueLiteral, FalseLiteral).foreach { b =>
checkEvaluation(If(b, nullLiteral, FalseLiteral), And(b, nullLiteral).eval(EmptyRow))
checkEvaluation(If(b, nullLiteral, TrueLiteral), Or(Not(b), nullLiteral).eval(EmptyRow))
checkEvaluation(If(b, FalseLiteral, nullLiteral), And(Not(b), nullLiteral).eval(EmptyRow))
checkEvaluation(If(b, TrueLiteral, nullLiteral), Or(b, nullLiteral).eval(EmptyRow))
}

// should have no effect on expressions with nullable if condition
assert((Factorial(5) > 100L).nullable)
Seq(TrueLiteral, FalseLiteral).foreach { b =>
checkEvaluation(If(Factorial(5) > 100L, nullLiteral, b),
If(Factorial(5) > 100L, nullLiteral, b).eval(EmptyRow))
checkEvaluation(If(Factorial(5) > 100L, b, nullLiteral),
If(Factorial(5) > 100L, b, nullLiteral).eval(EmptyRow))
}
}
}