Skip to content

Commit

Permalink
Query: Apply pending selector on single result query before trying to…
Browse files Browse the repository at this point in the history
… expand collection navigation (#21690)

Issue: We expand collection navigation when subquery terminates on single result returning. This logic did not apply pending selector. So if the pending selector had another navigation (always reference) which needs to be expanded then we failed to expand collection navigation.

Resolves #13220
  • Loading branch information
smitpatel authored Jul 21, 2020
1 parent 37ecb29 commit a52490b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ protected override Expression VisitMember(MemberExpression memberExpression)
{
// This is FirstOrDefault.Member
// due to SubqueryMemberPushdown, this may be collection navigation which was not pushed down
navigationExpansionExpression = (NavigationExpansionExpression)_pendingSelectorExpandingExpressionVisitor.Visit(navigationExpansionExpression);
var expandedExpression = new ExpandingExpressionVisitor(this, navigationExpansionExpression).Visit(updatedExpression);
if (expandedExpression != updatedExpression)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4163,6 +4163,12 @@ public override Task Max_on_empty_sequence_throws(bool async)
return base.Max_on_empty_sequence_throws(async);
}

[ConditionalTheory(Skip = "Non embedded collection subquery Issue#17246")]
public override Task Pending_selector_in_cardinality_reducing_method_is_applied_before_expanding_collection_navigation_member(bool async)
{
return base.Pending_selector_in_cardinality_reducing_method_is_applied_before_expanding_collection_navigation_member(async);
}

private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6074,5 +6074,30 @@ public virtual async Task Max_on_empty_sequence_throws(bool async)

Assert.Equal("Nullable object must have a value.", message);
}

[ConditionalTheory]
[MemberData(nameof(IsAsyncData))]
public virtual Task Pending_selector_in_cardinality_reducing_method_is_applied_before_expanding_collection_navigation_member(bool async)
{
return AssertQuery(
async,
ss => ss.Set<Customer>()
.Where(c => c.CustomerID.StartsWith("F"))
.OrderBy(c => c.CustomerID)
.Select(c => new
{
Complex = (bool?)c.Orders.OrderBy(e => e.OrderDate).FirstOrDefault().Customer.Orders.Any(e => e.OrderID < 11000)
}),
ss => ss.Set<Customer>()
.Where(c => c.CustomerID.StartsWith("F"))
.OrderBy(c => c.CustomerID)
.Select(c => new
{
Complex = c.Orders.OrderBy(e => e.OrderDate).FirstOrDefault() != null
? c.Orders.OrderBy(e => e.OrderDate).FirstOrDefault().Customer.Orders.Any(e => e.OrderID < 11000)
: (bool?)false
}),
assertOrder: true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5190,6 +5190,38 @@ FROM [Customers] AS [c]
ORDER BY [c].[CustomerID]");
}

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

AssertSql(
@"SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Orders] AS [o]
WHERE ((
SELECT TOP(1) [c].[CustomerID]
FROM [Orders] AS [o0]
LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID]
WHERE [c1].[CustomerID] = [o0].[CustomerID]
ORDER BY [o0].[OrderDate]) IS NOT NULL AND (((
SELECT TOP(1) [c0].[CustomerID]
FROM [Orders] AS [o1]
LEFT JOIN [Customers] AS [c0] ON [o1].[CustomerID] = [c0].[CustomerID]
WHERE [c1].[CustomerID] = [o1].[CustomerID]
ORDER BY [o1].[OrderDate]) = [o].[CustomerID]) OR ((
SELECT TOP(1) [c0].[CustomerID]
FROM [Orders] AS [o1]
LEFT JOIN [Customers] AS [c0] ON [o1].[CustomerID] = [c0].[CustomerID]
WHERE [c1].[CustomerID] = [o1].[CustomerID]
ORDER BY [o1].[OrderDate]) IS NULL AND [o].[CustomerID] IS NULL))) AND ([o].[OrderID] < 11000)) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END AS [Complex]
FROM [Customers] AS [c1]
WHERE [c1].[CustomerID] LIKE N'F%'
ORDER BY [c1].[CustomerID]");
}

private void AssertSql(params string[] expected)
=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected);

Expand Down

0 comments on commit a52490b

Please sign in to comment.