Skip to content

Commit a8c7b9d

Browse files
authored
Fix TPC equality check inside subquery predicate (#35120) (#35201)
Fixes #35118 (cherry picked from commit 3d0b86d)
1 parent bd7d0aa commit a8c7b9d

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using System.Runtime.CompilerServices;
56
using Microsoft.EntityFrameworkCore.Metadata.Internal;
67
using Microsoft.EntityFrameworkCore.Query.Internal;
@@ -52,6 +53,9 @@ public sealed partial class SelectExpression : TableExpressionBase
5253

5354
private static ConstructorInfo? _quotingConstructor;
5455

56+
private static readonly bool UseOldBehavior35118 =
57+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35118", out var enabled35118) && enabled35118;
58+
5559
/// <summary>
5660
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
5761
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -1550,7 +1554,8 @@ public void ApplyPredicate(SqlExpression sqlExpression)
15501554
Left: ColumnExpression leftColumn,
15511555
Right: SqlConstantExpression { Value: string s1 }
15521556
}
1553-
when GetTable(leftColumn) is TpcTablesExpression
1557+
when (UseOldBehavior35118 ? GetTable(leftColumn) : TryGetTable(leftColumn, out var table, out _) ? table : null)
1558+
is TpcTablesExpression
15541559
{
15551560
DiscriminatorColumn: var discriminatorColumn,
15561561
DiscriminatorValues: var discriminatorValues
@@ -1573,7 +1578,8 @@ when GetTable(leftColumn) is TpcTablesExpression
15731578
Left: SqlConstantExpression { Value: string s2 },
15741579
Right: ColumnExpression rightColumn
15751580
}
1576-
when GetTable(rightColumn) is TpcTablesExpression
1581+
when (UseOldBehavior35118 ? GetTable(rightColumn) : TryGetTable(rightColumn, out var table, out _) ? table : null)
1582+
is TpcTablesExpression
15771583
{
15781584
DiscriminatorColumn: var discriminatorColumn,
15791585
DiscriminatorValues: var discriminatorValues
@@ -1597,7 +1603,8 @@ when GetTable(rightColumn) is TpcTablesExpression
15971603
Item: ColumnExpression itemColumn,
15981604
Values: IReadOnlyList<SqlExpression> valueExpressions
15991605
}
1600-
when GetTable(itemColumn) is TpcTablesExpression
1606+
when (UseOldBehavior35118 ? GetTable(itemColumn) : TryGetTable(itemColumn, out var table, out _) ? table : null)
1607+
is TpcTablesExpression
16011608
{
16021609
DiscriminatorColumn: var discriminatorColumn,
16031610
DiscriminatorValues: var discriminatorValues
@@ -2724,6 +2731,24 @@ private bool ContainsReferencedTable(ColumnExpression column)
27242731
return false;
27252732
}
27262733

2734+
private bool TryGetTable(ColumnExpression column, [NotNullWhen(true)] out TableExpressionBase? table, out int tableIndex)
2735+
{
2736+
for (var i = 0; i < _tables.Count; i++)
2737+
{
2738+
var t = _tables[i];
2739+
if (t.UnwrapJoin().Alias == column.TableAlias)
2740+
{
2741+
table = t;
2742+
tableIndex = i;
2743+
return true;
2744+
}
2745+
}
2746+
2747+
table = null;
2748+
tableIndex = 0;
2749+
return false;
2750+
}
2751+
27272752
private enum JoinType
27282753
{
27292754
InnerJoin,

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

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

52775277
#endregion ToPageAsync
52785278

5279+
public override async Task Column_access_inside_subquery_predicate(bool async)
5280+
{
5281+
// Uncorrelated subquery, not supported by Cosmos
5282+
await AssertTranslationFailed(() => base.Column_access_inside_subquery_predicate(async));
5283+
5284+
AssertSql();
5285+
}
5286+
52795287
private void AssertSql(params string[] expected)
52805288
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
52815289

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

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

58505850
private static string StaticProperty
58515851
=> "ALF";
5852+
5853+
[ConditionalTheory] // #35118
5854+
[MemberData(nameof(IsAsyncData))]
5855+
public virtual Task Column_access_inside_subquery_predicate(bool async)
5856+
=> AssertQuery(
5857+
async,
5858+
ss => ss.Set<Customer>().Where(c => ss.Set<Order>().Where(o => c.CustomerID == "ALFKI").Any()));
58525859
}

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

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

7464+
public override async Task Column_access_inside_subquery_predicate(bool async)
7465+
{
7466+
await base.Column_access_inside_subquery_predicate(async);
7467+
7468+
AssertSql(
7469+
"""
7470+
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
7471+
FROM [Customers] AS [c]
7472+
WHERE EXISTS (
7473+
SELECT 1
7474+
FROM [Orders] AS [o]
7475+
WHERE [c].[CustomerID] = N'ALFKI')
7476+
""");
7477+
}
7478+
74647479
private void AssertSql(params string[] expected)
74657480
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);
74667481

0 commit comments

Comments
 (0)