From 03ca42e2f7bd4ebca74dbc6a4c1da9fbabd98418 Mon Sep 17 00:00:00 2001 From: Maurycy Markowski Date: Mon, 7 Oct 2019 14:29:18 -0700 Subject: [PATCH] Adding tests for various group by scenarios - added regression tests for #12289 - added regression tests for #15279 - added regression tests for #15938 - added regression tests for #18267 - resolves #12522 - resolves #12805 - resolves #13231 - resolves #13594 - resolves #13754 - resolves #14851 - resolves #15103 - resolves #15669 - resolves #15853 --- .../Query/GearsOfWarQueryInMemoryTest.cs | 6 + .../Query/GearsOfWarQueryTestBase.cs | 151 +++++++++ .../Query/GroupByQueryTestBase.cs | 317 +++++++++++++++++- .../ProceduralQueryExpressionGenerator.cs | 5 - .../Query/GearsOfWarQuerySqlServerTest.cs | 94 ++++++ .../Query/GroupByQuerySqlServerTest.cs | 165 +++++++++ 6 files changed, 723 insertions(+), 15 deletions(-) diff --git a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs index 0fc031a5ab2..e5ecb432950 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs @@ -62,5 +62,11 @@ public override Task Null_semantics_is_correctly_applied_for_function_comparison { return base.Null_semantics_is_correctly_applied_for_function_comparisons_that_take_arguments_from_optional_navigation_complex(isAsync); } + + [ConditionalTheory(Skip = "issue #18284")] + public override Task GroupBy_with_boolean_groupin_key_thru_navigation_access(bool isAsync) + { + return GroupBy_with_boolean_groupin_key_thru_navigation_access(isAsync); + } } } diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index a7c0716e1d3..c879c7ad756 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -7753,6 +7753,157 @@ public virtual Task Project_entity_and_collection_element(bool isAsync) }); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_GroupBy_after_set_operator(bool isAsync) + { + return AssertQuery( + isAsync, + ss => (from g in ss.Set() + select new + { + g.AssignedCity.Name, + Count = g.Weapons.Count(), + }).Concat( + from g in ss.Set() + select new + { + g.CityOfBirth.Name, + Count = g.Weapons.Count(), + }) + .GroupBy(x => new { x.Name, x.Count }) + .Select(g => new { g.Key.Name, g.Key.Count, Sum = g.Sum(xx => xx.Count) }), + ss => (from g in ss.Set() + select new + { + Name = Maybe(g.AssignedCity, () => g.AssignedCity.Name), + Count = g.Weapons.Count(), + }).Concat( + from g in ss.Set() + select new + { + g.CityOfBirth.Name, + Count = g.Weapons.Count(), + }) + .GroupBy(x => new { x.Name, x.Count }) + .Select(g => new { g.Key.Name, g.Key.Count, Sum = g.Sum(xx => xx.Count) }), + elementSorter: e => (e.Name, e.Count, e.Sum)); + } + + [ConditionalTheory(Skip = "issue #18267")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_GroupBy_after_set_operator_using_result_selector(bool isAsync) + { + return AssertQuery( + isAsync, + ss => (from g in ss.Set() + select new + { + g.AssignedCity.Name, + Count = g.Weapons.Count(), + }).Concat( + from g in ss.Set() + select new + { + g.CityOfBirth.Name, + Count = g.Weapons.Count(), + }) + .GroupBy( + x => new { x.Name, x.Count }, + (k, g) => new { k.Name, k.Count, Sum = g.Sum(xx => xx.Count) }), + ss => (from g in ss.Set() + select new + { + Name = Maybe(g.AssignedCity, () => g.AssignedCity.Name), + Count = g.Weapons.Count(), + }).Concat( + from g in ss.Set() + select new + { + g.CityOfBirth.Name, + Count = g.Weapons.Count(), + }) + .GroupBy( + x => new { x.Name, x.Count }, + (k, g) => new { k.Name, k.Count, Sum = g.Sum(xx => xx.Count) }), + elementSorter: e => (e.Name, e.Count, e.Sum)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Left_join_with_GroupBy_with_composite_group_key(bool isAsync) + { + return AssertQuery( + isAsync, + ss => from g in ss.Set() + join s in ss.Set() on g.SquadId equals s.Id + join t in ss.Set() on g.Nickname equals t.GearNickName into grouping + from t in grouping.DefaultIfEmpty() + group g by new { g.CityOrBirthName, g.HasSoulPatch } into groupby + select new { groupby.Key.CityOrBirthName, groupby.Key.HasSoulPatch }, + elementSorter: e => (e.CityOrBirthName, e.HasSoulPatch)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_boolean_grouping_key(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(g => new { g.Nickname, g.CityOrBirthName, g.HasSoulPatch, IsMarcus = g.Nickname == "Marcus" }) + .GroupBy(g => new { g.CityOrBirthName, g.HasSoulPatch, g.IsMarcus }) + .Select(x => new { x.Key.CityOrBirthName, x.Key.HasSoulPatch, x.Key.IsMarcus, Count = x.Count() }), + elementSorter: e => (e.CityOrBirthName, e.HasSoulPatch, e.IsMarcus, e.Count)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_boolean_groupin_key_thru_navigation_access(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(t => new { t.Gear.HasSoulPatch, t.Gear.Squad.Name }) + .Select(g => new { g.Key.HasSoulPatch, Name = g.Key.Name.ToLower() }), + ss => ss.Set() + .GroupBy(t => new + { + HasSoulPatch = MaybeScalar(t.Gear, () => t.Gear.HasSoulPatch) ?? false, + Name = Maybe(t.Gear, () => t.Gear.Squad.Name) + }) + .Select(g => new { g.Key.HasSoulPatch, Name = Maybe(g.Key.Name, () => g.Key.Name.ToLower()) }), + elementSorter: e => (e.HasSoulPatch, e.Name)); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Group_by_over_projection_with_multiple_properties_accessed_thru_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(g => new + { + g.Nickname, + AssignedCityName = g.AssignedCity.Name, + CityOfBirthName = g.CityOfBirth.Name, + SquadName = g.Squad.Name + }) + .GroupBy(x => x.CityOfBirthName) + .Select(g => g.Key), + ss => ss.Set() + .Select(g => new + { + g.Nickname, + AssignedCityName = Maybe(g.AssignedCity, () => g.AssignedCity.Name), + CityOfBirthName = Maybe(g.CityOfBirth, () => g.CityOfBirth.Name), + SquadName = g.Squad.Name + }) + .GroupBy(x => x.CityOfBirthName) + .Select(g => g.Key)); + } + protected GearsOfWarContext CreateContext() => Fixture.CreateContext(); protected virtual void ClearLog() diff --git a/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs index 9646f0715a9..9eb6f2c9097 100644 --- a/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs @@ -272,6 +272,95 @@ public virtual Task GroupBy_aggregate_projecting_conditional_expression_based_on e => e.Sum); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_access_thru_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order.CustomerID) + .Select(g => new + { + g.Key, + Aggregate = g.Sum(od => od.OrderID), + }), + elementSorter: e => e.Key); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_access_thru_nested_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order.Customer.Country) + .Select(g => new + { + g.Key, + Aggregate = g.Sum(od => od.OrderID), + }), + elementSorter: e => e.Key); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_grouping_key_using_Like(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(o => EF.Functions.Like(o.CustomerID, "A%")) + .Select(g => new { g.Key, Count = g.Count() }), + elementSorter: e => e.Key); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_grouping_key_DateTime_Day(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(o => o.OrderDate.Value.Day) + .Select(g => new { g.Key, Count = g.Count() }), + elementSorter: e => e.Key); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_cast_inside_grouping_aggregate(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(o => o.CustomerID) + .Select(g => new { g.Key, Count = g.Count(), Sum = g.Sum(o => (long)o.OrderID) }), + elementSorter: e => e.Key); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Group_by_with_arithmetic_operation_inside_aggregate(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(o => o.CustomerID) + .Select(g => new + { + g.Key, + Sum = g.Sum(o => o.OrderID + o.CustomerID.Length) + }), + elementSorter: e => e.Key, + elementAsserter: (e, a) => + { + Assert.Equal(e.Key, a.Key); + Assert.Equal(e.Sum, a.Sum); + }); + } + #endregion #region GroupByAnonymousAggregate @@ -869,6 +958,32 @@ public virtual Task GroupBy_anonymous_key_type_mismatch_with_aggregate(bool isAs elementSorter: a => a.I1); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_based_on_renamed_property_simple(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(g => new { Renamed = g.City }) + .Select(x => new { x.Key, Count = x.Count() }), + elementSorter: e => e.Key.Renamed); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_based_on_renamed_property_complex(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(x => new { Renamed = x.City, x.CustomerID }) + .Distinct() + .GroupBy(g => g.Renamed) + .Select(x => new { x.Key, Count = x.Count() }), + elementSorter: e => e.Key); + } + #endregion #region GroupByWithElementSelectorAggregate @@ -1774,6 +1889,21 @@ public virtual Task GroupBy_composite_Key_as_part_of_element_selector(bool isAsy g => new { g.Key, Avg = g.Average(e => e.OrderID), Max = g.Max(o => o.OrderDate) })); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_order_by_skip_and_another_order_by(bool isAsync) + { + return AssertQueryScalar( + isAsync, + ss => ss.Set() + .OrderBy(o => o.CustomerID) + .Skip(80) + .OrderBy(o => o.CustomerID) + .GroupBy(o => o.CustomerID) + .Select(g => g.Sum(o => o.OrderID)) + ); + } + #endregion #region GroupByWithoutAggregate @@ -2235,6 +2365,76 @@ into grp select new { C = grp.Key, Os = grp.ToList() }); } + [ConditionalTheory(Skip = "issue #15938")] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_being_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select(g => new + { + g.Key, + Aggregate = g.Sum(od => od.OrderID), + }), + elementSorter: e => e.Key); + } + + [ConditionalTheory(Skip = "issue #15938")] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_being_nested_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order.Customer) + .Select(g => new + { + g.Key, + Aggregate = g.Sum(od => od.OrderID), + }), + elementSorter: e => e.Key); + } + + [ConditionalTheory(Skip = "issue #15938")] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_being_navigation_with_entity_key_projection(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select(g => g.Key)); + } + + [ConditionalTheory(Skip = "issue #15938")] + [MemberData(nameof(IsAsyncData))] + public virtual Task GroupBy_with_group_key_being_navigation_with_complex_projection(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select(g => new + { + g.Key, + Id1 = g.Key.CustomerID, + Id2 = g.Key.Customer.CustomerID, + Id3 = g.Key.OrderID, + Aggregate = g.Sum(od => od.OrderID), + }), + elementSorter: e => e.Id3, + elementAsserter: (e, a) => + { + AssertEqual(e.Key, a.Key); + Assert.Equal(e.Id1, a.Id1); + Assert.Equal(e.Id2, a.Id2); + Assert.Equal(e.Id3, a.Id3); + Assert.Equal(e.Aggregate, a.Aggregate); + }); + } + #endregion #region DoubleGroupBy @@ -2297,9 +2497,9 @@ await AssertMax( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task All_after_GroupBy_aggregate(bool isAsync) + public virtual Task All_after_GroupBy_aggregate(bool isAsync) { - await AssertAll( + return AssertAll( isAsync, ss => ss.Set().GroupBy(o => o.CustomerID).Select(g => g.Sum(gg => gg.OrderID)), predicate: ee => true); @@ -2307,9 +2507,9 @@ await AssertAll( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task All_after_GroupBy_aggregate2(bool isAsync) + public virtual Task All_after_GroupBy_aggregate2(bool isAsync) { - await AssertAll( + return AssertAll( isAsync, ss => ss.Set().GroupBy(o => o.CustomerID).Select(g => g.Sum(gg => gg.OrderID)), predicate: ee => ee >= 0); @@ -2317,31 +2517,128 @@ await AssertAll( [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual async Task Any_after_GroupBy_aggregate(bool isAsync) + public virtual Task Any_after_GroupBy_aggregate(bool isAsync) { - await AssertAny( + return AssertAny( isAsync, ss => ss.Set().GroupBy(o => o.CustomerID).Select(g => g.Sum(gg => gg.OrderID))); } [ConditionalTheory(Skip = "Issue#15097")] [MemberData(nameof(IsAsyncData))] - public virtual async Task Count_after_GroupBy_without_aggregate(bool isAsync) + public virtual Task Count_after_GroupBy_without_aggregate(bool isAsync) { - await AssertCount( + return AssertCount( isAsync, ss => ss.Set().GroupBy(o => o.CustomerID)); } [ConditionalTheory(Skip = "Issue#15097")] [MemberData(nameof(IsAsyncData))] - public virtual async Task LongCount_after_GroupBy_without_aggregate(bool isAsync) + public virtual Task LongCount_after_GroupBy_without_aggregate(bool isAsync) { - await AssertLongCount( + return AssertLongCount( isAsync, ss => ss.Set().GroupBy(o => o.CustomerID)); } #endregion + + # region GroupByInSubquery + + [ConditionalTheory(Skip = "issue #15279")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_query_with_groupBy_in_subquery(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(c => new + { + Key = c.CustomerID, + Subquery = c.Orders + .Select(o => new + { + First = o.CustomerID, + Second = o.OrderID + }) + .GroupBy(x => x.First) + .Select(g => new + { + Count = g.Count(x => x.First.StartsWith("A")), + Sum = g.Sum(x => x.Second), + }).ToList() + }), + elementSorter: e => e.Key, + elementAsserter: (e, a) => + { + Assert.Equal(e.Key, a.Key); + AssertCollection(e.Subquery, a.Subquery); + }); + } + + [ConditionalTheory(Skip = "issue #15279")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_query_with_groupBy_in_subquery2(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(c => new + { + Key = c.CustomerID, + Subquery = ss.Set() + .Select(o => new + { + First = o.CustomerID, + Second = o.OrderID + }) + .GroupBy(x => x.First) + .Select(g => new + { + Count = g.Count(x => x.First.StartsWith("A")), + Sum = g.Sum(x => x.Second), + }).ToList() + }), + elementSorter: e => e.Key, + elementAsserter: (e, a) => + { + Assert.Equal(e.Key, a.Key); + AssertCollection(e.Subquery, a.Subquery); + }); + } + + [ConditionalTheory(Skip = "issue #15279")] + [MemberData(nameof(IsAsyncData))] + public virtual Task Complex_query_with_groupBy_in_subquery3(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set() + .Select(c => new + { + Key = c.CustomerID, + Subquery = c.Orders + .Select(o => new + { + First = o.OrderID, + Second = o.Customer.City + o.CustomerID + }) + .GroupBy(x => x.Second) + .Select(g => new + { + Sum = g.Sum(x => x.First), + Count = g.Count(x => x.Second.StartsWith("Lon")) + }).ToList() + }), + elementSorter: e => e.Key, + elementAsserter: (e, a) => + { + Assert.Equal(e.Key, a.Key); + AssertCollection(e.Subquery, a.Subquery); + }); + } + + #endregion } } diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs index 831d3feaceb..6842e7f0fb8 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs @@ -245,11 +245,6 @@ static ProcedurallyGeneratedQueryExecutor() AddExpectedFailure( "Join_navigation_translated_to_subquery_non_key_join", "Index was outside the bounds of the array."); // 12804 - AddExpectedFailure("OrderBy_Skip_GroupBy_Aggregate", "Value does not fall within the expected range."); // 12805 - AddExpectedFailure("OrderBy_Skip_Take_GroupBy_Aggregate", "Value does not fall within the expected range."); // 12805 - AddExpectedFailure("GroupJoin_complex_GroupBy_Aggregate", "Value does not fall within the expected range."); // 12805 - AddExpectedFailure("OrderBy_GroupBy_SelectMany", "Value does not fall within the expected range."); // 12805 - AddExpectedFailure( "Select_expression_references_are_updated_correctly_with_subquery", "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value."); // 12819 diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index fced17751e0..9587687e8e3 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -7265,6 +7265,100 @@ WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND (([s].[Id] = @__entity_eq ORDER BY [t].[FullName]"); } + public override async Task Complex_GroupBy_after_set_operator(bool isAsync) + { + await base.Complex_GroupBy_after_set_operator(isAsync); + + AssertSql( + @"SELECT [t].[Name], [t].[Count], SUM([t].[Count]) AS [Sum] +FROM ( + SELECT [c].[Name], ( + SELECT COUNT(*) + FROM [Weapons] AS [w] + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND [w].[OwnerFullName] IS NOT NULL) AS [Count] + FROM [Gears] AS [g] + LEFT JOIN [Cities] AS [c] ON [g].[AssignedCityName] = [c].[Name] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') + UNION ALL + SELECT [c0].[Name], ( + SELECT COUNT(*) + FROM [Weapons] AS [w0] + WHERE ([g0].[FullName] = [w0].[OwnerFullName]) AND [w0].[OwnerFullName] IS NOT NULL) AS [Count] + FROM [Gears] AS [g0] + INNER JOIN [Cities] AS [c0] ON [g0].[CityOrBirthName] = [c0].[Name] + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] +GROUP BY [t].[Name], [t].[Count]"); + } + + public override async Task Complex_GroupBy_after_set_operator_using_result_selector(bool isAsync) + { + await base.Complex_GroupBy_after_set_operator_using_result_selector(isAsync); + + AssertSql( + @""); + } + + public override async Task Left_join_with_GroupBy_with_composite_group_key(bool isAsync) + { + await base.Left_join_with_GroupBy_with_composite_group_key(isAsync); + + AssertSql( + @"SELECT [g].[CityOrBirthName], [g].[HasSoulPatch] +FROM [Gears] AS [g] +INNER JOIN [Squads] AS [s] ON [g].[SquadId] = [s].[Id] +LEFT JOIN [Tags] AS [t] ON [g].[Nickname] = [t].[GearNickName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +GROUP BY [g].[CityOrBirthName], [g].[HasSoulPatch]"); + } + + public override async Task GroupBy_with_boolean_grouping_key(bool isAsync) + { + await base.GroupBy_with_boolean_grouping_key(isAsync); + + AssertSql( + @"SELECT [g].[CityOrBirthName], [g].[HasSoulPatch], CASE + WHEN [g].[Nickname] = N'Marcus' THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsMarcus], COUNT(*) AS [Count] +FROM [Gears] AS [g] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +GROUP BY [g].[CityOrBirthName], [g].[HasSoulPatch], CASE + WHEN [g].[Nickname] = N'Marcus' THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END"); + } + + public override async Task GroupBy_with_boolean_groupin_key_thru_navigation_access(bool isAsync) + { + await base.GroupBy_with_boolean_groupin_key_thru_navigation_access(isAsync); + + AssertSql( + @"SELECT [t0].[HasSoulPatch], LOWER([s].[Name]) AS [Name] +FROM [Tags] AS [t] +LEFT JOIN ( + SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + FROM [Gears] AS [g] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +) AS [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND [t].[GearNickName] IS NOT NULL) AND (([t].[GearSquadId] = [t0].[SquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Squads] AS [s] ON [t0].[SquadId] = [s].[Id] +GROUP BY [t0].[HasSoulPatch], [s].[Name]"); + } + + public override async Task Group_by_over_projection_with_multiple_properties_accessed_thru_navigation(bool isAsync) + { + await base.Group_by_over_projection_with_multiple_properties_accessed_thru_navigation(isAsync); + + AssertSql( + @"SELECT [c].[Name] +FROM [Gears] AS [g] +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +LEFT JOIN [Cities] AS [c0] ON [g].[AssignedCityName] = [c0].[Name] +INNER JOIN [Squads] AS [s] ON [g].[SquadId] = [s].[Id] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +GROUP BY [c].[Name]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs index f4cb765e885..448b197fe4b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs @@ -2020,6 +2020,171 @@ public override async Task LongCount_after_GroupBy_without_aggregate(bool isAsyn AssertSql(" "); } + public override async Task GroupBy_based_on_renamed_property_simple(bool isAsync) + { + await base.GroupBy_based_on_renamed_property_simple(isAsync); + + AssertSql( + @"SELECT [c].[City] AS [Renamed], COUNT(*) AS [Count] +FROM [Customers] AS [c] +GROUP BY [c].[City]"); + } + + public override async Task GroupBy_based_on_renamed_property_complex(bool isAsync) + { + await base.GroupBy_based_on_renamed_property_complex(isAsync); + + AssertSql( + @"SELECT [t].[City] AS [Key], COUNT(*) AS [Count] +FROM ( + SELECT DISTINCT [c].[City], [c].[CustomerID] + FROM [Customers] AS [c] +) AS [t] +GROUP BY [t].[City]"); + } + + public override async Task GroupBy_with_group_key_access_thru_navigation(bool isAsync) + { + await base.GroupBy_with_group_key_access_thru_navigation(isAsync); + + AssertSql( + @"SELECT [o0].[CustomerID] AS [Key], SUM([o].[OrderID]) AS [Aggregate] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +GROUP BY [o0].[CustomerID]"); + } + + public override async Task GroupBy_with_group_key_access_thru_nested_navigation(bool isAsync) + { + await base.GroupBy_with_group_key_access_thru_nested_navigation(isAsync); + + AssertSql( + @"SELECT [c].[Country] AS [Key], SUM([o].[OrderID]) AS [Aggregate] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID] +GROUP BY [c].[Country]"); + } + + public override async Task GroupBy_with_group_key_being_navigation(bool isAsync) + { + await base.GroupBy_with_group_key_being_navigation(isAsync); + + AssertSql( + @""); + } + + public override async Task GroupBy_with_group_key_being_nested_navigation(bool isAsync) + { + await base.GroupBy_with_group_key_being_nested_navigation(isAsync); + + AssertSql( + @""); + } + + public override async Task GroupBy_with_group_key_being_navigation_with_entity_key_projection(bool isAsync) + { + await base.GroupBy_with_group_key_being_navigation_with_entity_key_projection(isAsync); + + AssertSql( + @""); + } + + public override async Task GroupBy_with_group_key_being_navigation_with_complex_projection(bool isAsync) + { + await base.GroupBy_with_group_key_being_navigation_with_complex_projection(isAsync); + + AssertSql( + @""); + } + + public override async Task GroupBy_with_order_by_skip_and_another_order_by(bool isAsync) + { + await base.GroupBy_with_order_by_skip_and_another_order_by(isAsync); + + AssertSql( + @"@__p_0='80' + +SELECT SUM([t].[OrderID]) +FROM ( + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + FROM [Orders] AS [o] + ORDER BY [o].[CustomerID] + OFFSET @__p_0 ROWS +) AS [t] +GROUP BY [t].[CustomerID]"); + } + + public override async Task GroupBy_with_grouping_key_using_Like(bool isAsync) + { + await base.GroupBy_with_grouping_key_using_Like(isAsync); + + AssertSql( + @"SELECT CASE + WHEN [o].[CustomerID] LIKE N'A%' THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [Key], COUNT(*) AS [Count] +FROM [Orders] AS [o] +GROUP BY CASE + WHEN [o].[CustomerID] LIKE N'A%' THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END"); + } + + public override async Task GroupBy_with_grouping_key_DateTime_Day(bool isAsync) + { + await base.GroupBy_with_grouping_key_DateTime_Day(isAsync); + + AssertSql( + @"SELECT DATEPART(day, [o].[OrderDate]) AS [Key], COUNT(*) AS [Count] +FROM [Orders] AS [o] +GROUP BY DATEPART(day, [o].[OrderDate])"); + } + + public override async Task GroupBy_with_cast_inside_grouping_aggregate(bool isAsync) + { + await base.GroupBy_with_cast_inside_grouping_aggregate(isAsync); + + AssertSql( + @"SELECT [o].[CustomerID] AS [Key], COUNT(*) AS [Count], SUM(CAST([o].[OrderID] AS bigint)) AS [Sum] +FROM [Orders] AS [o] +GROUP BY [o].[CustomerID]"); + } + + public override async Task Complex_query_with_groupBy_in_subquery(bool isAsync) + { + await base.Complex_query_with_groupBy_in_subquery(isAsync); + + AssertSql( + @""); + } + + public override async Task Complex_query_with_groupBy_in_subquery2(bool isAsync) + { + await base.Complex_query_with_groupBy_in_subquery2(isAsync); + + AssertSql( + @""); + } + + public override async Task Complex_query_with_groupBy_in_subquery3(bool isAsync) + { + await base.Complex_query_with_groupBy_in_subquery3(isAsync); + + AssertSql( + @""); + } + + public override async Task Group_by_with_arithmetic_operation_inside_aggregate(bool isAsync) + { + await base.Group_by_with_arithmetic_operation_inside_aggregate(isAsync); + + AssertSql( + @"SELECT [o].[CustomerID] AS [Key], SUM([o].[OrderID] + CAST(LEN([o].[CustomerID]) AS int)) AS [Sum] +FROM [Orders] AS [o] +GROUP BY [o].[CustomerID]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected);