Skip to content

Commit

Permalink
Avoid using ^ and ~ on value-converted expressions
Browse files Browse the repository at this point in the history
The transformation of equality/in-equality in a (negated) XOR is only possible
when the expressions are BIT or integer types on the SQL side (i.e. taking value
conversion into account).

Similarly, the Boolean negation `NOT` can be implemented as `~` only if the
underlying expression is a BIT.

Fixes dotnet#35093.
  • Loading branch information
ranma42 committed Nov 16, 2024
1 parent 3769433 commit 6cedf11
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions src/EFCore.SqlServer/Query/Internal/SearchConditionConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,11 @@ protected virtual Expression VisitSqlBinary(SqlBinaryExpression binary, bool inS

if (binary.OperatorType is ExpressionType.NotEqual or ExpressionType.Equal)
{
var leftType = newLeft.TypeMapping?.Converter?.ProviderClrType ?? newLeft.Type;
var rightType = newRight.TypeMapping?.Converter?.ProviderClrType ?? newRight.Type;
if (!inSearchConditionContext
&& (newLeft.Type == typeof(bool) || newLeft.Type.IsEnum || newLeft.Type.IsInteger())
&& (newRight.Type == typeof(bool) || newRight.Type.IsEnum || newRight.Type.IsInteger()))
&& (leftType == typeof(bool) || leftType.IsEnum || leftType.IsInteger())
&& (rightType == typeof(bool) || rightType.IsEnum || rightType.IsInteger()))
{
// "lhs != rhs" is the same as "CAST(lhs ^ rhs AS BIT)", except that
// the first is a boolean, the second is a BIT
Expand Down Expand Up @@ -265,7 +267,9 @@ protected virtual Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression
case ExpressionType.Not when sqlUnaryExpression.Type == typeof(bool):
{
// when possible, avoid converting to/from predicate form
if (!inSearchConditionContext && sqlUnaryExpression.Operand is not (ExistsExpression or InExpression or LikeExpression))
if (!inSearchConditionContext &&
sqlUnaryExpression.TypeMapping?.Converter is null &&
sqlUnaryExpression.Operand is not (ExistsExpression or InExpression or LikeExpression))
{
var negatedOperand = (SqlExpression)Visit(sqlUnaryExpression.Operand);

Expand Down

0 comments on commit 6cedf11

Please sign in to comment.