Skip to content

Commit

Permalink
Correct VisitUnary operand evaluation in funcletizer (#35172) (#35203)
Browse files Browse the repository at this point in the history
Fixes #35152

(cherry picked from commit 3ba88c4)
  • Loading branch information
roji authored Nov 26, 2024
1 parent fa4ce99 commit 3695bca
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public class ExpressionTreeFuncletizer : ExpressionVisitor
private static readonly bool UseOldBehavior35095 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35095", out var enabled35095) && enabled35095;

private static readonly bool UseOldBehavior35152 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35152", out var enabled35152) && enabled35152;

private static readonly MethodInfo ReadOnlyCollectionIndexerGetter = typeof(ReadOnlyCollection<Expression>).GetProperties()
.Single(p => p.GetIndexParameters() is { Length: 1 } indexParameters && indexParameters[0].ParameterType == typeof(int)).GetMethod!;

Expand Down Expand Up @@ -1558,9 +1561,20 @@ UnaryExpression EvaluateOperand(UnaryExpression unary, Expression operand, State
operand = ProcessEvaluatableRoot(operand, ref operandState);
}

if (_state.ContainsEvaluatable)
if (UseOldBehavior35152)
{
if (_state.ContainsEvaluatable)
{
_state = _calculatingPath
? State.CreateContainsEvaluatable(
typeof(UnaryExpression),
[_state.Path! with { PathFromParent = static e => Property(e, nameof(UnaryExpression.Operand)) }])
: State.NoEvaluatability;
}
}
else
{
_state = _calculatingPath
_state = operandState.ContainsEvaluatable && _calculatingPath
? State.CreateContainsEvaluatable(
typeof(UnaryExpression),
[_state.Path! with { PathFromParent = static e => Property(e, nameof(UnaryExpression.Operand)) }])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5284,6 +5284,17 @@ public override async Task Column_access_inside_subquery_predicate(bool async)
AssertSql();
}

public override async Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
{
// Sync always throws before getting to exception being tested.
if (async)
{
// Cosmos doesn't support ORDER BY over parameter/constant:
// Unsupported ORDER BY clause. ORDER BY item expression could not be mapped to a document path.
await Assert.ThrowsAsync<CosmosException>(() => base.Cast_to_object_over_parameter_directly_in_lambda(async: true));
}
}

private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5856,4 +5856,15 @@ public virtual Task Column_access_inside_subquery_predicate(bool async)
=> AssertQuery(
async,
ss => ss.Set<Customer>().Where(c => ss.Set<Order>().Where(o => c.CustomerID == "ALFKI").Any()));

[ConditionalTheory] // #35152
[MemberData(nameof(IsAsyncData))]
public virtual Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
{
var i = 8;

return AssertQuery(
async,
ss => ss.Set<Order>().OrderBy(o => (object)i).Select(o => o));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7476,6 +7476,17 @@ FROM [Orders] AS [o]
""");
}

public override async Task Cast_to_object_over_parameter_directly_in_lambda(bool async)
{
await base.Cast_to_object_over_parameter_directly_in_lambda(async);

AssertSql(
"""
SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate]
FROM [Orders] AS [o]
""");
}

private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down

0 comments on commit 3695bca

Please sign in to comment.