Skip to content

Commit

Permalink
Fix comparison of nullable values
Browse files Browse the repository at this point in the history
In C# an ordered comparison (<, >, <=, >=) between two nullable values always
returns a boolean value: if either operand is null, the result is false;
otherwise, the result is that of the comparison of the (non-null) values.

Fixes dotnet#33752
  • Loading branch information
ranma42 committed May 29, 2024
1 parent 22e2b36 commit 5d8b386
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/EFCore.Relational/Query/SqlNullabilityProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,27 @@ protected virtual SqlExpression VisitSqlBinary(
nullable = leftNullable || rightNullable;
var result = sqlBinaryExpression.Update(left, right);

if (nullable && !optimize && result.OperatorType
is ExpressionType.GreaterThan
or ExpressionType.GreaterThanOrEqual
or ExpressionType.LessThan
or ExpressionType.LessThanOrEqual)
{
// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types#lifted-operators
// For the comparison operators <, >, <=, and >=, if one or both
// operands are null, the result is false; otherwise, the contained
// values of operands are compared.

// if either operand is NULL, the SQL comparison would return NULL;
// to match the C# semantics, replace expr -> COALESCE(expr, FALSE)

nullable = false;
return _sqlExpressionFactory.Case(
[new(result, _sqlExpressionFactory.Constant(true, result.TypeMapping))],
_sqlExpressionFactory.Constant(false, result.TypeMapping)
);
}

return result is SqlBinaryExpression sqlBinaryResult
&& sqlBinaryExpression.OperatorType is ExpressionType.AndAlso or ExpressionType.OrElse
? SimplifyLogicalSqlBinaryExpression(sqlBinaryResult)
Expand Down

0 comments on commit 5d8b386

Please sign in to comment.