|
From: <fab...@us...> - 2011-05-23 19:10:29
|
Revision: 5864
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5864&view=rev
Author: fabiomaulo
Date: 2011-05-23 19:10:23 +0000 (Mon, 23 May 2011)
Log Message:
-----------
Fix NH-2317
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Linq/ReWriters/QueryReferenceExpressionFlattener.cs
trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2317/Fixture.cs
Modified: trunk/nhibernate/src/NHibernate/Linq/ReWriters/QueryReferenceExpressionFlattener.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Linq/ReWriters/QueryReferenceExpressionFlattener.cs 2011-05-23 19:07:03 UTC (rev 5863)
+++ trunk/nhibernate/src/NHibernate/Linq/ReWriters/QueryReferenceExpressionFlattener.cs 2011-05-23 19:10:23 UTC (rev 5864)
@@ -1,61 +1,82 @@
-using System.Linq.Expressions;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
using NHibernate.Linq.Visitors;
using Remotion.Linq;
using Remotion.Linq.Clauses;
using Remotion.Linq.Clauses.Expressions;
+using Remotion.Linq.Clauses.ResultOperators;
namespace NHibernate.Linq.ReWriters
{
+ /// <summary>
+ /// This re-writer is responsible to re-write a query without a body (no where-clause and so on).
+ /// </summary>
public class QueryReferenceExpressionFlattener : NhExpressionTreeVisitor
{
- private readonly QueryModel _model;
+ private readonly QueryModel _model;
+ // NOTE: Skip/Take are not completelly flattenable since Take(10).Skip(5).Take(2) should result in a subqueries-tsunami (so far not common understanding from our users)
+ private static readonly List<System.Type> FlattenableResultOperactors = new List<System.Type>
+ {
+ typeof(CacheableResultOperator),
+ typeof(SkipResultOperator),
+ typeof(TakeResultOperator),
+ };
- private QueryReferenceExpressionFlattener(QueryModel model)
+ private QueryReferenceExpressionFlattener(QueryModel model)
{
- _model = model;
+ _model = model;
}
- public static void ReWrite(QueryModel model)
+ public static void ReWrite(QueryModel model)
{
var visitor = new QueryReferenceExpressionFlattener(model);
model.TransformExpressions(visitor.VisitExpression);
}
- protected override Expression VisitSubQueryExpression(SubQueryExpression subQuery)
- {
- if ((subQuery.QueryModel.BodyClauses.Count == 0) &&
- ((subQuery.QueryModel.ResultOperators.Count == 0) || (subQuery.QueryModel.ResultOperators.Count == 1 && subQuery.QueryModel.ResultOperators[0] is CacheableResultOperator))
- )
- {
- var selectQuerySource =
- subQuery.QueryModel.SelectClause.Selector as QuerySourceReferenceExpression;
+ protected override Expression VisitSubQueryExpression(SubQueryExpression subQuery)
+ {
+ var hasBodyClauses = subQuery.QueryModel.BodyClauses.Count > 0;
+ if(hasBodyClauses)
+ {
+ return base.VisitSubQueryExpression(subQuery);
+ }
+ var resultOperators = subQuery.QueryModel.ResultOperators;
+ if (resultOperators.Count == 0 || HasJustAllFlattenableOperator(resultOperators))
+ {
+ var selectQuerySource = subQuery.QueryModel.SelectClause.Selector as QuerySourceReferenceExpression;
- if (selectQuerySource != null && selectQuerySource.ReferencedQuerySource == subQuery.QueryModel.MainFromClause)
- {
- if (subQuery.QueryModel.ResultOperators.Count == 1)
- {
- _model.ResultOperators.Add(subQuery.QueryModel.ResultOperators[0]);
- }
+ if (selectQuerySource != null && selectQuerySource.ReferencedQuerySource == subQuery.QueryModel.MainFromClause)
+ {
+ foreach (var resultOperator in resultOperators)
+ {
+ _model.ResultOperators.Add(resultOperator);
+ }
- return subQuery.QueryModel.MainFromClause.FromExpression;
- }
- }
+ return subQuery.QueryModel.MainFromClause.FromExpression;
+ }
+ }
- return base.VisitSubQueryExpression(subQuery);
- }
+ return base.VisitSubQueryExpression(subQuery);
+ }
- protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression)
+ private bool HasJustAllFlattenableOperator(IEnumerable<ResultOperatorBase> resultOperators)
{
+ return resultOperators.All(x => FlattenableResultOperactors.Contains(x.GetType()));
+ }
+
+ protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression)
+ {
var fromClauseBase = expression.ReferencedQuerySource as FromClauseBase;
- if (fromClauseBase != null &&
+ if (fromClauseBase != null &&
fromClauseBase.FromExpression is QuerySourceReferenceExpression &&
expression.Type == fromClauseBase.FromExpression.Type)
{
return fromClauseBase.FromExpression;
}
- return base.VisitQuerySourceReferenceExpression(expression);
+ return base.VisitQuerySourceReferenceExpression(expression);
}
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2317/Fixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2317/Fixture.cs 2011-05-23 19:07:03 UTC (rev 5863)
+++ trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/NH2317/Fixture.cs 2011-05-23 19:10:23 UTC (rev 5864)
@@ -5,7 +5,7 @@
namespace NHibernate.Test.NHSpecificTest.NH2317
{
- [TestFixture, Ignore("Not fixed yet.")]
+ [TestFixture]
public class Fixture : BugTestCase
{
protected override void OnSetUp()
@@ -28,8 +28,12 @@
using (var session = sessions.OpenSession())
using(session.BeginTransaction())
{
- // HQL show how should look the HQL tree in this case and in all others casses where Skip/Take are not the last sentences
- var expected = session.CreateQuery("select a.id from Artist a where a in (from Artist take 3)").List<int>();
+ // The HQL : "select a.id from Artist a where a in (from Artist take 3)"
+ // shows how should look the HQL tree in the case where Skip/Take are not the last sentences.
+
+ // When the query has no where-clauses the the HQL can be reduced to: "select a.id from Artist a take 3)"
+
+ var expected = session.CreateQuery("select a.id from Artist a take 3").List<int>();
var actual = session.Query<Artist>().Take(3).Select(a => a.Id).ToArray();
actual.Should().Have.SameValuesAs(expected);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|