Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

1270 lines
57 KiB
C#

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity.Query
{
using System.Collections.Generic;
using System.Data.Entity.Core.Common.CommandTrees;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Data.Entity.Core.Metadata.Edm;
using System.Linq;
using Xunit;
public class GroupAggregateTests : FunctionalTestBase
{
private static readonly MetadataWorkspace workspace = QueryTestHelpers.CreateMetadataWorkspace(
ProductModel.csdl, ProductModel.ssdl, ProductModel.msl);
private DbGroupExpressionBinding CreateBasicGroupBinding()
{
var entitySet = workspace.GetEntityContainer("ProductContainer", DataSpace.CSpace).GetEntitySetByName("Products", false);
var scan = entitySet.Scan();
return scan.GroupBindAs("input", "group");
}
[Fact]
public void Basic_GroupBy_with_group_key_and_group_aggregate()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable.Property("ReorderLevel"))
};
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project2].[C1] AS [C1],
[Project2].[ReorderLevel] AS [ReorderLevel],
[Project2].[C2] AS [C2],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[Distinct1].[ReorderLevel] AS [ReorderLevel],
1 AS [C1],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM (SELECT DISTINCT
[Extent1].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [Distinct1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([Distinct1].[ReorderLevel] = [Extent2].[ReorderLevel]) OR (([Distinct1].[ReorderLevel] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project2]
ORDER BY [Project2].[ReorderLevel] ASC, [Project2].[C2] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_with_function_aggregate_and_group_aggregate_being_first()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>();
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate),
new KeyValuePair<string, DbAggregate>(
"max", maxFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project2].[C2] AS [C1],
[Project2].[C1] AS [C2],
[Project2].[C3] AS [C3],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel] AS [ReorderLevel]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
1 AS [C2],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[C1] AS [C3]
FROM (SELECT
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [GroupBy1]
LEFT OUTER JOIN (SELECT
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel],
[Extent2].[Discontinued] AS [Discontinued],
1 AS [C1]
FROM [dbo].[Products] AS [Extent2]
WHERE [Extent2].[Discontinued] IN (0,1) ) AS [Project1] ON 1 = 1
) AS [Project2]
ORDER BY [Project2].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_with_function_aggregate_and_group_aggregate_being_second()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>();
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>(
"max", maxFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate),
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project2].[C2] AS [C1],
[Project2].[C1] AS [C2],
[Project2].[C3] AS [C3],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel] AS [ReorderLevel]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
1 AS [C2],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[C1] AS [C3]
FROM (SELECT
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [GroupBy1]
LEFT OUTER JOIN (SELECT
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel],
[Extent2].[Discontinued] AS [Discontinued],
1 AS [C1]
FROM [dbo].[Products] AS [Extent2]
WHERE [Extent2].[Discontinued] IN (0,1) ) AS [Project1] ON 1 = 1
) AS [Project2]
ORDER BY [Project2].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_with_two_function_aggregates_and_group_aggregate_being_in_the_middle()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>();
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var minFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Min" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>(
"max", maxFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate),
new KeyValuePair<string, DbAggregate>(
"min", minFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project2].[C3] AS [C1],
[Project2].[C1] AS [C2],
[Project2].[C2] AS [C3],
[Project2].[C4] AS [C4],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel] AS [ReorderLevel]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[A2] AS [C2],
1 AS [C3],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[C1] AS [C4]
FROM (SELECT
MAX([Extent1].[ProductID]) AS [A1],
MIN([Extent1].[ProductID]) AS [A2]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [GroupBy1]
LEFT OUTER JOIN (SELECT
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel],
[Extent2].[Discontinued] AS [Discontinued],
1 AS [C1]
FROM [dbo].[Products] AS [Extent2]
WHERE [Extent2].[Discontinued] IN (0,1) ) AS [Project1] ON 1 = 1
) AS [Project2]
ORDER BY [Project2].[C4] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_with_just_group_aggregate()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project2].[C1] AS [C1],
[Project2].[C2] AS [C2],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel] AS [ReorderLevel]
FROM ( SELECT
1 AS [C1],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[C1] AS [C2]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[ReorderLevel] AS [ReorderLevel],
[Extent1].[Discontinued] AS [Discontinued],
1 AS [C1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [Project1] ON 1 = 1
) AS [Project2]
ORDER BY [Project2].[C2] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
private DbGroupByExpression CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable.Property("ReorderLevel"))
};
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>(
"max", maxFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
return groupBinding.GroupBy(keys, aggregates);
}
[Fact]
public void GropuBy_with_group_key_function_aggregate_and_group_aggregate()
{
var query = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var expectedSql =
@"
SELECT
[Project1].[C2] AS [C1],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C2],
[Project1].[C3] AS [C3],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
1 AS [C2],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
FROM (SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel] ) AS [GroupBy1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project1]
ORDER BY [Project1].[ReorderLevel] ASC, [Project1].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Project_over_group_by_with_group_key_function_aggregate_and_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>("max", groupByBinding.Variable.Property("max")),
new KeyValuePair<string, DbExpression>(
"groupPartition", groupByBinding.Variable.Property("groupPartition")),
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
[Project1].[C2] AS [C1],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C2],
[Project1].[C3] AS [C3],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
1 AS [C2],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
FROM (SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel] ) AS [GroupBy1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project1]
ORDER BY [Project1].[ReorderLevel] ASC, [Project1].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Project_over_group_by_skip_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>("max", groupByBinding.Variable.Property("max")),
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Project_over_group_by_only_project_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>(
"groupPartition", groupByBinding.Variable.Property("groupPartition")),
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
[Project2].[ReorderLevel] AS [ReorderLevel],
[Project2].[C1] AS [C1],
[Project2].[C2] AS [C2],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[Distinct1].[ReorderLevel] AS [ReorderLevel],
1 AS [C1],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
FROM (SELECT DISTINCT
[Extent1].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [Distinct1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([Distinct1].[ReorderLevel] = [Extent2].[ReorderLevel]) OR (([Distinct1].[ReorderLevel] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project2]
ORDER BY [Project2].[ReorderLevel] ASC, [Project2].[C2] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_over_GroupBy()
{
var innerGroupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var outerGroupBinding = innerGroupBy.GroupBindAs("input2", "group2");
var outerKeys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey2", outerGroupBinding.Variable.Property("max"))
};
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var outerAggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition2", outerGroupBinding.GroupAggregate),
new KeyValuePair<string, DbAggregate>(
"max2", maxFunction.Aggregate(outerGroupBinding.GroupVariable.Property("groupKey"))),
};
var query = outerGroupBinding.GroupBy(outerKeys, outerAggregates);
var expectedSql =
@"SELECT
[Project2].[C3] AS [C1],
[Project2].[C1] AS [C2],
[Project2].[C2] AS [C3],
[Project2].[C6] AS [C4],
[Project2].[ReorderLevel] AS [ReorderLevel],
[Project2].[C4] AS [C5],
[Project2].[C5] AS [C6],
[Project2].[Discontinued] AS [Discontinued],
[Project2].[ProductID] AS [ProductID],
[Project2].[ProductName] AS [ProductName],
[Project2].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[GroupBy2].[K1] AS [C1],
[GroupBy2].[A1] AS [C2],
1 AS [C3],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C4],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel1] AS [ReorderLevel1],
[Project1].[Discontinued] AS [Discontinued],
CASE WHEN ([Project1].[C2] IS NULL) THEN CAST(NULL AS int) WHEN ([Project1].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C5],
[Project1].[C2] AS [C6]
FROM (SELECT
[GroupBy1].[A1] AS [K1],
MAX([GroupBy1].[K1]) AS [A1]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]
GROUP BY [GroupBy1].[A1] ) AS [GroupBy2]
LEFT OUTER JOIN (SELECT
[GroupBy3].[K1] AS [ReorderLevel],
[GroupBy3].[A1] AS [C1],
[Extent3].[ProductID] AS [ProductID],
[Extent3].[ProductName] AS [ProductName],
[Extent3].[ReorderLevel] AS [ReorderLevel1],
[Extent3].[Discontinued] AS [Discontinued],
1 AS [C2]
FROM (SELECT
[Extent2].[ReorderLevel] AS [K1],
MAX([Extent2].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent2]
WHERE [Extent2].[Discontinued] IN (0,1)
GROUP BY [Extent2].[ReorderLevel] ) AS [GroupBy3]
LEFT OUTER JOIN [dbo].[Products] AS [Extent3] ON ([Extent3].[Discontinued] IN (0,1)) AND (([GroupBy3].[K1] = [Extent3].[ReorderLevel]) OR (([GroupBy3].[K1] IS NULL) AND ([Extent3].[ReorderLevel] IS NULL))) ) AS [Project1] ON ([GroupBy2].[K1] = [Project1].[C1]) OR (([GroupBy2].[K1] IS NULL) AND ([Project1].[C1] IS NULL))
) AS [Project2]
ORDER BY [Project2].[C1] ASC, [Project2].[C6] ASC, [Project2].[ReorderLevel] ASC, [Project2].[C5] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_over_union()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable.Property("ReorderLevel"))
};
var maxFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Max" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate),
new KeyValuePair<string, DbAggregate>(
"max", maxFunction.Aggregate(groupBinding.GroupVariable.Property("ProductID"))),
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project1].[C2] AS [C1],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C2],
[Project1].[C3] AS [C3],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
1 AS [C2],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
FROM (SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel] ) AS [GroupBy1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project1]
ORDER BY [Project1].[ReorderLevel] ASC, [Project1].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_with_nulls()
{
DbExpression one = DbExpressionBuilder.Constant(1);
DbExpression intNull = one.ResultType.Null();
var input = DbExpressionBuilder.NewCollection(new[] { 1, 2, 3, intNull, intNull, 2, 1, intNull });
var groupBinding = input.GroupBindAs("input", "group");
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable)
};
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project30].[C2] AS [C1],
[Project30].[C1] AS [C2],
[Project30].[C4] AS [C3],
[Project30].[C3] AS [C4]
FROM ( SELECT
[Distinct1].[C1] AS [C1],
1 AS [C2],
CASE WHEN ([UnionAll14].[C1] IS NULL) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 0) THEN cast(1 as tinyint) WHEN ([UnionAll14].[C1] = 1) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 2) THEN cast(3 as tinyint) WHEN ([UnionAll14].[C1] = 3) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 4) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 5) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 6) THEN cast(1 as tinyint) END AS [C3],
CASE WHEN ([UnionAll14].[C1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C4]
FROM (SELECT DISTINCT
CASE WHEN ([UnionAll7].[C1] = 0) THEN cast(1 as tinyint) WHEN ([UnionAll7].[C1] = 1) THEN cast(2 as tinyint) WHEN ([UnionAll7].[C1] = 2) THEN cast(3 as tinyint) WHEN ([UnionAll7].[C1] = 3) THEN CAST(NULL AS int) WHEN ([UnionAll7].[C1] = 4) THEN CAST(NULL AS int) WHEN ([UnionAll7].[C1] = 5) THEN cast(2 as tinyint) WHEN ([UnionAll7].[C1] = 6) THEN cast(1 as tinyint) END AS [C1]
FROM (SELECT
[UnionAll6].[C1] AS [C1]
FROM (SELECT
[UnionAll5].[C1] AS [C1]
FROM (SELECT
[UnionAll4].[C1] AS [C1]
FROM (SELECT
[UnionAll3].[C1] AS [C1]
FROM (SELECT
[UnionAll2].[C1] AS [C1]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
UNION ALL
SELECT
4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll4]
UNION ALL
SELECT
5 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable6]) AS [UnionAll5]
UNION ALL
SELECT
6 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable7]) AS [UnionAll6]
UNION ALL
SELECT
7 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable8]) AS [UnionAll7] ) AS [Distinct1]
LEFT OUTER JOIN (SELECT
[UnionAll13].[C1] AS [C1]
FROM (SELECT
[UnionAll12].[C1] AS [C1]
FROM (SELECT
[UnionAll11].[C1] AS [C1]
FROM (SELECT
[UnionAll10].[C1] AS [C1]
FROM (SELECT
[UnionAll9].[C1] AS [C1]
FROM (SELECT
[UnionAll8].[C1] AS [C1]
FROM (SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable9]
UNION ALL
SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable10]) AS [UnionAll8]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable11]) AS [UnionAll9]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable12]) AS [UnionAll10]
UNION ALL
SELECT
4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable13]) AS [UnionAll11]
UNION ALL
SELECT
5 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable14]) AS [UnionAll12]
UNION ALL
SELECT
6 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable15]) AS [UnionAll13]
UNION ALL
SELECT
7 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable16]) AS [UnionAll14] ON ([Distinct1].[C1] = (CASE WHEN ([UnionAll14].[C1] = 0) THEN cast(1 as tinyint) WHEN ([UnionAll14].[C1] = 1) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 2) THEN cast(3 as tinyint) WHEN ([UnionAll14].[C1] = 3) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 4) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 5) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 6) THEN cast(1 as tinyint) END)) OR (([Distinct1].[C1] IS NULL) AND (CASE WHEN ([UnionAll14].[C1] = 0) THEN cast(1 as tinyint) WHEN ([UnionAll14].[C1] = 1) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 2) THEN cast(3 as tinyint) WHEN ([UnionAll14].[C1] = 3) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 4) THEN CAST(NULL AS int) WHEN ([UnionAll14].[C1] = 5) THEN cast(2 as tinyint) WHEN ([UnionAll14].[C1] = 6) THEN cast(1 as tinyint) END IS NULL))
) AS [Project30]
ORDER BY [Project30].[C1] ASC, [Project30].[C4] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_on_entity()
{
var groupBinding = CreateBasicGroupBinding();
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable)
};
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project1].[ProductID] AS [ProductID],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C1],
[Project1].[Discontinued1] AS [Discontinued1],
[Project1].[ProductID1] AS [ProductID1],
[Project1].[ProductName1] AS [ProductName1],
[Project1].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName],
[Extent1].[ReorderLevel] AS [ReorderLevel],
[Extent1].[Discontinued] AS [Discontinued],
[Extent2].[ProductID] AS [ProductID1],
[Extent2].[ProductName] AS [ProductName1],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued1],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM [dbo].[Products] AS [Extent1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([Extent1].[ProductID] = [Extent2].[ProductID]) OR (([Extent1].[Discontinued] IS NULL) AND ([Extent2].[Discontinued] IS NULL)))
WHERE [Extent1].[Discontinued] IN (0,1)
) AS [Project1]
ORDER BY [Project1].[Discontinued] ASC, [Project1].[ProductID] ASC, [Project1].[ProductName] ASC, [Project1].[ReorderLevel] ASC, [Project1].[C1] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void GroupBy_row()
{
DbExpression one = DbExpressionBuilder.Constant(1);
DbExpression intNull = one.ResultType.Null();
var rows = new DbExpression[3]
{
DbExpressionBuilder.NewRow(
new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("x", one),
new KeyValuePair<string, DbExpression>("y", one),
}),
DbExpressionBuilder.NewRow(
new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("x", one),
new KeyValuePair<string, DbExpression>("y", intNull),
}),
DbExpressionBuilder.NewRow(
new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("x", intNull),
new KeyValuePair<string, DbExpression>("y", intNull),
}),
};
var input = DbExpressionBuilder.NewCollection(rows);
var groupBinding = input.GroupBindAs("input", "group");
var keys = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupBinding.Variable)
};
var aggregates = new List<KeyValuePair<string, DbAggregate>>
{
new KeyValuePair<string, DbAggregate>("groupPartition", groupBinding.GroupAggregate)
};
var query = groupBinding.GroupBy(keys, aggregates);
var expectedSql =
@"SELECT
[Project10].[C1] AS [C1],
[Project10].[C2] AS [C2],
[Project10].[C3] AS [C3],
[Project10].[C7] AS [C4],
[Project10].[C4] AS [C5],
[Project10].[C5] AS [C6],
[Project10].[C6] AS [C7]
FROM ( SELECT
[Distinct1].[C1] AS [C1],
[Distinct1].[C2] AS [C2],
[Distinct1].[C3] AS [C3],
[UnionAll4].[C1] AS [C4],
CASE WHEN ([UnionAll4].[C1] IS NULL) THEN CAST(NULL AS int) WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN 1 END AS [C5],
CASE WHEN ([UnionAll4].[C1] IS NULL) THEN CAST(NULL AS int) WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN CAST(NULL AS int) END AS [C6],
CASE WHEN ([UnionAll4].[C1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C7]
FROM (SELECT DISTINCT
1 AS [C1],
CASE WHEN ([UnionAll2].[C1] = 0) THEN 1 WHEN ([UnionAll2].[C1] = 1) THEN 1 END AS [C2],
CASE WHEN ([UnionAll2].[C1] = 0) THEN 1 WHEN ([UnionAll2].[C1] = 1) THEN CAST(NULL AS int) END AS [C3]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2] ) AS [Distinct1]
LEFT OUTER JOIN (SELECT
[UnionAll3].[C1] AS [C1]
FROM (SELECT
0 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]
UNION ALL
SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll3]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable6]) AS [UnionAll4] ON (([Distinct1].[C2] = (CASE WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN 1 END)) OR (([Distinct1].[C2] IS NULL) AND (CASE WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN 1 END IS NULL))) AND (([Distinct1].[C3] = (CASE WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN CAST(NULL AS int) END)) OR (([Distinct1].[C3] IS NULL) AND (CASE WHEN ([UnionAll4].[C1] = 0) THEN 1 WHEN ([UnionAll4].[C1] = 1) THEN CAST(NULL AS int) END IS NULL)))
) AS [Project10]
ORDER BY [Project10].[C1] ASC, [Project10].[C2] ASC, [Project10].[C3] ASC, [Project10].[C7] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_Group_aggregate_with_group_key_and_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>(
"groupPartition", groupByBinding.Variable.Property("groupPartition")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
groupByBinding.Variable.Property("groupPartition").Select(p => p.Property("ProductID"))))
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
[Project1].[C2] AS [C1],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C2],
[Project1].[C3] AS [C3],
[Project1].[Discontinued] AS [Discontinued],
[Project1].[ProductID] AS [ProductID],
[Project1].[ProductName] AS [ProductName],
[Project1].[ReorderLevel1] AS [ReorderLevel1]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
1 AS [C2],
[Extent2].[ProductID] AS [ProductID],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[ReorderLevel] AS [ReorderLevel1],
[Extent2].[Discontinued] AS [Discontinued],
CASE WHEN ([Extent2].[ProductID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C3]
FROM (SELECT
[Extent1].[ReorderLevel] AS [K1],
COUNT([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel] ) AS [GroupBy1]
LEFT OUTER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [Project1]
ORDER BY [Project1].[ReorderLevel] ASC, [Project1].[C3] ASC";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_Group_aggregate_with_group_key_and_no_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
groupByBinding.Variable.Property("groupPartition").Select(p => p.Property("ProductID"))))
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
COUNT([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_filter_over_group_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByBinding = groupBy.BindAs("groupBy");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
groupByBinding.Variable.Property("groupPartition").Where(
f => f.Property("ProductID").LessThan(3)).Select(p => p.Property("ProductID")))),
};
var query = groupByBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[Project2].[ReorderLevel] AS [ReorderLevel],
[Project2].[C1] AS [C2]
FROM ( SELECT
[Distinct1].[ReorderLevel] AS [ReorderLevel],
(SELECT
COUNT([Extent2].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent2]
WHERE ([Extent2].[Discontinued] IN (0,1)) AND (([Distinct1].[ReorderLevel] = [Extent2].[ReorderLevel]) OR (([Distinct1].[ReorderLevel] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL))) AND ([Extent2].[ProductID] < cast(3 as tinyint))) AS [C1]
FROM ( SELECT DISTINCT
[Extent1].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
) AS [Distinct1]
) AS [Project2]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_project_filtered_group_aggregate_also_include_group_key_and_function_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var filteredGroupAggregateProjection = groupBy.Select(
p => new
{
groupKey = p.Property("groupKey"),
max = p.Property("max"),
groupPartition = p.Property("groupPartition").Where(g => g.Property("ProductID").LessThan(3)),
});
var filteredGroupAggregateProjectionBinding = filteredGroupAggregateProjection.BindAs("groupBy");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>(
"groupKey", filteredGroupAggregateProjectionBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>(
"max", filteredGroupAggregateProjectionBinding.Variable.Property("max")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
filteredGroupAggregateProjectionBinding.Variable.Property("groupPartition").Select(
p => p.Property("ProductID")))),
};
var query = filteredGroupAggregateProjectionBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[Project1].[ReorderLevel] AS [ReorderLevel],
[Project1].[C1] AS [C2],
[Project1].[C2] AS [C3]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
(SELECT
COUNT([Extent2].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent2]
WHERE ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL))) AND ([Extent2].[ProductID] < cast(3 as tinyint))) AS [C2]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]
) AS [Project1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_project_unioned_group_aggregate_also_include_group_key_and_function_aggregate()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var unionedGroupAggregateProjection = groupBy.Select(
p => new
{
groupKey = p.Property("groupKey"),
max = p.Property("max"),
groupPartition = p.Property("groupPartition").UnionAll(p.Property("groupPartition")),
});
var unionedGroupAggregateProjectionBinding = unionedGroupAggregateProjection.BindAs("groupBy");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>(
"groupKey", unionedGroupAggregateProjectionBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>(
"max", unionedGroupAggregateProjectionBinding.Variable.Property("max")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
unionedGroupAggregateProjectionBinding.Variable.Property("groupPartition").Select(
p => p.Property("ProductID")))),
};
var query = unionedGroupAggregateProjectionBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[Project3].[ReorderLevel] AS [ReorderLevel],
[Project3].[C1] AS [C2],
[Project3].[C2] AS [C3]
FROM ( SELECT
[GroupBy1].[A1] AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
(SELECT
COUNT([UnionAll1].[ProductID]) AS [A1]
FROM (SELECT
[Extent2].[ProductID] AS [ProductID]
FROM [dbo].[Products] AS [Extent2]
WHERE ([Extent2].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent2].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
UNION ALL
SELECT
[Extent3].[ProductID] AS [ProductID]
FROM [dbo].[Products] AS [Extent3]
WHERE ([Extent3].[Discontinued] IN (0,1)) AND (([GroupBy1].[K1] = [Extent3].[ReorderLevel]) OR (([GroupBy1].[K1] IS NULL) AND ([Extent3].[ReorderLevel] IS NULL)))) AS [UnionAll1]) AS [C2]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]
) AS [Project3]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_group_aggregate_propagated_through_Apply()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var query = groupBy.OuterApply(c => new KeyValuePair<string, DbExpression>("applyColumn", groupBy)).
Select(a => countFunction.Invoke(a.Property("c").Property("groupPartition").Select(p => p.Property("ProductID"))));
var expectedSql =
@"SELECT
(SELECT
COUNT([Extent3].[ProductID]) AS [A1]
FROM [dbo].[Products] AS [Extent3]
WHERE ([Extent3].[Discontinued] IN (0,1)) AND (([Distinct1].[ReorderLevel] = [Extent3].[ReorderLevel]) OR (([Distinct1].[ReorderLevel] IS NULL) AND ([Extent3].[ReorderLevel] IS NULL)))) AS [C1]
FROM (SELECT DISTINCT
[Extent1].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1) ) AS [Distinct1]
LEFT OUTER JOIN (SELECT DISTINCT
[Extent2].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent2]
WHERE [Extent2].[Discontinued] IN (0,1) ) AS [Distinct2] ON 1 = 1";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_group_aggregate_propagated_throgh_Element()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var query = countFunction.Invoke(groupBy.Element().Property("groupPartition").Select(p => p.Property("ProductID")));
var expectedSql =
@"SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT([Extent2].[ProductID]) AS [A1]
FROM (SELECT TOP (1)
[Distinct1].[ReorderLevel] AS [ReorderLevel]
FROM ( SELECT DISTINCT
[Extent1].[ReorderLevel] AS [ReorderLevel]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
) AS [Distinct1] ) AS [Element1]
INNER JOIN [dbo].[Products] AS [Extent2] ON ([Extent2].[Discontinued] IN (0,1)) AND (([Element1].[ReorderLevel] = [Extent2].[ReorderLevel]) OR (([Element1].[ReorderLevel] IS NULL) AND ([Extent2].[ReorderLevel] IS NULL)))
) AS [GroupBy1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_group_aggregate_propagated_through_Limit()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByLimit = groupBy.Limit(2);
var groupByLimitBinding = groupByLimit.BindAs("groupByLimit");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByLimitBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>("max", groupByLimitBinding.Variable.Property("max")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
groupByLimitBinding.Variable.Property("groupPartition").Select(p => p.Property("ProductID")))),
};
var query = groupByLimitBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[Limit1].[K1] AS [ReorderLevel],
[Limit1].[A1] AS [C2],
[Limit1].[A2] AS [C3]
FROM ( SELECT TOP (2)
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1],
COUNT([Extent1].[ProductID]) AS [A2]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ReorderLevel]
) AS [Limit1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Count_over_group_aggregate_propagated_through_Filter()
{
var groupBy = CreateGroupByWithGroupKeyFunctionAggregateAndGroupAggregate();
var groupByFilter = groupBy.Where(c => c.Property("groupKey").LessThan(3));
var groupByFilterBinding = groupByFilter.BindAs("groupByLimit");
var countFunction =
workspace.GetItems<EdmFunction>(DataSpace.CSpace).Where(
a => a.Name == "Count" && a.Parameters[0].TypeUsage.EdmType.Name.Contains("Int32")).First();
var projections = new List<KeyValuePair<string, DbExpression>>
{
new KeyValuePair<string, DbExpression>("groupKey", groupByFilterBinding.Variable.Property("groupKey")),
new KeyValuePair<string, DbExpression>("max", groupByFilterBinding.Variable.Property("max")),
new KeyValuePair<string, DbExpression>(
"count",
countFunction.Invoke(
groupByFilterBinding.Variable.Property("groupPartition").Select(p => p.Property("ProductID")))),
};
var query = groupByFilterBinding.Project(DbExpressionBuilder.NewRow(projections));
var expectedSql =
@"SELECT
1 AS [C1],
[GroupBy1].[K1] AS [ReorderLevel],
[GroupBy1].[A1] AS [C2],
[GroupBy1].[A2] AS [C3]
FROM ( SELECT
[Extent1].[ReorderLevel] AS [K1],
MAX([Extent1].[ProductID]) AS [A1],
COUNT([Extent1].[ProductID]) AS [A2]
FROM [dbo].[Products] AS [Extent1]
WHERE ([Extent1].[Discontinued] IN (0,1)) AND ([Extent1].[ReorderLevel] < cast(3 as tinyint))
GROUP BY [Extent1].[ReorderLevel]
) AS [GroupBy1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
[Fact]
public void Using_model_defined_aggregate_function()
{
var query =
@"select gkey, ProductModel.F_CountProducts(GroupPartition(P))
FROM ProductContainer.Products as P
Group By P.ProductName as gkey";
var expectedSql =
@"SELECT
1 AS [C1],
[GroupBy1].[K1] AS [ProductName],
[GroupBy1].[A1] AS [C2]
FROM ( SELECT
[Extent1].[ProductName] AS [K1],
COUNT(1) AS [A1]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[Discontinued] IN (0,1)
GROUP BY [Extent1].[ProductName]
) AS [GroupBy1]";
QueryTestHelpers.VerifyQuery(query, workspace, expectedSql);
}
}
}