8
8
9
9
namespace NHibernate . Linq . Visitors
10
10
{
11
- public class SelectClauseVisitor : ExpressionTreeVisitor
12
- {
13
- private readonly ILinqToHqlGeneratorsRegistry functionRegistry ;
14
-
15
- private HashSet < Expression > _hqlNodes ;
16
- private readonly ParameterExpression _inputParameter ;
17
- private readonly VisitorParameters _parameters ;
18
- private int _iColumn ;
19
- private List < HqlExpression > _hqlTreeNodes = new List < HqlExpression > ( ) ;
20
-
21
- public SelectClauseVisitor ( System . Type inputType , VisitorParameters parameters )
22
- {
23
- functionRegistry = parameters . SessionFactory . Settings . LinqToHqlGeneratorsRegistry ;
24
- _inputParameter = Expression . Parameter ( inputType , "input" ) ;
25
- _parameters = parameters ;
26
- }
27
-
28
- public LambdaExpression ProjectionExpression { get ; private set ; }
29
-
30
- public IEnumerable < HqlExpression > GetHqlNodes ( )
31
- {
32
- return _hqlTreeNodes ;
33
- }
34
-
35
- public void Visit ( Expression expression )
36
- {
37
- // First, find the sub trees that can be expressed purely in HQL
38
- _hqlNodes = new Nominator ( CanBeEvaluatedInHqlSelectStatement , CanBeEvaluatedInHqlStatementShortcut ) . Nominate ( expression ) ;
39
-
40
- // Now visit the tree
41
- Expression projection = VisitExpression ( expression ) ;
42
-
43
- if ( ( projection != expression ) && ! _hqlNodes . Contains ( expression ) )
44
- {
45
- ProjectionExpression = Expression . Lambda ( projection , _inputParameter ) ;
46
- }
47
-
48
- // Finally, handle any boolean results in the output nodes
49
- _hqlTreeNodes = BooleanToCaseConvertor . Convert ( _hqlTreeNodes ) . ToList ( ) ;
50
- }
51
-
52
- public override Expression VisitExpression ( Expression expression )
53
- {
54
- if ( expression == null )
55
- {
56
- return null ;
57
- }
58
-
59
- if ( _hqlNodes . Contains ( expression ) )
60
- {
61
- // Pure HQL evaluation - TODO - cache the Visitor?
11
+ public class SelectClauseVisitor : ExpressionTreeVisitor
12
+ {
13
+ private readonly ILinqToHqlGeneratorsRegistry _functionRegistry ;
14
+ private HashSet < Expression > _hqlNodes ;
15
+ private readonly ParameterExpression _inputParameter ;
16
+ private readonly VisitorParameters _parameters ;
17
+ private int _iColumn ;
18
+ private List < HqlExpression > _hqlTreeNodes = new List < HqlExpression > ( ) ;
19
+
20
+ public SelectClauseVisitor ( System . Type inputType , VisitorParameters parameters )
21
+ {
22
+ _functionRegistry = parameters . SessionFactory . Settings . LinqToHqlGeneratorsRegistry ;
23
+ _inputParameter = Expression . Parameter ( inputType , "input" ) ;
24
+ _parameters = parameters ;
25
+ }
26
+
27
+ public LambdaExpression ProjectionExpression { get ; private set ; }
28
+
29
+ public IEnumerable < HqlExpression > GetHqlNodes ( )
30
+ {
31
+ return _hqlTreeNodes ;
32
+ }
33
+
34
+ public void Visit ( Expression expression )
35
+ {
36
+ // First, find the sub trees that can be expressed purely in HQL
37
+ _hqlNodes =
38
+ new Nominator ( CanBeEvaluatedInHqlSelectStatement , CanBeEvaluatedInHqlStatementShortcut ) . Nominate ( expression ) ;
39
+
40
+ // Now visit the tree
41
+ Expression projection = VisitExpression ( expression ) ;
42
+
43
+ if ( ( projection != expression ) && ! _hqlNodes . Contains ( expression ) )
44
+ {
45
+ ProjectionExpression = Expression . Lambda ( projection , _inputParameter ) ;
46
+ }
47
+
48
+ // Finally, handle any boolean results in the output nodes
49
+ _hqlTreeNodes = BooleanToCaseConvertor . Convert ( _hqlTreeNodes ) . ToList ( ) ;
50
+ }
51
+
52
+ public override Expression VisitExpression ( Expression expression )
53
+ {
54
+ if ( expression == null )
55
+ {
56
+ return null ;
57
+ }
58
+
59
+ if ( _hqlNodes . Contains ( expression ) )
60
+ {
61
+ // Pure HQL evaluation - TODO - cache the Visitor?
62
62
var hqlVisitor = new HqlGeneratorExpressionTreeVisitor ( _parameters ) ;
63
-
64
- _hqlTreeNodes . Add ( hqlVisitor . Visit ( expression ) . AsExpression ( ) ) ;
65
-
66
- return Expression . Convert ( Expression . ArrayIndex ( _inputParameter , Expression . Constant ( _iColumn ++ ) ) ,
67
- expression . Type ) ;
68
- }
69
-
70
- // Can't handle this node with HQL. Just recurse down, and emit the expression
71
- return base . VisitExpression ( expression ) ;
72
- }
73
-
74
- private bool CanBeEvaluatedInHqlSelectStatement ( Expression expression )
75
- {
76
- if ( ( expression . NodeType == ExpressionType . MemberInit ) || ( expression . NodeType == ExpressionType . New ) || ( expression . NodeType == ExpressionType . Constant ) )
77
- {
78
- // Hql can't do New or Member Init
79
- return false ;
80
- }
81
-
82
- if ( expression . NodeType == ExpressionType . Call )
83
- {
84
- // Depends if it's in the function registry
85
- IHqlGeneratorForMethod methodGenerator ;
86
- if ( ! functionRegistry . TryGetGenerator ( ( ( MethodCallExpression ) expression ) . Method , out methodGenerator ) )
87
- {
88
- return false ;
89
- }
90
- }
91
-
92
- // Assume all is good
93
- return true ;
94
- }
95
-
96
- private static bool CanBeEvaluatedInHqlStatementShortcut ( Expression expression )
97
- {
98
- return ( ( NhExpressionType ) expression . NodeType ) == NhExpressionType . Count ;
99
- }
100
- }
101
-
102
- public static class BooleanToCaseConvertor
103
- {
104
- public static IEnumerable < HqlExpression > Convert ( IEnumerable < HqlExpression > hqlTreeNodes )
105
- {
106
- return hqlTreeNodes . Select ( node => ConvertBooleanToCase ( node ) ) ;
107
- }
108
-
109
- private static HqlExpression ConvertBooleanToCase ( HqlExpression node )
110
- {
111
- if ( node is HqlBooleanExpression )
112
- {
113
- var builder = new HqlTreeBuilder ( ) ;
114
-
115
- return builder . Case (
116
- new HqlWhen [ ] { builder . When ( node , builder . True ( ) ) } ,
117
- builder . False ( ) ) ;
118
- }
119
-
120
- return node ;
121
- }
122
- }
63
+
64
+ _hqlTreeNodes . Add ( hqlVisitor . Visit ( expression ) . AsExpression ( ) ) ;
65
+
66
+ return Expression . Convert ( Expression . ArrayIndex ( _inputParameter , Expression . Constant ( _iColumn ++ ) ) ,
67
+ expression . Type ) ;
68
+ }
69
+
70
+ // Can't handle this node with HQL. Just recurse down, and emit the expression
71
+ return base . VisitExpression ( expression ) ;
72
+ }
73
+
74
+ private bool CanBeEvaluatedInHqlSelectStatement ( Expression expression )
75
+ {
76
+ if ( ( expression . NodeType == ExpressionType . MemberInit ) || ( expression . NodeType == ExpressionType . New ) ||
77
+ ( expression . NodeType == ExpressionType . Constant ) )
78
+ {
79
+ // Hql can't do New or Member Init
80
+ return false ;
81
+ }
82
+
83
+ if ( expression . NodeType == ExpressionType . Call )
84
+ {
85
+ // Depends if it's in the function registry
86
+ IHqlGeneratorForMethod methodGenerator ;
87
+ if ( ! _functionRegistry . TryGetGenerator ( ( ( MethodCallExpression ) expression ) . Method , out methodGenerator ) )
88
+ {
89
+ return false ;
90
+ }
91
+ }
92
+
93
+ // Assume all is good
94
+ return true ;
95
+ }
96
+
97
+ private static bool CanBeEvaluatedInHqlStatementShortcut ( Expression expression )
98
+ {
99
+ return ( ( NhExpressionType ) expression . NodeType ) == NhExpressionType . Count ;
100
+ }
101
+ }
102
+
103
+ public static class BooleanToCaseConvertor
104
+ {
105
+ public static IEnumerable < HqlExpression > Convert ( IEnumerable < HqlExpression > hqlTreeNodes )
106
+ {
107
+ return hqlTreeNodes . Select ( node => ConvertBooleanToCase ( node ) ) ;
108
+ }
109
+
110
+ private static HqlExpression ConvertBooleanToCase ( HqlExpression node )
111
+ {
112
+ if ( node is HqlBooleanExpression )
113
+ {
114
+ var builder = new HqlTreeBuilder ( ) ;
115
+
116
+ return builder . Case (
117
+ new HqlWhen [ ] { builder . When ( node , builder . True ( ) ) } ,
118
+ builder . False ( ) ) ;
119
+ }
120
+
121
+ return node ;
122
+ }
123
+ }
123
124
}
0 commit comments