Skip to content

Commit 17b36d3

Browse files
committed
Correct VisitUnary operand evaluation in funcletizer (dotnet#35172)
Fixes dotnet#35152 (cherry picked from commit 3ba88c4)
1 parent bd7d0aa commit 17b36d3

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ public class ExpressionTreeFuncletizer : ExpressionVisitor
100100

101101
private static readonly IReadOnlySet<string> EmptyStringSet = new HashSet<string>();
102102

103+
private static readonly bool UseOldBehavior35152 =
104+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35152", out var enabled35152) && enabled35152;
105+
103106
private static readonly MethodInfo ReadOnlyCollectionIndexerGetter = typeof(ReadOnlyCollection<Expression>).GetProperties()
104107
.Single(p => p.GetIndexParameters() is { Length: 1 } indexParameters && indexParameters[0].ParameterType == typeof(int)).GetMethod!;
105108

@@ -1548,14 +1551,22 @@ UnaryExpression EvaluateOperand(UnaryExpression unary, Expression operand, State
15481551
operand = ProcessEvaluatableRoot(operand, ref operandState);
15491552
}
15501553

1551-
if (_state.ContainsEvaluatable)
1554+
if (UseOldBehavior35152)
15521555
{
15531556
_state = _calculatingPath
15541557
? State.CreateContainsEvaluatable(
15551558
typeof(UnaryExpression),
15561559
[_state.Path! with { PathFromParent = static e => Property(e, nameof(UnaryExpression.Operand)) }])
15571560
: State.NoEvaluatability;
15581561
}
1562+
else
1563+
{
1564+
_state = operandState.ContainsEvaluatable && _calculatingPath
1565+
? State.CreateContainsEvaluatable(
1566+
typeof(UnaryExpression),
1567+
[_state.Path! with { PathFromParent = static e => Property(e, nameof(UnaryExpression.Operand)) }])
1568+
: State.NoEvaluatability;
1569+
}
15591570

15601571
return unary.Update(operand);
15611572
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5276,6 +5276,17 @@ public virtual async Task ToPageAsync_in_subquery_throws()
52765276

52775277
#endregion ToPageAsync
52785278

5279+
public override async Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
5280+
{
5281+
// Sync always throws before getting to exception being tested.
5282+
if (async)
5283+
{
5284+
// Cosmos doesn't support ORDER BY over parameter/constant:
5285+
// Unsupported ORDER BY clause. ORDER BY item expression could not be mapped to a document path.
5286+
await Assert.ThrowsAsync<CosmosException>(() => base.Cast_to_object_over_parameter_directly_in_lambda(async: true));
5287+
}
5288+
}
5289+
52795290
private void AssertSql(params string[] expected)
52805291
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
52815292

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5849,4 +5849,15 @@ public virtual Task Static_member_access_gets_parameterized_within_larger_evalua
58495849

58505850
private static string StaticProperty
58515851
=> "ALF";
5852+
5853+
[ConditionalTheory] // #35152
5854+
[MemberData(nameof(IsAsyncData))]
5855+
public virtual Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
5856+
{
5857+
var i = 8;
5858+
5859+
return AssertQuery(
5860+
async,
5861+
ss => ss.Set<Order>().OrderBy(o => (object)i).Select(o => o));
5862+
}
58525863
}

test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7461,6 +7461,17 @@ FROM [Orders] AS [o]
74617461
""");
74627462
}
74637463

7464+
public override async Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
7465+
{
7466+
await base.Cast_to_object_over_parameter_directly_in_lambda(async);
7467+
7468+
AssertSql(
7469+
"""
7470+
SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate]
7471+
FROM [Orders] AS [o]
7472+
""");
7473+
}
7474+
74647475
private void AssertSql(params string[] expected)
74657476
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
74667477

0 commit comments

Comments
 (0)