-
Notifications
You must be signed in to change notification settings - Fork 934
/
Copy pathPagingRewriter.cs
73 lines (62 loc) · 2.55 KB
/
PagingRewriter.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System.Linq;
using NHibernate.Linq.ReWriters;
using NHibernate.Linq.Visitors;
using Remotion.Linq;
using Remotion.Linq.Clauses;
using Remotion.Linq.Clauses.Expressions;
using Remotion.Linq.Clauses.ResultOperators;
namespace NHibernate.Linq.GroupBy
{
internal static class PagingRewriter
{
private static readonly System.Type[] PagingResultOperators = new[]
{
typeof (SkipResultOperator),
typeof (TakeResultOperator),
};
public static void ReWrite(QueryModel queryModel)
{
var subQueryExpression = queryModel.MainFromClause.FromExpression as SubQueryExpression;
if (subQueryExpression != null &&
subQueryExpression.QueryModel.ResultOperators.All(x => PagingResultOperators.Contains(x.GetType())))
{
FlattenSubQuery(subQueryExpression, queryModel);
}
}
private static void FlattenSubQuery(SubQueryExpression subQueryExpression, QueryModel queryModel)
{
// we can not flatten subquery if outer query has body clauses.
var subQueryModel = subQueryExpression.QueryModel;
var subQueryMainFromClause = subQueryModel.MainFromClause;
if (queryModel.BodyClauses.Count == 0)
{
foreach (var resultOperator in subQueryModel.ResultOperators)
queryModel.ResultOperators.Add(resultOperator);
foreach (var bodyClause in subQueryModel.BodyClauses)
queryModel.BodyClauses.Add(bodyClause);
var visitor1 = new PagingRewriterSelectClauseVisitor(queryModel.MainFromClause);
queryModel.SelectClause.TransformExpressions(visitor1.Swap);
}
else
{
var cro = new ContainsResultOperator(new QuerySourceReferenceExpression(subQueryMainFromClause));
var newSubQueryModel = subQueryModel.Clone();
newSubQueryModel.ResultOperators.Add(cro);
newSubQueryModel.ResultTypeOverride = typeof (bool);
var where = new WhereClause(new SubQueryExpression(newSubQueryModel));
queryModel.BodyClauses.Add(where);
if (RemoveUnnecessaryBodyOperators.IsOrderByNeeded(queryModel) && !queryModel.BodyClauses.OfType<OrderByClause>().Any())
{
var orderByClauses = subQueryModel.BodyClauses.OfType<OrderByClause>();
foreach (var orderByClause in orderByClauses)
queryModel.BodyClauses.Add(orderByClause);
}
}
// Point all query source references to the outer from clause
var visitor2 = new SwapQuerySourceVisitor(queryModel.MainFromClause, subQueryMainFromClause);
queryModel.TransformExpressions(visitor2.Swap);
// Replace the outer query source
queryModel.MainFromClause = subQueryMainFromClause;
}
}
}