Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/6.0] Query: Don't add grouping key to projection when Distinct is applied #28143

Merged
merged 1 commit into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2996,7 +2996,10 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal()
}
}

if (subquery._groupBy.Count > 0)
if (subquery._groupBy.Count > 0
&& (AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue28039", out var enabled28039)
&& enabled28039
|| !subquery.IsDistinct))
{
foreach (var key in subquery._groupBy)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2027,6 +2027,23 @@ from g in grouping
entryCount: 63);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Join_GroupBy_Aggregate_distinct_single_join(bool async)
{
return AssertQuery(
async,
ss =>
from c in ss.Set<Customer>()
join a in ss.Set<Order>().GroupBy(o => new { o.CustomerID, o.OrderDate.Value.Year })
.Where(g => g.Count() > 5)
.Select(g => new { CustomerID = g.Key.CustomerID, LastOrderID = g.Max(o => o.OrderID) })
.Distinct()
on c.CustomerID equals a.CustomerID
select new { c, a.LastOrderID },
entryCount: 31);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Join_GroupBy_Aggregate_with_left_join(bool async)
Expand Down
64 changes: 64 additions & 0 deletions test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -986,5 +986,69 @@ protected class Child26744
public DateTime? SomeOtherNullableDateTime { get; set; }
public Parent26744 Parent { get; set; }
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual async Task Pushdown_does_not_add_grouping_key_to_projection_when_distinct_is_applied(bool async)
{
var contextFactory = await InitializeAsync<Context28039>();
using var db = contextFactory.CreateContext();


var queryResults = (from i in db.IndexData.Where(a => a.Parcel == "some condition")
.Select(a => new SearchResult { ParcelNumber = a.Parcel, RowId = a.RowId })
group i by new { i.ParcelNumber, i.RowId } into grp
where grp.Count() == 1
select grp.Key.ParcelNumber).Distinct();

var jsonLookup = (from dcv in db.TableData.Where(a => a.TableId == 123)
join wos in queryResults
on dcv.ParcelNumber equals wos
orderby dcv.ParcelNumber
select dcv.JSON).Take(123456);


var result = async
? await jsonLookup.ToListAsync()
: jsonLookup.ToList();
}

protected class Context28039 : DbContext
{
public Context28039(DbContextOptions options)
: base(options)
{
}

public DbSet<IndexData> IndexData { get; set; }
public DbSet<TableData> TableData { get; set; }
}

public class TableData : EntityBase
{
public int TableId { get; set; }
public string ParcelNumber { get; set; }
public short RowId { get; set; }
public string JSON { get; set; }

}

public abstract class EntityBase
{
[Key]
public int ID { get; set; }
}
public class IndexData : EntityBase
{
public string Parcel { get; set; }
public int RowId { get; set; }
}

internal class SearchResult
{
public string ParcelNumber { get; set; }
public int RowId { get; set; }
public string DistinctValue { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1517,6 +1517,21 @@ HAVING COUNT(*) > 5
INNER JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID]");
}

public override async Task Join_GroupBy_Aggregate_distinct_single_join(bool async)
{
await base.Join_GroupBy_Aggregate_distinct_single_join(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], [t].[LastOrderID]
FROM [Customers] AS [c]
INNER JOIN (
SELECT DISTINCT [o].[CustomerID], MAX([o].[OrderID]) AS [LastOrderID]
FROM [Orders] AS [o]
GROUP BY [o].[CustomerID], DATEPART(year, [o].[OrderDate])
HAVING COUNT(*) > 5
) AS [t] ON [c].[CustomerID] = [t].[CustomerID]");
}

public override async Task Join_GroupBy_Aggregate_with_left_join(bool async)
{
await base.Join_GroupBy_Aggregate_with_left_join(async);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,5 +297,25 @@ WHERE [c].[SomeNullableDateTime] IS NULL
) AS [t0] ON [p].[Id] = [t0].[ParentId]
WHERE [t0].[SomeOtherNullableDateTime] IS NOT NULL");
}

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

AssertSql(
@"@__p_0='123456'

SELECT TOP(@__p_0) [t].[JSON]
FROM [TableData] AS [t]
INNER JOIN (
SELECT DISTINCT [i].[Parcel]
FROM [IndexData] AS [i]
WHERE [i].[Parcel] = N'some condition'
GROUP BY [i].[Parcel], [i].[RowId]
HAVING COUNT(*) = 1
) AS [t0] ON [t].[ParcelNumber] = [t0].[Parcel]
WHERE [t].[TableId] = 123
ORDER BY [t].[ParcelNumber]");
}
}
}