Skip to content

Commit

Permalink
Fix conditional test evaluation in funcletizer (#34886)
Browse files Browse the repository at this point in the history
Fixes #34883
  • Loading branch information
roji authored Oct 12, 2024
1 parent 9d0f345 commit fdb4c38
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 2 deletions.
1 change: 1 addition & 0 deletions EFCore.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<s:Boolean x:Key="/Default/UserDictionary/Words/=fallbacks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Formattable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=funcletization/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=funcletize/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Funcletizer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Includable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=initializers/@EntryIndexedValue">True</s:Boolean>
Expand Down
4 changes: 2 additions & 2 deletions src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional
var test = Visit(conditional.Test, out var testState);

// If the test evaluates, simplify the conditional away by bubbling up the leg that remains
if (testState.IsEvaluatable && Evaluate(conditional.Test) is bool testBoolValue)
if (testState.IsEvaluatable && Evaluate(test) is bool testBoolValue)
{
return testBoolValue
? Visit(conditional.IfTrue, out _state)
Expand Down Expand Up @@ -905,7 +905,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCall)
var method = methodCall.Method;

// Handle some special, well-known functions
// If this is a call to EF.Constant(), or EF.Parameter(), then examine the operand; it it's isn't evaluatable (i.e. contains a
// If this is a call to EF.Constant(), or EF.Parameter(), then examine the operand; if it isn't evaluatable (i.e. contains a
// reference to a database table), throw immediately. Otherwise, evaluate the operand (either as a constant or as a parameter) and
// return that.
if (method.DeclaringType == typeof(EF))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4547,11 +4547,25 @@ public override Task MemberInitExpression_NewExpression_is_funcletized_even_when
async, async a =>
{
await base.MemberInitExpression_NewExpression_is_funcletized_even_when_bindings_are_not_evaluatable(a);
AssertSql(
"""
SELECT VALUE c["id"]
FROM root c
WHERE STARTSWITH(c["id"], "A")
""");
});

public override Task Funcletize_conditional_with_evaluatable_test(bool async)
=> Fixture.NoSyncTest(
async, async a =>
{
await base.Funcletize_conditional_with_evaluatable_test(a);
AssertSql(
"""
SELECT VALUE c
FROM root c
""");
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5150,6 +5150,16 @@ private class Dto(string value)
public Dto NestedDto { get; set; }
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Funcletize_conditional_with_evaluatable_test(bool async)
=> AssertQuery(
async,
ss => ss.Set<Customer>().Where(c => (AlwaysFalse() && c.CustomerID == "ALFKI" ? "yes" : "no") == "no"));

private static bool AlwaysFalse()
=> false;

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Null_parameter_name_works(bool async)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5657,6 +5657,17 @@ WHERE [c].[CustomerID] LIKE N'A%'
""");
}

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

AssertSql(
"""
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
""");
}

public override async Task Projecting_collection_split(bool async)
{
await base.Projecting_collection_split(async);
Expand Down

0 comments on commit fdb4c38

Please sign in to comment.