From: <pa...@us...> - 2011-01-16 20:55:20
|
Revision: 5354 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5354&view=rev Author: patearl Date: 2011-01-16 20:55:13 +0000 (Sun, 16 Jan 2011) Log Message: ----------- Linq: Fixed group by on multiple keys. Added more group by tests. Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessGroupBy.cs trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2362/Fixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2011-01-16 20:48:51 UTC (rev 5353) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2011-01-16 20:55:13 UTC (rev 5354) @@ -321,9 +321,9 @@ return new HqlDirectionDescending(_factory); } - public HqlGroupBy GroupBy(HqlExpression expression) + public HqlGroupBy GroupBy(params HqlExpression[] expressions) { - return new HqlGroupBy(_factory, expression); + return new HqlGroupBy(_factory, expressions); } public HqlAll All() Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2011-01-16 20:48:51 UTC (rev 5353) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2011-01-16 20:55:13 UTC (rev 5354) @@ -786,7 +786,7 @@ public class HqlGroupBy : HqlStatement { - public HqlGroupBy(IASTFactory factory, HqlExpression expression) : base(HqlSqlWalker.GROUP, "group by", factory, expression) + public HqlGroupBy(IASTFactory factory, params HqlExpression[] expressions) : base(HqlSqlWalker.GROUP, "group by", factory, expressions) { } } Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessGroupBy.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessGroupBy.cs 2011-01-16 20:48:51 UTC (rev 5353) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessGroupBy.cs 2011-01-16 20:55:13 UTC (rev 5354) @@ -1,5 +1,8 @@ -using NHibernate.Hql.Ast; +using System.Collections.Generic; +using System.Linq.Expressions; +using NHibernate.Hql.Ast; using Remotion.Data.Linq.Clauses.ResultOperators; +using System.Linq; namespace NHibernate.Linq.Visitors.ResultOperatorProcessors { @@ -7,9 +10,15 @@ { public void Process(GroupResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) { - tree.AddGroupByClause(tree.TreeBuilder.GroupBy( - HqlGeneratorExpressionTreeVisitor.Visit(resultOperator.KeySelector, queryModelVisitor.VisitorParameters) - .AsExpression())); + IEnumerable<Expression> groupByKeys; + if (resultOperator.KeySelector is NewExpression) + groupByKeys = (resultOperator.KeySelector as NewExpression).Arguments; + else + groupByKeys = new[] {resultOperator.KeySelector}; + + IEnumerable<HqlExpression> hqlGroupByKeys = groupByKeys.Select(k => HqlGeneratorExpressionTreeVisitor.Visit(k, queryModelVisitor.VisitorParameters).AsExpression()); + + tree.AddGroupByClause(tree.TreeBuilder.GroupBy(hqlGroupByKeys.ToArray())); } } } \ No newline at end of file Added: trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/Linq/ByMethod/GroupByTests.cs 2011-01-16 20:55:13 UTC (rev 5354) @@ -0,0 +1,120 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NHibernate.DomainModel.Northwind.Entities; +using NUnit.Framework; + +namespace NHibernate.Test.Linq.ByMethod +{ + [TestFixture] + public class GroupByTests : LinqTestCase + { + [Test] + public void SingleKeyGroupAndCount() + { + var orderCounts = db.Orders.GroupBy(o => o.Customer).Select(g => g.Count()).ToList(); + Assert.AreEqual(89, orderCounts.Count); + Assert.AreEqual(830, orderCounts.Sum()); + } + + [Test] + public void MultipleKeyGroupAndCount() + { + var orderCounts = db.Orders.GroupBy(o => new {o.Customer, o.Employee}).Select(g => g.Count()).ToList(); + Assert.AreEqual(464, orderCounts.Count); + Assert.AreEqual(830, orderCounts.Sum()); + } + + [Test] + [Ignore("Not working yet.")] + public void SingleKeyGrouping() + { + var orders = db.Orders.GroupBy(o => o.Customer).ToList(); + Assert.That(orders.Count, Is.EqualTo(830)); + CheckGrouping(orders, o => o.Customer); + } + + [Test] + [Ignore("Not working yet.")] + public void MultipleKeyGrouping() + { + var orders = db.Orders.GroupBy(o => new { o.Customer, o.Employee }).ToList(); + Assert.That(orders.Count, Is.EqualTo(830)); + + CheckGrouping( + orders.Select(g => new TupGrouping<Customer, Employee, Order>(g.Key.Customer, g.Key.Employee, g)), + o => o.Customer, + o => o.Employee); + } + + private void CheckGrouping<TKey, TElement>(IEnumerable<IGrouping<TKey, TElement>> groupedItems, Func<TElement, TKey> groupBy) + { + HashSet<object> used = new HashSet<object>(); + foreach (IGrouping<TKey, TElement> group in groupedItems) + { + Assert.IsFalse(used.Contains(group.Key)); + used.Add(group.Key); + + foreach (var item in group) + { + Assert.AreEqual(group.Key, groupBy(item)); + } + } + } + + private void CheckGrouping<TKey1, TKey2, TElement>(IEnumerable<TupGrouping<TKey1, TKey2, TElement>> groupedItems, Func<TElement, TKey1> groupBy1, Func<TElement, TKey2> groupBy2) + { + HashSet<object> used = new HashSet<object>(); + foreach (IGrouping<Tup<TKey1, TKey2>, TElement> group in groupedItems) + { + Assert.IsFalse(used.Contains(group.Key.Item1)); + used.Add(group.Key.Item1); + Assert.IsFalse(used.Contains(group.Key.Item2)); + used.Add(group.Key.Item2); + + foreach (var item in group) + { + Assert.AreEqual(group.Key.Item1, groupBy1(item)); + Assert.AreEqual(group.Key.Item2, groupBy2(item)); + } + } + } + + private class TupGrouping<TKey1, TKey2, TElement> : IGrouping<Tup<TKey1, TKey2>, TElement> + { + private IEnumerable<TElement> Elements { get; set; } + + public TupGrouping(TKey1 key1, TKey2 key2, IEnumerable<TElement> elements) + { + Key = new Tup<TKey1, TKey2>(key1, key2); + Elements = elements; + } + + public IEnumerator<TElement> GetEnumerator() + { + return Elements.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public Tup<TKey1, TKey2> Key { get; private set; } + } + + private class Tup<T1, T2> + { + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + + public Tup(T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + } + } +} Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2362/Fixture.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2362/Fixture.cs 2011-01-16 20:48:51 UTC (rev 5353) +++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2362/Fixture.cs 2011-01-16 20:55:13 UTC (rev 5354) @@ -4,10 +4,10 @@ namespace NHibernate.Test.NHSpecificTest.NH2362 { - [Ignore("Not fixed yet.")] public class Fixture : BugTestCase { [Test] + [Ignore("Not working yet.")] public void CanParseMultipleGroupByAndSelect() { using (var session = OpenSession()) Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-16 20:48:51 UTC (rev 5353) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-01-16 20:55:13 UTC (rev 5354) @@ -427,6 +427,7 @@ <Compile Include="Linq\BinaryBooleanExpressionTests.cs" /> <Compile Include="Linq\BinaryExpressionOrdererTests.cs" /> <Compile Include="Linq\BooleanMethodExtensionExample.cs" /> + <Compile Include="Linq\ByMethod\GroupByTests.cs" /> <Compile Include="Linq\CasingTest.cs" /> <Compile Include="Linq\CollectionAssert.cs" /> <Compile Include="Linq\CustomExtensionsExample.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |