From: <ste...@us...> - 2010-04-07 10:48:48
|
Revision: 4970 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4970&view=rev Author: steverstrong Date: 2010-04-07 10:48:41 +0000 (Wed, 07 Apr 2010) Log Message: ----------- Added support for OfType() and "is" in Linq queries Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/Linq/PagingTests.cs trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs Added Paths: ----------- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessOfType.cs Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeBuilder.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -405,5 +405,10 @@ { return new HqlLeftFetchJoin(_factory, expression, @alias); } + + public HqlClass Class() + { + return new HqlClass(_factory); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate/Hql/Ast/HqlTreeNode.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -697,6 +697,14 @@ } } + public class HqlClass : HqlExpression + { + public HqlClass(IASTFactory factory) + : base(HqlSqlWalker.CLASS, "class", factory) + { + } + } + public class HqlLeft : HqlTreeNode { public HqlLeft(IASTFactory factory) Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/HqlGeneratorExpressionTreeVisitor.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -102,8 +102,8 @@ // return VisitListInitExpression((ListInitExpression)expression); case ExpressionType.Parameter: return VisitParameterExpression((ParameterExpression)expression); - //case ExpressionType.TypeIs: - // return VisitTypeBinaryExpression((TypeBinaryExpression)expression); + case ExpressionType.TypeIs: + return VisitTypeBinaryExpression((TypeBinaryExpression)expression); default: if (expression is SubQueryExpression) @@ -136,6 +136,15 @@ } } + private HqlTreeNode VisitTypeBinaryExpression(TypeBinaryExpression expression) + { + return _hqlTreeBuilder.Equality( + _hqlTreeBuilder.Dot( + Visit(expression.Expression).AsExpression(), + _hqlTreeBuilder.Class()), + _hqlTreeBuilder.Ident(expression.TypeOperand.FullName)); + } + protected HqlTreeNode VisitNhStar(NhStarExpression expression) { return _hqlTreeBuilder.Star(); Modified: trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/QueryModelVisitor.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -79,6 +79,7 @@ ResultOperatorMap.Add<FetchOneRequest, ProcessFetchOne>(); ResultOperatorMap.Add<FetchManyRequest, ProcessFetchMany>(); ResultOperatorMap.Add<CacheableResultOperator, ProcessCacheable>(); + ResultOperatorMap.Add<OfTypeResultOperator, ProcessOfType>(); } private QueryModelVisitor(VisitorParameters visitorParameters, bool root, QueryModel queryModel) Added: trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessOfType.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessOfType.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Linq/Visitors/ResultOperatorProcessors/ProcessOfType.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NHibernate.Hql.Ast; +using Remotion.Data.Linq.Clauses.ResultOperators; +using Remotion.Data.Linq.Clauses.StreamedData; + +namespace NHibernate.Linq.Visitors.ResultOperatorProcessors +{ + public class ProcessOfType : IResultOperatorProcessor<OfTypeResultOperator> + { + public void Process(OfTypeResultOperator resultOperator, QueryModelVisitor queryModelVisitor, IntermediateHqlTree tree) + { + var source = + queryModelVisitor.CurrentEvaluationType.As<StreamedSequenceInfo>().ItemExpression; + + var type = BuildDot(resultOperator.SearchedItemType.FullName.Split('.'), tree.TreeBuilder); + + tree.AddWhereClause(tree.TreeBuilder.Equality( + tree.TreeBuilder.Dot( + HqlGeneratorExpressionTreeVisitor.Visit(source, queryModelVisitor.VisitorParameters).AsExpression(), + tree.TreeBuilder.Class()), + tree.TreeBuilder.Ident(resultOperator.SearchedItemType.FullName))); + } + + private static HqlExpression BuildDot(IEnumerable<string> split, HqlTreeBuilder builder) + { + if (split.Count() == 1) + { + return builder.Ident(split.First()); + } + + return builder.Dot(builder.Ident(split.First()), BuildDot(split.Skip(1), builder)); + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-04-07 10:48:41 UTC (rev 4970) @@ -682,6 +682,7 @@ <Compile Include="Linq\ReWriters\RemoveUnnecessaryBodyOperators.cs" /> <Compile Include="Linq\Clauses\LeftJoinClause.cs" /> <Compile Include="Linq\IntermediateHqlTree.cs" /> + <Compile Include="Linq\Visitors\ResultOperatorProcessors\ProcessOfType.cs" /> <Compile Include="Linq\Visitors\ResultOperatorProcessors\ProcessCacheable.cs" /> <Compile Include="Linq\Visitors\QuerySourceLocator.cs" /> <Compile Include="Linq\Visitors\ResultOperatorProcessors\ProcessFetch.cs" /> Modified: trunk/nhibernate/src/NHibernate.Test/Linq/PagingTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/PagingTests.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate.Test/Linq/PagingTests.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -26,7 +26,7 @@ } [Test] - [Ignore("NHibernate does not currently support subqueries in from clause")] + [Ignore("Multiple Takes (or Skips) not handled correctly")] public void CustomersChainedTake() { var q = (from c in db.Customers @@ -41,7 +41,7 @@ } [Test] - [Ignore("NHibernate does not currently support subqueries in from clause")] + [Ignore("Multiple Takes (or Skips) not handled correctly")] public void CustomersChainedSkip() { var q = (from c in db.Customers select c.CustomerId).Skip(10).Skip(5); @@ -53,7 +53,7 @@ [Test] - [Ignore("NHibernate does not currently support subqueries in from clause")] + [Ignore("Count with Skip or Take is incorrect (Skip / Take done on the query not the HQL, so get applied at the wrong point")] public void CountAfterTakeShouldReportTheCorrectNumber() { var users = db.Customers.Skip(3).Take(10); Modified: trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2010-04-05 07:15:43 UTC (rev 4969) +++ trunk/nhibernate/src/NHibernate.Test/Linq/WhereTests.cs 2010-04-07 10:48:41 UTC (rev 4970) @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using NHibernate.Linq; using NHibernate.Test.Linq.Entities; using NUnit.Framework; @@ -384,5 +385,24 @@ Assert.AreEqual(2, query.Count); } - } + + [Test] + public void SearchOnObjectTypeWithExtensionMethod() + { + var query = (from o in session.Query<Animal>() + select o).OfType<Dog>().ToList(); + + Assert.AreEqual(2, query.Count); + } + + [Test] + public void SearchOnObjectTypeWithIsKeyword() + { + var query = (from o in session.Query<Animal>() + where o is Dog + select o).ToList(); + + Assert.AreEqual(2, query.Count); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |