Skip to content

Commit

Permalink
Avoid duplicating complex expression in comparisons
Browse files Browse the repository at this point in the history
When comparing a nullable expression to a non-nullable one, a  `NULL` result  always
represent a difference.

This makes it possible to avoid duplicating the nullable expression by mapping
the `NULL` result to a `FALSE` (when comparing for equality).

Fixes dotnet#34165.
  • Loading branch information
ranma42 committed Jul 13, 2024
1 parent 8a42d11 commit f457bea
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1815,10 +1815,23 @@ private SqlExpression RewriteNullSemantics(
// doing a full null semantics rewrite - removing all nulls from truth table
nullable = false;

// (a == b && (a != null && b != null)) || (a == null && b == null)
body = _sqlExpressionFactory.OrElse(
_sqlExpressionFactory.AndAlso(body, _sqlExpressionFactory.AndAlso(leftIsNotNull, rightIsNotNull)),
_sqlExpressionFactory.AndAlso(leftIsNull, rightIsNull));
if (leftNullable && rightNullable
|| leftIsNull is SqlUnaryExpression { Operand: ColumnExpression }
|| rightIsNull is SqlUnaryExpression { Operand: ColumnExpression })
{
// (a == b && (a != null && b != null)) || (a == null && b == null)
body = _sqlExpressionFactory.OrElse(
_sqlExpressionFactory.AndAlso(body, _sqlExpressionFactory.AndAlso(leftIsNotNull, rightIsNotNull)),
_sqlExpressionFactory.AndAlso(leftIsNull, rightIsNull));
}
else
{
// a == b -> CASE WHEN a == b THEN TRUE ELSE FALSE END
body = _sqlExpressionFactory.Case(
[new(body, _sqlExpressionFactory.Constant(true, body.Type, body.TypeMapping))],
_sqlExpressionFactory.Constant(false, body.Type, body.TypeMapping));
}


if (sqlBinaryExpression.OperatorType == ExpressionType.NotEqual)
{
Expand Down

0 comments on commit f457bea

Please sign in to comment.