Skip to content

Commit ebc301e

Browse files
authored
Fix GroupBy.Select EmptyProjectionMember (#38140)
Part of #30052 and #31209
1 parent 358c2bd commit ebc301e

4 files changed

Lines changed: 129 additions & 1 deletion

File tree

src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1348,7 +1348,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen
13481348
case { Subquery: { } subquery }:
13491349
{
13501350
var entityShaper = (StructuralTypeShaperExpression)subquery.ShaperExpression;
1351-
var subSelectExpression = (SelectExpression)subquery.QueryExpression;
1351+
var subSelectExpression = ((SelectExpression)subquery.QueryExpression).Clone();
13521352

13531353
var projectionBindingExpression = (ProjectionBindingExpression)entityShaper.ValueBufferExpression;
13541354
var projection = (StructuralTypeProjectionExpression)subSelectExpression.GetProjection(projectionBindingExpression);

test/EFCore.InMemory.FunctionalTests/Query/NorthwindGroupByQueryInMemoryTest.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,16 @@ public override Task Final_GroupBy_TagWith(bool async)
7272
=> AssertTranslationFailedWithDetails(
7373
() => base.Final_GroupBy_TagWith(async),
7474
InMemoryStrings.NonComposedGroupByNotSupported);
75+
76+
[Theory(Skip = "Issue#31209")]
77+
public override Task GroupBy_Select_Anonymous_Type_With_Entire_Entity(bool async)
78+
=> base.GroupBy_Select_Anonymous_Type_With_Entire_Entity(async);
79+
80+
[Theory(Skip = "Issue#31209")]
81+
public override Task GroupBy_Select_Entire_Entity_Order(bool async)
82+
=> base.GroupBy_Select_Entire_Entity_Order(async);
83+
84+
[Theory(Skip = "Issue#31209")]
85+
public override Task GroupBy_Select_Entire_Entity_Where(bool async)
86+
=> base.GroupBy_Select_Entire_Entity_Where(async);
7587
}

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,52 @@ public virtual Task GroupBy_aggregate_join_with_grouping_key(bool async)
19491949
AssertEqual(e.Count, a.Count);
19501950
});
19511951

1952+
[Theory, MemberData(nameof(IsAsyncData))]
1953+
public virtual Task GroupBy_Select_Entire_Entity_Where(bool async) // #31209
1954+
=> AssertQuery(
1955+
async,
1956+
ss => ss.Set<Order>().GroupBy(o => o.CustomerID)
1957+
.Select(a => a.First())
1958+
.Where(x => x.EmployeeID == 6u));
1959+
1960+
[Theory(Skip = "Issue#31209"), MemberData(nameof(IsAsyncData))]
1961+
public virtual Task GroupBy_Select_Entire_Entity_Where_Select(bool async) // #31209
1962+
=> AssertQuery(
1963+
async,
1964+
ss => ss.Set<Order>().GroupBy(x => x.OrderID)
1965+
.Select(x => x.First())
1966+
.Where(x => x.OrderID > 10)
1967+
.Select(r => r.EmployeeID));
1968+
1969+
[Theory(Skip = "Issue#31209"), MemberData(nameof(IsAsyncData))]
1970+
public virtual Task GroupBy_Select_Entire_Entity_Select(bool async) // #31209
1971+
=> AssertQuery(
1972+
async,
1973+
ss => ss.Set<Order>().GroupBy(x => x.OrderID)
1974+
.Select(x => x.First())
1975+
.Select(r => r.EmployeeID));
1976+
1977+
[Theory, MemberData(nameof(IsAsyncData))]
1978+
public virtual Task GroupBy_Select_Entire_Entity_Order(bool async) // #31209
1979+
=> AssertQuery(
1980+
async,
1981+
ss => ss.Set<Order>().GroupBy(o => o.CustomerID)
1982+
.Select(a => a.First())
1983+
.OrderBy(x => x.EmployeeID)
1984+
.ThenBy(x => x.OrderID),
1985+
assertOrder: true);
1986+
1987+
[Theory, MemberData(nameof(IsAsyncData))]
1988+
public virtual Task GroupBy_Select_Anonymous_Type_With_Entire_Entity(bool async) // #31209
1989+
=> AssertQuery(
1990+
async,
1991+
ss => ss.Set<Order>().GroupBy(o => o.CustomerID)
1992+
.Select(g => new
1993+
{
1994+
g.Key,
1995+
Item = g.OrderByDescending(x => x.OrderDate).FirstOrDefault(),
1996+
}).Where(x => x.Item != null));
1997+
19521998
[Theory, MemberData(nameof(IsAsyncData))]
19531999
public virtual Task GroupBy_aggregate_join_with_group_result(bool async)
19542000
=> AssertQuery(

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,6 +3056,76 @@ GROUP BY [o].[CustomerID]
30563056
""");
30573057
}
30583058

3059+
public override async Task GroupBy_Select_Entire_Entity_Where(bool async)
3060+
{
3061+
await base.GroupBy_Select_Entire_Entity_Where(async);
3062+
3063+
AssertSql(
3064+
"""
3065+
SELECT [o4].[OrderID], [o4].[CustomerID], [o4].[EmployeeID], [o4].[OrderDate]
3066+
FROM (
3067+
SELECT [o].[CustomerID]
3068+
FROM [Orders] AS [o]
3069+
GROUP BY [o].[CustomerID]
3070+
HAVING (
3071+
SELECT TOP(1) [o1].[EmployeeID]
3072+
FROM [Orders] AS [o1]
3073+
WHERE [o].[CustomerID] = [o1].[CustomerID] OR ([o].[CustomerID] IS NULL AND [o1].[CustomerID] IS NULL)) = 6
3074+
) AS [o2]
3075+
LEFT JOIN (
3076+
SELECT [o3].[OrderID], [o3].[CustomerID], [o3].[EmployeeID], [o3].[OrderDate]
3077+
FROM (
3078+
SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o0].[CustomerID] ORDER BY [o0].[OrderID]) AS [row]
3079+
FROM [Orders] AS [o0]
3080+
) AS [o3]
3081+
WHERE [o3].[row] <= 1
3082+
) AS [o4] ON [o2].[CustomerID] = [o4].[CustomerID]
3083+
""");
3084+
}
3085+
3086+
public override async Task GroupBy_Select_Entire_Entity_Where_Select(bool async)
3087+
{
3088+
await base.GroupBy_Select_Entire_Entity_Where_Select(async);
3089+
3090+
AssertSql();
3091+
}
3092+
3093+
public override async Task GroupBy_Select_Entire_Entity_Select(bool async)
3094+
{
3095+
await base.GroupBy_Select_Entire_Entity_Select(async);
3096+
3097+
AssertSql();
3098+
}
3099+
3100+
public override async Task GroupBy_Select_Entire_Entity_Order(bool async)
3101+
{
3102+
await base.GroupBy_Select_Entire_Entity_Order(async);
3103+
3104+
AssertSql(
3105+
"""
3106+
SELECT [o5].[OrderID], [o5].[CustomerID], [o5].[EmployeeID], [o5].[OrderDate]
3107+
FROM (
3108+
SELECT [o].[CustomerID], (
3109+
SELECT TOP(1) [o1].[EmployeeID]
3110+
FROM [Orders] AS [o1]
3111+
WHERE [o].[CustomerID] = [o1].[CustomerID] OR ([o].[CustomerID] IS NULL AND [o1].[CustomerID] IS NULL)) AS [c], (
3112+
SELECT TOP(1) [o2].[OrderID]
3113+
FROM [Orders] AS [o2]
3114+
WHERE [o].[CustomerID] = [o2].[CustomerID] OR ([o].[CustomerID] IS NULL AND [o2].[CustomerID] IS NULL)) AS [c0]
3115+
FROM [Orders] AS [o]
3116+
GROUP BY [o].[CustomerID]
3117+
) AS [o3]
3118+
LEFT JOIN (
3119+
SELECT [o4].[OrderID], [o4].[CustomerID], [o4].[EmployeeID], [o4].[OrderDate]
3120+
FROM (
3121+
SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o0].[CustomerID] ORDER BY [o0].[OrderID]) AS [row]
3122+
FROM [Orders] AS [o0]
3123+
) AS [o4]
3124+
WHERE [o4].[row] <= 1
3125+
) AS [o5] ON [o3].[CustomerID] = [o5].[CustomerID]
3126+
ORDER BY [o3].[c], [o3].[c0]
3127+
""");
3128+
}
30593129
public override async Task GroupBy_aggregate_join_with_group_result(bool async)
30603130
{
30613131
await base.GroupBy_aggregate_join_with_group_result(async);

0 commit comments

Comments
 (0)