Skip to content
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 @@ -286,7 +286,7 @@ protected override Expression VisitExtension(Expression expression)
var navigation = collectionResultExpression.StructuralProperty switch
{
INavigationBase n => n,
null => null,
null or IComplexProperty => null,
_ => throw new UnreachableException()
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,14 @@ FROM root c

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
if (queryTrackingBehavior is not QueryTrackingBehavior.TrackAll)
{
await AssertTranslationFailed(() => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));
}
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
if (queryTrackingBehavior is not QueryTrackingBehavior.TrackAll)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ public virtual Task Select_subquery_optional_related_FirstOrDefault(QueryTrackin
.FirstOrDefault()!.RequiredNestedAssociate),
queryTrackingBehavior: queryTrackingBehavior);

[ConditionalTheory, MemberData(nameof(TrackingData))]
public virtual Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> AssertQuery(
ss => ss.Set<RootEntity>()
.OrderBy(x => x.Id)
.Select(x => ss.Set<RootEntity>()
.OrderBy(e => e.Id)
.FirstOrDefault()!.AssociateCollection),
assertOrder: true,
elementAsserter: (e, a) => AssertCollection(e, a, elementSorter: r => r.Id),
queryTrackingBehavior: queryTrackingBehavior);

// [ConditionalTheory]
// [MemberData(nameof(TrackingData))]
// public virtual Task Select_subquery_root_set_trunk_FirstOrDefault_collection(QueryTrackingBehavior queryTrackingBehavior)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ public override Task SelectMany_nested_collection_on_optional_associate(QueryTra

#region Subquery

public override Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> AssertOwnedTrackingQuery(
queryTrackingBehavior, () => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));

public override Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
=> AssertOwnedTrackingQuery(
queryTrackingBehavior, () => base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,23 @@ FROM [RootEntity] AS [r]

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

AssertSql(
"""
SELECT [r1].[c], [r1].[c0]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) [r0].[AssociateCollection] AS [c], 1 AS [c0]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r1]
ORDER BY [r].[Id]
""");
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,23 @@ FROM [RootEntity] AS [r]

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

AssertSql(
"""
SELECT [r1].[Id], [r1].[Name], [r1].[OptionalAssociate_Id], [r1].[OptionalAssociate_Int], [r1].[OptionalAssociate_Ints], [r1].[OptionalAssociate_Name], [r1].[OptionalAssociate_String], [r1].[OptionalAssociate_OptionalNestedAssociate_Id], [r1].[OptionalAssociate_OptionalNestedAssociate_Int], [r1].[OptionalAssociate_OptionalNestedAssociate_Ints], [r1].[OptionalAssociate_OptionalNestedAssociate_Name], [r1].[OptionalAssociate_OptionalNestedAssociate_String], [r1].[OptionalAssociate_RequiredNestedAssociate_Id], [r1].[OptionalAssociate_RequiredNestedAssociate_Int], [r1].[OptionalAssociate_RequiredNestedAssociate_Ints], [r1].[OptionalAssociate_RequiredNestedAssociate_Name], [r1].[OptionalAssociate_RequiredNestedAssociate_String], [r1].[RequiredAssociate_Id], [r1].[RequiredAssociate_Int], [r1].[RequiredAssociate_Ints], [r1].[RequiredAssociate_Name], [r1].[RequiredAssociate_String], [r1].[RequiredAssociate_OptionalNestedAssociate_Id], [r1].[RequiredAssociate_OptionalNestedAssociate_Int], [r1].[RequiredAssociate_OptionalNestedAssociate_Ints], [r1].[RequiredAssociate_OptionalNestedAssociate_Name], [r1].[RequiredAssociate_OptionalNestedAssociate_String], [r1].[RequiredAssociate_RequiredNestedAssociate_Id], [r1].[RequiredAssociate_RequiredNestedAssociate_Int], [r1].[RequiredAssociate_RequiredNestedAssociate_Ints], [r1].[RequiredAssociate_RequiredNestedAssociate_Name], [r1].[RequiredAssociate_RequiredNestedAssociate_String], [r1].[c]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) [r0].[Id], [r0].[Name], [r0].[OptionalAssociate_Id], [r0].[OptionalAssociate_Int], [r0].[OptionalAssociate_Ints], [r0].[OptionalAssociate_Name], [r0].[OptionalAssociate_String], [r0].[OptionalAssociate_OptionalNestedAssociate_Id], [r0].[OptionalAssociate_OptionalNestedAssociate_Int], [r0].[OptionalAssociate_OptionalNestedAssociate_Ints], [r0].[OptionalAssociate_OptionalNestedAssociate_Name], [r0].[OptionalAssociate_OptionalNestedAssociate_String], [r0].[OptionalAssociate_RequiredNestedAssociate_Id], [r0].[OptionalAssociate_RequiredNestedAssociate_Int], [r0].[OptionalAssociate_RequiredNestedAssociate_Ints], [r0].[OptionalAssociate_RequiredNestedAssociate_Name], [r0].[OptionalAssociate_RequiredNestedAssociate_String], [r0].[RequiredAssociate_Id], [r0].[RequiredAssociate_Int], [r0].[RequiredAssociate_Ints], [r0].[RequiredAssociate_Name], [r0].[RequiredAssociate_String], [r0].[RequiredAssociate_OptionalNestedAssociate_Id], [r0].[RequiredAssociate_OptionalNestedAssociate_Int], [r0].[RequiredAssociate_OptionalNestedAssociate_Ints], [r0].[RequiredAssociate_OptionalNestedAssociate_Name], [r0].[RequiredAssociate_OptionalNestedAssociate_String], [r0].[RequiredAssociate_RequiredNestedAssociate_Id], [r0].[RequiredAssociate_RequiredNestedAssociate_Int], [r0].[RequiredAssociate_RequiredNestedAssociate_Ints], [r0].[RequiredAssociate_RequiredNestedAssociate_Name], [r0].[RequiredAssociate_RequiredNestedAssociate_String], 1 AS [c]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r1]
ORDER BY [r].[Id]
""");
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,30 @@ FROM [AssociateType] AS [a2]

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

AssertSql(
"""
SELECT [r].[Id], [r1].[Id], [s].[Id], [s].[CollectionRootId], [s].[Int], [s].[Ints], [s].[Name], [s].[OptionalNestedAssociateId], [s].[RequiredNestedAssociateId], [s].[String], [s].[Id0], [s].[Id1], [s].[Id2], [s].[CollectionAssociateId], [s].[Int0], [s].[Ints0], [s].[Name0], [s].[String0], [s].[CollectionAssociateId0], [s].[Int1], [s].[Ints1], [s].[Name1], [s].[String1], [s].[CollectionAssociateId1], [s].[Int2], [s].[Ints2], [s].[Name2], [s].[String2], [r1].[c]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) 1 AS [c], [r0].[Id]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r1]
LEFT JOIN (
SELECT [a].[Id], [a].[CollectionRootId], [a].[Int], [a].[Ints], [a].[Name], [a].[OptionalNestedAssociateId], [a].[RequiredNestedAssociateId], [a].[String], [n].[Id] AS [Id0], [n0].[Id] AS [Id1], [n1].[Id] AS [Id2], [n1].[CollectionAssociateId], [n1].[Int] AS [Int0], [n1].[Ints] AS [Ints0], [n1].[Name] AS [Name0], [n1].[String] AS [String0], [n].[CollectionAssociateId] AS [CollectionAssociateId0], [n].[Int] AS [Int1], [n].[Ints] AS [Ints1], [n].[Name] AS [Name1], [n].[String] AS [String1], [n0].[CollectionAssociateId] AS [CollectionAssociateId1], [n0].[Int] AS [Int2], [n0].[Ints] AS [Ints2], [n0].[Name] AS [Name2], [n0].[String] AS [String2]
FROM [AssociateType] AS [a]
LEFT JOIN [NestedAssociateType] AS [n] ON [a].[OptionalNestedAssociateId] = [n].[Id]
INNER JOIN [NestedAssociateType] AS [n0] ON [a].[RequiredNestedAssociateId] = [n0].[Id]
LEFT JOIN [NestedAssociateType] AS [n1] ON [a].[Id] = [n1].[CollectionAssociateId]
) AS [s] ON [r1].[Id] = [s].[CollectionRootId]
ORDER BY [r].[Id], [r1].[Id], [s].[Id], [s].[Id0], [s].[Id1]
""");
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,26 @@ FROM [RootEntity] AS [r]

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

if (queryTrackingBehavior is not QueryTrackingBehavior.TrackAll)
{
AssertSql(
"""
SELECT [r1].[c], [r1].[Id], [r1].[c0]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) [r0].[AssociateCollection] AS [c], [r0].[Id], 1 AS [c0]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r1]
ORDER BY [r].[Id]
""");
}
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,33 @@ FROM [RelatedCollection] AS [r8]

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

if (queryTrackingBehavior is not QueryTrackingBehavior.TrackAll)
{
AssertSql(
"""
SELECT [r].[Id], [r5].[Id], [s].[RootEntityId], [s].[Id], [s].[Int], [s].[Ints], [s].[Name], [s].[String], [s].[AssociateTypeRootEntityId], [s].[AssociateTypeId], [s].[AssociateTypeRootEntityId0], [s].[AssociateTypeId0], [s].[AssociateTypeRootEntityId1], [s].[AssociateTypeId1], [s].[Id0], [s].[Int0], [s].[Ints0], [s].[Name0], [s].[String0], [s].[Id1], [s].[Int1], [s].[Ints1], [s].[Name1], [s].[String1], [s].[Id2], [s].[Int2], [s].[Ints2], [s].[Name2], [s].[String2], [r5].[c]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) 1 AS [c], [r0].[Id]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r5]
LEFT JOIN (
SELECT [r1].[RootEntityId], [r1].[Id], [r1].[Int], [r1].[Ints], [r1].[Name], [r1].[String], [r2].[AssociateTypeRootEntityId], [r2].[AssociateTypeId], [r3].[AssociateTypeRootEntityId] AS [AssociateTypeRootEntityId0], [r3].[AssociateTypeId] AS [AssociateTypeId0], [r4].[AssociateTypeRootEntityId] AS [AssociateTypeRootEntityId1], [r4].[AssociateTypeId] AS [AssociateTypeId1], [r4].[Id] AS [Id0], [r4].[Int] AS [Int0], [r4].[Ints] AS [Ints0], [r4].[Name] AS [Name0], [r4].[String] AS [String0], [r2].[Id] AS [Id1], [r2].[Int] AS [Int1], [r2].[Ints] AS [Ints1], [r2].[Name] AS [Name1], [r2].[String] AS [String1], [r3].[Id] AS [Id2], [r3].[Int] AS [Int2], [r3].[Ints] AS [Ints2], [r3].[Name] AS [Name2], [r3].[String] AS [String2]
FROM [RelatedCollection] AS [r1]
LEFT JOIN [RelatedCollection_OptionalNested] AS [r2] ON [r1].[RootEntityId] = [r2].[AssociateTypeRootEntityId] AND [r1].[Id] = [r2].[AssociateTypeId]
LEFT JOIN [RelatedCollection_RequiredNested] AS [r3] ON [r1].[RootEntityId] = [r3].[AssociateTypeRootEntityId] AND [r1].[Id] = [r3].[AssociateTypeId]
LEFT JOIN [RelatedCollection_NestedCollection] AS [r4] ON [r1].[RootEntityId] = [r4].[AssociateTypeRootEntityId] AND [r1].[Id] = [r4].[AssociateTypeId]
) AS [s] ON [r5].[Id] = [s].[RootEntityId]
ORDER BY [r].[Id], [r5].[Id], [s].[RootEntityId], [s].[Id], [s].[AssociateTypeRootEntityId], [s].[AssociateTypeId], [s].[AssociateTypeRootEntityId0], [s].[AssociateTypeId0], [s].[AssociateTypeRootEntityId1], [s].[AssociateTypeId1]
""");
}
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,31 @@ WHEN [r].[OptionalAssociate_Id] IS NOT NULL AND [r].[OptionalAssociate_Int] IS N

#region Subquery

public override async Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior);

if (queryTrackingBehavior is not QueryTrackingBehavior.TrackAll)
{
AssertSql(
"""
SELECT [r].[Id], [r3].[Id], [s].[RootEntityId], [s].[Id], [s].[Int], [s].[Ints], [s].[Name], [s].[String], [s].[AssociateTypeRootEntityId], [s].[AssociateTypeId], [s].[Id0], [s].[Int0], [s].[Ints0], [s].[Name0], [s].[String0], [s].[OptionalNestedAssociate_Id], [s].[OptionalNestedAssociate_Int], [s].[OptionalNestedAssociate_Ints], [s].[OptionalNestedAssociate_Name], [s].[OptionalNestedAssociate_String], [s].[RequiredNestedAssociate_Id], [s].[RequiredNestedAssociate_Int], [s].[RequiredNestedAssociate_Ints], [s].[RequiredNestedAssociate_Name], [s].[RequiredNestedAssociate_String], [r3].[c]
FROM [RootEntity] AS [r]
OUTER APPLY (
SELECT TOP(1) 1 AS [c], [r0].[Id]
FROM [RootEntity] AS [r0]
ORDER BY [r0].[Id]
) AS [r3]
LEFT JOIN (
SELECT [r1].[RootEntityId], [r1].[Id], [r1].[Int], [r1].[Ints], [r1].[Name], [r1].[String], [r2].[AssociateTypeRootEntityId], [r2].[AssociateTypeId], [r2].[Id] AS [Id0], [r2].[Int] AS [Int0], [r2].[Ints] AS [Ints0], [r2].[Name] AS [Name0], [r2].[String] AS [String0], [r1].[OptionalNestedAssociate_Id], [r1].[OptionalNestedAssociate_Int], [r1].[OptionalNestedAssociate_Ints], [r1].[OptionalNestedAssociate_Name], [r1].[OptionalNestedAssociate_String], [r1].[RequiredNestedAssociate_Id], [r1].[RequiredNestedAssociate_Int], [r1].[RequiredNestedAssociate_Ints], [r1].[RequiredNestedAssociate_Name], [r1].[RequiredNestedAssociate_String]
FROM [RelatedCollection] AS [r1]
LEFT JOIN [RelatedCollection_NestedCollection] AS [r2] ON [r1].[RootEntityId] = [r2].[AssociateTypeRootEntityId] AND [r1].[Id] = [r2].[AssociateTypeId]
) AS [s] ON [r3].[Id] = [s].[RootEntityId]
ORDER BY [r].[Id], [r3].[Id], [s].[RootEntityId], [s].[Id], [s].[AssociateTypeRootEntityId], [s].[AssociateTypeId]
""");
}
}

public override async Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
{
await base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public override Task SelectMany_nested_collection_on_required_associate(QueryTra
public override Task SelectMany_nested_collection_on_optional_associate(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.SelectMany_nested_collection_on_optional_associate(queryTrackingBehavior));

public override Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));

public override Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Query.Associations.ComplexTableSplitting
public class ComplexTableSplittingProjectionSqliteTest(ComplexTableSplittingSqliteFixture fixture, ITestOutputHelper testOutputHelper)
: ComplexTableSplittingProjectionRelationalTestBase<ComplexTableSplittingSqliteFixture>(fixture, testOutputHelper)
{
public override Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));

public override Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Microsoft.EntityFrameworkCore.Query.Associations.Navigations;
public class NavigationsProjectionSqliteTest(NavigationsSqliteFixture fixture, ITestOutputHelper testOutputHelper)
: NavigationsProjectionRelationalTestBase<NavigationsSqliteFixture>(fixture, testOutputHelper)
{
public override Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));

public override Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
=> AssertApplyNotSupported(() => base.Select_subquery_required_related_FirstOrDefault(queryTrackingBehavior));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public override Task SelectMany_nested_collection_on_optional_associate(QueryTra
? Task.CompletedTask // Base test expects "can't track owned entities" exception, but with SQLite we get "no CROSS APPLY"
: AssertApplyNotSupported(() => base.SelectMany_nested_collection_on_optional_associate(queryTrackingBehavior));

public override Task Select_subquery_FirstOrDefault_complex_collection(QueryTrackingBehavior queryTrackingBehavior)
=> queryTrackingBehavior is QueryTrackingBehavior.TrackAll
? Task.CompletedTask // Base test expects "can't track owned entities" exception, but with SQLite we get "no CROSS APPLY"
: AssertApplyNotSupported(() => base.Select_subquery_FirstOrDefault_complex_collection(queryTrackingBehavior));

public override Task Select_subquery_required_related_FirstOrDefault(QueryTrackingBehavior queryTrackingBehavior)
=> queryTrackingBehavior is QueryTrackingBehavior.TrackAll
? Task.CompletedTask // Base test expects "can't track owned entities" exception, but with SQLite we get "no CROSS APPLY"
Expand Down