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