|
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.
|