Skip to content

Commit 7e313ab

Browse files
authored
Implement translation for XOR (#34071)
1 parent f1fef24 commit 7e313ab

File tree

14 files changed

+84
-15
lines changed

14 files changed

+84
-15
lines changed

src/EFCore.Cosmos/Query/Internal/CosmosQuerySqlGenerator.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres
476476
// Arithmetic
477477
ExpressionType.Add => " + ",
478478
ExpressionType.Subtract => " - ",
479-
ExpressionType.Multiply => " * " ,
480-
ExpressionType.Divide => " / " ,
479+
ExpressionType.Multiply => " * ",
480+
ExpressionType.Divide => " / ",
481481
ExpressionType.Modulo => " % ",
482482

483483
// Bitwise >>> (zero-fill right shift) not available in C#
@@ -513,6 +513,11 @@ protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpres
513513
{
514514
op = " || ";
515515
}
516+
else if (sqlBinaryExpression.OperatorType == ExpressionType.ExclusiveOr
517+
&& sqlBinaryExpression.Type == typeof(bool))
518+
{
519+
op = " != ";
520+
}
516521

517522
_sqlBuilder.Append(op);
518523

src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ private SqlExpression ApplyTypeMappingOnSqlBinary(
152152
case ExpressionType.RightShift:
153153
case ExpressionType.And:
154154
case ExpressionType.Or:
155+
case ExpressionType.ExclusiveOr:
155156
case ExpressionType.Coalesce:
156157
{
157158
inferredTypeMapping = typeMapping ?? ExpressionExtensions.InferTypeMapping(left, right);

src/EFCore.Relational/Query/QuerySqlGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,7 @@ protected virtual string GetOperator(SqlBinaryExpression binaryExpression)
10961096
ExpressionType.Modulo => " % ",
10971097
ExpressionType.And => " & ",
10981098
ExpressionType.Or => " | ",
1099+
ExpressionType.ExclusiveOr => " ^ ",
10991100

11001101
_ => throw new UnreachableException($"Unsupported unary OperatorType: {binaryExpression.OperatorType}")
11011102
};

src/EFCore.Relational/Query/SqlExpressionFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ private SqlExpression ApplyTypeMappingOnSqlBinary(
256256
case ExpressionType.Modulo:
257257
case ExpressionType.And:
258258
case ExpressionType.Or:
259+
case ExpressionType.ExclusiveOr:
259260
{
260261
inferredTypeMapping = typeMapping ?? ExpressionExtensions.InferTypeMapping(left, right);
261262
resultType = inferredTypeMapping?.ClrType ?? left.Type;

src/EFCore.Relational/Query/SqlExpressions/SqlBinaryExpression.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ internal static bool IsValidOperator(ExpressionType operatorType)
100100
case ExpressionType.Equal:
101101
case ExpressionType.NotEqual:
102102
case ExpressionType.Coalesce:
103+
case ExpressionType.ExclusiveOr:
103104
return true;
104105
default:
105106
return false;

src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ protected override bool TryGetOperatorInfo(SqlExpression expression, out int pre
653653
ExpressionType.Subtract => (700, false),
654654
ExpressionType.And => (700, true),
655655
ExpressionType.Or => (700, true),
656+
ExpressionType.ExclusiveOr => (700, true),
656657
ExpressionType.LeftShift => (700, true),
657658
ExpressionType.RightShift => (700, true),
658659
ExpressionType.LessThan => (500, false),

src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,11 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression)
211211

212212
if (visitedExpression is SqlBinaryExpression sqlBinary)
213213
{
214+
if (sqlBinary.OperatorType == ExpressionType.ExclusiveOr)
215+
{
216+
return QueryCompilationContext.NotTranslatedExpression;
217+
}
218+
214219
if (sqlBinary.OperatorType == ExpressionType.Modulo
215220
&& (ModuloFunctions.TryGetValue(GetProviderType(sqlBinary.Left), out var function)
216221
|| ModuloFunctions.TryGetValue(GetProviderType(sqlBinary.Right), out function)))

test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,20 @@ public override Task Where_bitwise_binary_or(bool async)
23692369
SELECT c
23702370
FROM root c
23712371
WHERE ((c["Discriminator"] = "Order") AND ((c["OrderID"] | 10248) = 10248))
2372+
""");
2373+
});
2374+
2375+
public override Task Where_bitwise_binary_xor(bool async)
2376+
=> Fixture.NoSyncTest(
2377+
async, async a =>
2378+
{
2379+
await base.Where_bitwise_binary_xor(async);
2380+
2381+
AssertSql(
2382+
"""
2383+
SELECT c
2384+
FROM root c
2385+
WHERE ((c["Discriminator"] = "Order") AND ((c["OrderID"] ^ 1) = 10249))
23722386
""");
23732387
});
23742388

test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,21 @@ FROM root c
150150
""");
151151
});
152152

153-
public override async Task Where_bitwise_xor(bool async)
154-
{
155-
// Bitwise operators on booleans. Issue #13168.
156-
Assert.Equal(
157-
CosmosStrings.UnsupportedOperatorForSqlExpression("ExclusiveOr", "SqlBinaryExpression"),
158-
(await Assert.ThrowsAsync<InvalidOperationException>(() => base.Where_bitwise_xor(async))).Message);
153+
[ConditionalTheory]
154+
[MemberData(nameof(IsAsyncData))]
155+
public override Task Where_bitwise_xor(bool async)
156+
=> Fixture.NoSyncTest(
157+
async, async a =>
158+
{
159+
await base.Where_bitwise_xor(a);
159160

160-
AssertSql();
161-
}
161+
AssertSql(
162+
"""
163+
SELECT c
164+
FROM root c
165+
WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = "ALFKI") != true))
166+
""");
167+
});
162168

163169
[ConditionalTheory]
164170
[MemberData(nameof(IsAsyncData))]

test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3265,6 +3265,16 @@ public virtual Task Where_bitwise_binary_or(bool async)
32653265
async,
32663266
ss => ss.Set<Order>().Where(o => (o.OrderID | 10248) == 10248));
32673267

3268+
3269+
[ConditionalTheory]
3270+
[MemberData(nameof(IsAsyncData))]
3271+
public virtual Task Where_bitwise_binary_xor(bool async)
3272+
{
3273+
return AssertQuery(
3274+
async,
3275+
ss => ss.Set<Order>().Where(o => (o.OrderID ^ 1) == 10249));
3276+
}
3277+
32683278
[ConditionalTheory]
32693279
[MemberData(nameof(IsAsyncData))]
32703280
public virtual Task Select_bitwise_or_with_logical_or(bool async)

0 commit comments

Comments
 (0)