Skip to content

Commit

Permalink
Push down subquery before using COUNT/COUNT_BIG if the query has an o…
Browse files Browse the repository at this point in the history
…ffset (fixes dotnet#7523)
  • Loading branch information
tuespetre committed Feb 10, 2017
1 parent a457f2e commit 3960a54
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ var collectionSelectExpression

private static Expression HandleCount(HandlerContext handlerContext)
{
if (handlerContext.SelectExpression.Offset != null)
{
handlerContext.SelectExpression.PushDownSubquery();
}

handlerContext.SelectExpression
.SetProjectionExpression(
new SqlFunctionExpression(
Expand Down Expand Up @@ -579,6 +584,11 @@ private static Expression HandleLast(HandlerContext handlerContext)

private static Expression HandleLongCount(HandlerContext handlerContext)
{
if (handlerContext.SelectExpression.Offset != null)
{
handlerContext.SelectExpression.PushDownSubquery();
}

handlerContext.SelectExpression
.SetProjectionExpression(
new SqlFunctionExpression(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3593,6 +3593,33 @@ public virtual async Task Select_bitwise_and_with_logical_and()
}
}

[ConditionalFact]
public virtual async Task Skip_CountAsync()
{
await AssertQuery<Customer>(
cs => cs.Skip(7).CountAsync());
}

[ConditionalFact]
public virtual async Task Skip_LongCountAsync()
{
await AssertQuery<Customer>(
cs => cs.Skip(7).LongCountAsync());
}

[ConditionalFact]
public virtual async Task OrderBy_Skip_CountAsync()
{
await AssertQuery<Customer>(
cs => cs.OrderBy(c => c.Country).Skip(7).CountAsync());
}

[ConditionalFact]
public virtual async Task OrderBy_Skip_LongCountAsync()
{
await AssertQuery<Customer>(
cs => cs.OrderBy(c => c.Country).Skip(7).LongCountAsync());
}

protected NorthwindContext CreateContext()
{
Expand Down Expand Up @@ -3620,6 +3647,20 @@ private async Task AssertQuery<TItem>(
}
}

private async Task AssertQuery<TItem>(
Func<IQueryable<TItem>, Task<long>> query,
bool assertOrder = false)
where TItem : class
{
using (var context = CreateContext())
{
TestHelpers.AssertResults(
new[] { await query(NorthwindData.Set<TItem>()) },
new[] { await query(context.Set<TItem>()) },
assertOrder);
}
}

private async Task AssertQuery<TItem>(
Func<IQueryable<TItem>, Task<bool>> query,
bool assertOrder = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6767,6 +6767,34 @@ from e2 in ClientDefaultIfEmpty(grouping)
select new { City1 = e1.City, City2 = e2 != null ? e2.City : null });
}

[ConditionalFact]
public virtual void Skip_Count()
{
AssertQuery<Customer>(
cs => cs.Skip(7).Count());
}

[ConditionalFact]
public virtual void Skip_LongCount()
{
AssertQuery<Customer>(
cs => cs.Skip(7).LongCount());
}

[ConditionalFact]
public virtual void OrderBy_Skip_Count()
{
AssertQuery<Customer>(
cs => cs.OrderBy(c => c.Country).Skip(7).Count());
}

[ConditionalFact]
public virtual void OrderBy_Skip_LongCount()
{
AssertQuery<Customer>(
cs => cs.OrderBy(c => c.Country).Skip(7).LongCount());
}

private static IEnumerable<TElement> ClientDefaultIfEmpty<TElement>(IEnumerable<TElement> source)
{
return source?.Count() == 0 ? new[] { default(TElement) } : source;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6827,6 +6827,74 @@ FROM [Employees] AS [e1]
Sql);
}

public override void Skip_Count()
{
base.Skip_Count();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT(*)
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS
) AS [t]",
Sql);
}

public override void Skip_LongCount()
{
base.Skip_LongCount();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT_BIG(*)
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS
) AS [t]",
Sql);
}

public override void OrderBy_Skip_Count()
{
base.OrderBy_Skip_Count();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT(*)
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
ORDER BY [c].[Country]
OFFSET @__p_0 ROWS
) AS [t]",
Sql);
}

public override void OrderBy_Skip_LongCount()
{
base.OrderBy_Skip_LongCount();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT_BIG(*)
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
ORDER BY [c].[Country]
OFFSET @__p_0 ROWS
) AS [t]",
Sql);
}

private const string FileLineEnding = @"
";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,82 @@ THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
Sql);
}

public override void Skip_Count()
{
base.Skip_Count();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT(*)
FROM (
SELECT [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ROW_NUMBER() OVER(ORDER BY @@RowCount) AS [__RowNumber__]
FROM [Customers] AS [c]
) AS [t0]
WHERE [t0].[__RowNumber__] > @__p_0
) AS [t]",
Sql);
}

public override void Skip_LongCount()
{
base.Skip_LongCount();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT_BIG(*)
FROM (
SELECT [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ROW_NUMBER() OVER(ORDER BY @@RowCount) AS [__RowNumber__]
FROM [Customers] AS [c]
) AS [t0]
WHERE [t0].[__RowNumber__] > @__p_0
) AS [t]",
Sql);
}

public override void OrderBy_Skip_Count()
{
base.OrderBy_Skip_Count();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT(*)
FROM (
SELECT [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ROW_NUMBER() OVER(ORDER BY [c].[Country]) AS [__RowNumber__]
FROM [Customers] AS [c]
) AS [t0]
WHERE [t0].[__RowNumber__] > @__p_0
) AS [t]",
Sql);
}

public override void OrderBy_Skip_LongCount()
{
base.OrderBy_Skip_LongCount();

Assert.Equal(
@"@__p_0: 7
SELECT COUNT_BIG(*)
FROM (
SELECT [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
FROM (
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ROW_NUMBER() OVER(ORDER BY [c].[Country]) AS [__RowNumber__]
FROM [Customers] AS [c]
) AS [t0]
WHERE [t0].[__RowNumber__] > @__p_0
) AS [t]",
Sql);
}

private const string FileLineEnding = @"
";

Expand Down

0 comments on commit 3960a54

Please sign in to comment.