annotate Source/Data/Linq/Builder/ExpressionBuilder.SqlBuilder.cs @ 3:1ef98bd70424

!bug 100 +3h Исправление проблемы BLToolkit + mono 3.4
author cin
date Fri, 22 Aug 2014 17:34:46 +0400
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7 using System.Text;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 namespace BLToolkit.Data.Linq.Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11 using BLToolkit.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 using Common;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13 using Data.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 using Mapping;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 using Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 partial class ExpressionBuilder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 #region Build Where
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 public IBuildContext BuildWhere(IBuildContext parent, IBuildContext sequence, LambdaExpression condition, bool checkForSubQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 var makeHaving = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 var prevParent = sequence.Parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 var ctx = new ExpressionContext(parent, sequence, condition);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 var expr = ConvertExpression(condition.Body.Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 if (checkForSubQuery && CheckSubQueryForWhere(ctx, expr, out makeHaving))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 ReplaceParent(ctx, prevParent);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 sequence = new SubQueryContext(sequence);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 prevParent = sequence.Parent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 ctx = new ExpressionContext(parent, sequence, condition);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 BuildSearchCondition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40 ctx,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 expr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 makeHaving ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 ctx.SqlQuery.Having.SearchCondition.Conditions :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 ctx.SqlQuery.Where. SearchCondition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 ReplaceParent(ctx, prevParent);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 return sequence;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51 bool CheckSubQueryForWhere(IBuildContext context, Expression expression, out bool makeHaving)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 var makeSubQuery = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 var isHaving = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 var isWhere = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57 expression.Visit(expr =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 if (_subQueryExpressions != null && _subQueryExpressions.Contains(expr))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61 makeSubQuery = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 isWhere = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66 var stopWalking = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 case ExpressionType.MemberAccess:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 var ma = (MemberExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 if (TypeHelper.IsNullableValueMember(ma.Member) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 TypeHelper.IsNullableHasValueMember(ma.Member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78 if (SqlProvider.ConvertMember(ma.Member) == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 var ctx = GetContext(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 if (ctx.IsExpression(expr, 0, RequestFor.Expression).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 makeSubQuery = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86 stopWalking = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 isWhere = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 case ExpressionType.Call:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 var e = (MethodCallExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 if (e.Method.DeclaringType == typeof(Enumerable) && e.Method.Name != "Contains")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 return isHaving = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 isWhere = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 case ExpressionType.Parameter:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 var ctx = GetContext(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 if (ctx.IsExpression(expr, 0, RequestFor.Expression).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 makeSubQuery = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 stopWalking = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118 isWhere = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 return !stopWalking;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 makeHaving = isHaving && !isWhere;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 return makeSubQuery || isHaving && isWhere;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 #region BuildTake
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135 public void BuildTake(IBuildContext context, ISqlExpression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137 var sql = context.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 sql.Select.Take(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141 SqlProvider.SqlQuery = sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 if (sql.Select.SkipValue != null && SqlProvider.IsTakeSupported && !SqlProvider.IsSkipSupported)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 if (context.SqlQuery.Select.SkipValue is SqlParameter && sql.Select.TakeValue is SqlValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147 var skip = (SqlParameter)sql.Select.SkipValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 var parm = (SqlParameter)sql.Select.SkipValue.Clone(new Dictionary<ICloneableElement,ICloneableElement>(), _ => true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150 parm.SetTakeConverter((int)((SqlValue)sql.Select.TakeValue).Value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 sql.Select.Take(parm);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 var ep = (from pm in CurrentSqlParameters where pm.SqlParameter == skip select pm).First();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 ep = new ParameterAccessor
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 Expression = ep.Expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 Accessor = ep.Accessor,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 SqlParameter = parm
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 CurrentSqlParameters.Add(ep);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166 sql.Select.Take(Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 new SqlBinaryExpression(typeof(int), sql.Select.SkipValue, "+", sql.Select.TakeValue, Precedence.Additive)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171 if (!SqlProvider.TakeAcceptsParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 var p = sql.Select.TakeValue as SqlParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 p.IsQueryParameter = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 #region SubQueryToSql
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184 public IBuildContext GetSubQuery(IBuildContext context, MethodCallExpression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 var info = new BuildInfo(context, expr, new SqlQuery { ParentSql = context.SqlQuery });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 var ctx = BuildSequence(info);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 if (ctx.SqlQuery.Select.Columns.Count == 0 &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 (ctx.IsExpression(null, 0, RequestFor.Expression).Result ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 ctx.IsExpression(null, 0, RequestFor.Field). Result))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 ctx.ConvertToIndex(null, 0, ConvertFlags.Field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196 return ctx;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 internal ISqlExpression SubQueryToSql(IBuildContext context, MethodCallExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 var sequence = GetSubQuery(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 var subSql = sequence.GetSubQuery(context);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204 if (subSql != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 return subSql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 var query = context.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 var subQuery = sequence.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 // This code should be moved to context.
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 if (!query.GroupBy.IsEmpty && !subQuery.Where.IsEmpty)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 var fromGroupBy = sequence.SqlQuery.Properties
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 .OfType<System.Tuple<string,SqlQuery>>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 .Where(p => p.Item1 == "from_group_by" && p.Item2 == context.SqlQuery)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217 .Any();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 if (fromGroupBy)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221 if (subQuery.Select.Columns.Count == 1 &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 subQuery.Select.Columns[0].Expression.ElementType == QueryElementType.SqlFunction &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 subQuery.GroupBy.IsEmpty && !subQuery.Select.HasModifier && !subQuery.HasUnion &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 subQuery.Where.SearchCondition.Conditions.Count == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 var cond = subQuery.Where.SearchCondition.Conditions[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228 if (cond.Predicate.ElementType == QueryElementType.ExprExprPredicate && query.GroupBy.Items.Count == 1 ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 cond.Predicate.ElementType == QueryElementType.SearchCondition &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 query.GroupBy.Items.Count == ((SqlQuery.SearchCondition)cond.Predicate).Conditions.Count)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232 var func = (SqlFunction)subQuery.Select.Columns[0].Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 if (CountBuilder.MethodNames.Contains(func.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235 return SqlFunction.CreateCount(func.SystemType, query);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241 return sequence.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 #region IsSubQuery
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248 bool IsSubQuery(IBuildContext context, MethodCallExpression call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 if (call.IsQueryable())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 var info = new BuildInfo(context, call, new SqlQuery { ParentSql = context.SqlQuery });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 if (!IsSequence(info))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257 var arg = call.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 if (AggregationBuilder.MethodNames.Contains(call.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 while (arg.NodeType == ExpressionType.Call && ((MethodCallExpression) arg).Method.Name == "Select")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261 arg = ((MethodCallExpression)arg).Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 var mc = arg as MethodCallExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 while (mc != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267 if (!mc.IsQueryable())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 return GetTableFunctionAttribute(mc.Method) != null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 mc = mc.Arguments[0] as MethodCallExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 return arg.NodeType == ExpressionType.Call || IsSubQuerySource(context, arg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279 bool IsSubQuerySource(IBuildContext context, Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281 if (expr == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284 var ctx = GetContext(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 if (ctx != null && ctx.IsExpression(expr, 0, RequestFor.Object).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 while (expr != null && expr.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 expr = ((MemberExpression)expr).Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 return expr != null && expr.NodeType == ExpressionType.Constant;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 bool IsGroupJoinSource(IBuildContext context, MethodCallExpression call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 if (!call.IsQueryable() || CountBuilder.MethodNames.Contains(call.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300 Expression expr = call;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 while (expr.NodeType == ExpressionType.Call)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303 expr = ((MethodCallExpression)expr).Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 var ctx = GetContext(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 return ctx != null && ctx.IsExpression(expr, 0, RequestFor.GroupJoin).Result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312 #region ConvertExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314 interface IConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 Expression ConvertNull(MemberExpression expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319 class ConvertHelper<T> : IConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 where T : struct
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 public Expression ConvertNull(MemberExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324 return Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326 ReflectionHelper.Expressor<T?>.MethodExpressor(p => Sql.ConvertNullable(p)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 expression.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331 Expression ConvertExpression(Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 return expression.Convert2(e =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335 if (CanBeConstant(e) || CanBeCompiled(e))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336 return new ExpressionHelper.ConvertInfo(e, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 switch (e.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 case ExpressionType.New:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342 var ex = ConvertNew((NewExpression)e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343 if (ex != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344 return new ExpressionHelper.ConvertInfo(ConvertExpression(ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348 case ExpressionType.Call:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350 var cm = ConvertMethod((MethodCallExpression)e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 if (cm != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352 return new ExpressionHelper.ConvertInfo(ConvertExpression(cm));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356 case ExpressionType.MemberAccess:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
358 var ma = (MemberExpression)e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
359 var l = SqlProvider.ConvertMember(ma.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
360
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
361 if (l != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
362 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
363 var body = l.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
364 var expr = body.Convert(wpi => wpi.NodeType == ExpressionType.Parameter ? ma.Expression : wpi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
365
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
366 if (expr.Type != e.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
367 expr = new ChangeTypeExpression(expr, e.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
368
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
369 return new ExpressionHelper.ConvertInfo(ConvertExpression(expr));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
370 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
371
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
372 if (TypeHelper.IsNullableValueMember(ma.Member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
373 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
374 var ntype = typeof(ConvertHelper<>).MakeGenericType(ma.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
375 var helper = (IConvertHelper)Activator.CreateInstance(ntype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
376 var expr = helper.ConvertNull(ma);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
377
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
378 return new ExpressionHelper.ConvertInfo(ConvertExpression(expr));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
379 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
380
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
381 if (ma.Member.DeclaringType == typeof(TimeSpan))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
382 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
383 switch (ma.Expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
384 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
385 case ExpressionType.Subtract :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
386 case ExpressionType.SubtractChecked:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
387
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
388 Sql.DateParts datePart;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
389
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
390 switch (ma.Member.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
391 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
392 case "TotalMilliseconds" : datePart = Sql.DateParts.Millisecond; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
393 case "TotalSeconds" : datePart = Sql.DateParts.Second; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
394 case "TotalMinutes" : datePart = Sql.DateParts.Minute; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
395 case "TotalHours" : datePart = Sql.DateParts.Hour; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
396 case "TotalDays" : datePart = Sql.DateParts.Day; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
397 default : return new ExpressionHelper.ConvertInfo(e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
398 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
399
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
400 var ex = (BinaryExpression)ma.Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
401 var method = ReflectionHelper.Expressor<object>.MethodExpressor(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
402 _ => Sql.DateDiff(Sql.DateParts.Day, DateTime.MinValue, DateTime.MinValue));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
403
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
404 var call =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
405 Expression.Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
406 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
407 null,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
408 method,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
409 Expression.Constant(datePart),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
410 Expression.Convert(ex.Right, typeof(DateTime?)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
411 Expression.Convert(ex.Left, typeof(DateTime?))),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
412 typeof(double));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
413
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
414 return new ExpressionHelper.ConvertInfo(ConvertExpression(call));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
415 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
416 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
417
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
418 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
419 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
420 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
421
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
422 return new ExpressionHelper.ConvertInfo(e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
423 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
424 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
425
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
426 Expression ConvertMethod(MethodCallExpression pi)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
427 {
3
1ef98bd70424 !bug 100 +3h
cin
parents: 0
diff changeset
428 var l = SqlProvider.ConvertMember(ReflectionHelper.ExtractMethodInfo(pi));
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
429 return l == null ? null : ConvertMethod(pi, l);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
430 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
431
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
432 static Expression ConvertMethod(MethodCallExpression pi, LambdaExpression lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
433 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
434 var ef = lambda.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
435 var parms = new Dictionary<string,int>(lambda.Parameters.Count);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
436 var pn = pi.Method.IsStatic ? 0 : -1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
437
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
438 foreach (var p in lambda.Parameters)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
439 parms.Add(p.Name, pn++);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
440
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
441 var pie = ef.Convert(wpi =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
442 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
443 if (wpi.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
444 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
445 int n;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
446 if (parms.TryGetValue(((ParameterExpression)wpi).Name, out n))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
447 return n < 0 ? pi.Object : pi.Arguments[n];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
448 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
449
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
450 return wpi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
451 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
452
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
453 if (pi.Method.ReturnType != pie.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
454 pie = new ChangeTypeExpression(pie, pi.Method.ReturnType);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
455
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
456 return pie;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
457 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
458
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
459 Expression ConvertNew(NewExpression pi)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
460 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
461 var lambda = SqlProvider.ConvertMember(pi.Constructor);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
462
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
463 if (lambda != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
464 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
465 var ef = lambda.Body.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
466 var parms = new Dictionary<string,int>(lambda.Parameters.Count);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
467 var pn = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
468
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
469 foreach (var p in lambda.Parameters)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
470 parms.Add(p.Name, pn++);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
471
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
472 return ef.Convert(wpi =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
473 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
474 if (wpi.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
475 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
476 var pe = (ParameterExpression)wpi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
477 var n = parms[pe.Name];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
478 return pi.Arguments[n];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
479 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
480
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
481 return wpi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
482 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
483 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
484
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
485 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
486 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
487
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
488 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
489
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
490 #region BuildExpression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
491
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
492 public SqlInfo[] ConvertExpressions(IBuildContext context, Expression expression, ConvertFlags queryConvertFlag)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
493 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
494 expression = ConvertExpression(expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
495
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
496 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
497 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
498 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
499 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
500 var expr = (NewExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
501
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
502 // ReSharper disable ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
503 // ReSharper disable HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
504 if (expr.Members == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
505 return Array<SqlInfo>.Empty;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
506 // ReSharper restore HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
507 // ReSharper restore ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
508
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
509 return expr.Arguments
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
510 .Select((arg,i) =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
511 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
512 var mi = expr.Members[i];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
513 if (mi is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
514 mi = TypeHelper.GetPropertyByMethod((MethodInfo)mi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
515
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
516 return ConvertExpressions(context, arg, queryConvertFlag).Select(si => si.Clone(mi));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
517 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
518 .SelectMany(si => si)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
519 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
520 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
521
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
522 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
523 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
524 var expr = (MemberInitExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
525 var dic = TypeAccessor.GetAccessor(expr.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
526 .Select((m,i) => new { m, i })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
527 .ToDictionary(_ => _.m.MemberInfo, _ => _.i);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
528
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
529 return expr.Bindings
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
530 .Where (b => b is MemberAssignment)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
531 .Cast<MemberAssignment>()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
532 .OrderBy(b => dic[b.Member])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
533 .Select (a =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
534 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
535 var mi = a.Member;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
536 if (mi is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
537 mi = TypeHelper.GetPropertyByMethod((MethodInfo)mi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
538
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
539 return ConvertExpressions(context, a.Expression, queryConvertFlag).Select(si => si.Clone(mi));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
540 })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
541 .SelectMany(si => si)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
542 .ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
543 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
544 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
545
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
546 var ctx = GetContext(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
547
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
548 if (ctx != null && ctx.IsExpression(expression, 0, RequestFor.Object).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
549 return ctx.ConvertToSql(expression, 0, queryConvertFlag);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
550
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
551 return new[] { new SqlInfo { Sql = ConvertToSql(context, expression, false) } };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
552 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
553
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
554 public ISqlExpression ConvertToSqlExpression(IBuildContext context, Expression expression, bool convertEnum)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
555 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
556 var expr = ConvertExpression(expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
557 return ConvertToSql(context, expr, false, convertEnum);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
558 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
559
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
560 #if FW3
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
561 public ISqlExpression ConvertToSql(IBuildContext context, Expression expression, bool unwrap)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
562 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
563 return ConvertToSql(context, expression, unwrap, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
564 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
565 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
566
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
567 public ISqlExpression ConvertToSql(IBuildContext context, Expression expression, bool unwrap, bool convertEnum
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
568 #if !FW3
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
569 = true
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
570 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
571 )
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
572 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
573 if (CanBeConstant(expression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
574 return BuildConstant(expression, convertEnum);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
575
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
576 if (CanBeCompiled(expression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
577 return BuildParameter(expression).SqlParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
578
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
579 if (unwrap)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
580 expression = expression.Unwrap();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
581
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
582 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
583 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
584 case ExpressionType.AndAlso :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
585 case ExpressionType.OrElse :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
586 case ExpressionType.Not :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
587 case ExpressionType.Equal :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
588 case ExpressionType.NotEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
589 case ExpressionType.GreaterThan :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
590 case ExpressionType.GreaterThanOrEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
591 case ExpressionType.LessThan :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
592 case ExpressionType.LessThanOrEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
593 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
594 var condition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
595 BuildSearchCondition(context, expression, condition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
596 return condition;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
597 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
598
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
599 case ExpressionType.And :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
600 case ExpressionType.Or :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
601 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
602 if (expression.Type == typeof(bool))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
603 goto case ExpressionType.AndAlso;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
604 goto case ExpressionType.Add;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
605 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
606
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
607 case ExpressionType.Add :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
608 case ExpressionType.AddChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
609 case ExpressionType.Divide :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
610 case ExpressionType.ExclusiveOr :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
611 case ExpressionType.Modulo :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
612 case ExpressionType.Multiply :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
613 case ExpressionType.MultiplyChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
614 case ExpressionType.Power :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
615 case ExpressionType.Subtract :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
616 case ExpressionType.SubtractChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
617 case ExpressionType.Coalesce :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
618 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
619 var e = (BinaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
620 var l = ConvertToSql(context, e.Left, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
621 var r = ConvertToSql(context, e.Right, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
622 var t = e.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
623
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
624 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
625 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
626 case ExpressionType.Add :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
627 case ExpressionType.AddChecked : return Convert(context, new SqlBinaryExpression(t, l, "+", r, Precedence.Additive));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
628 case ExpressionType.And : return Convert(context, new SqlBinaryExpression(t, l, "&", r, Precedence.Bitwise));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
629 case ExpressionType.Divide : return Convert(context, new SqlBinaryExpression(t, l, "/", r, Precedence.Multiplicative));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
630 case ExpressionType.ExclusiveOr : return Convert(context, new SqlBinaryExpression(t, l, "^", r, Precedence.Bitwise));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
631 case ExpressionType.Modulo : return Convert(context, new SqlBinaryExpression(t, l, "%", r, Precedence.Multiplicative));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
632 case ExpressionType.Multiply:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
633 case ExpressionType.MultiplyChecked : return Convert(context, new SqlBinaryExpression(t, l, "*", r, Precedence.Multiplicative));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
634 case ExpressionType.Or : return Convert(context, new SqlBinaryExpression(t, l, "|", r, Precedence.Bitwise));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
635 case ExpressionType.Power : return Convert(context, new SqlFunction(t, "Power", l, r));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
636 case ExpressionType.Subtract :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
637 case ExpressionType.SubtractChecked : return Convert(context, new SqlBinaryExpression(t, l, "-", r, Precedence.Subtraction));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
638 case ExpressionType.Coalesce :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
639 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
640 if (r is SqlFunction)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
641 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
642 var c = (SqlFunction)r;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
643
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
644 if (c.Name == "Coalesce")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
645 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
646 var parms = new ISqlExpression[c.Parameters.Length + 1];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
647
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
648 parms[0] = l;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
649 c.Parameters.CopyTo(parms, 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
650
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
651 return Convert(context, new SqlFunction(t, "Coalesce", parms));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
652 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
653 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
654
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
655 return Convert(context, new SqlFunction(t, "Coalesce", l, r));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
656 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
657 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
658
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
659 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
660 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
661
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
662 case ExpressionType.UnaryPlus :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
663 case ExpressionType.Negate :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
664 case ExpressionType.NegateChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
665 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
666 var e = (UnaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
667 var o = ConvertToSql(context, e.Operand, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
668 var t = e.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
669
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
670 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
671 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
672 case ExpressionType.UnaryPlus : return o;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
673 case ExpressionType.Negate :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
674 case ExpressionType.NegateChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
675 return Convert(context, new SqlBinaryExpression(t, new SqlValue(-1), "*", o, Precedence.Multiplicative));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
676 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
677
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
678 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
679 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
680
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
681 case ExpressionType.Convert :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
682 case ExpressionType.ConvertChecked :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
683 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
684 var e = (UnaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
685 var o = ConvertToSql(context, e.Operand, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
686
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
687 if (e.Method == null && e.IsLifted)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
688 return o;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
689
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
690 var t = e.Operand.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
691 var s = SqlDataType.GetDataType(t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
692
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
693 if (o.SystemType != null && s.Type == typeof(object))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
694 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
695 t = o.SystemType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
696 s = SqlDataType.GetDataType(t);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
697 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
698
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
699 if (e.Type == t ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
700 t.IsEnum && Enum.GetUnderlyingType(t) == e.Type ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
701 e.Type.IsEnum && Enum.GetUnderlyingType(e.Type) == t)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
702 return o;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
703
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
704 return Convert(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
705 context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
706 new SqlFunction(e.Type, "$Convert$", SqlDataType.GetDataType(e.Type), s, o));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
707 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
708
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
709 case ExpressionType.Conditional :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
710 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
711 var e = (ConditionalExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
712 var s = ConvertToSql(context, e.Test, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
713 var t = ConvertToSql(context, e.IfTrue, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
714 var f = ConvertToSql(context, e.IfFalse, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
715
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
716 if (f is SqlFunction)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
717 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
718 var c = (SqlFunction)f;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
719
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
720 if (c.Name == "CASE")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
721 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
722 var parms = new ISqlExpression[c.Parameters.Length + 2];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
723
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
724 parms[0] = s;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
725 parms[1] = t;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
726 c.Parameters.CopyTo(parms, 2);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
727
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
728 return Convert(context, new SqlFunction(e.Type, "CASE", parms));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
729 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
730 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
731
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
732 return Convert(context, new SqlFunction(e.Type, "CASE", s, t, f));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
733 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
734
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
735 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
736 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
737 var ma = (MemberExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
738 var attr = GetFunctionAttribute(ma.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
739
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
740 if (attr != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
741 return Convert(context, attr.GetExpression(ma.Member));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
742
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
743 var ctx = GetContext(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
744
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
745 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
746 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
747 var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
748
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
749 switch (sql.Length)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
750 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
751 case 0 : break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
752 case 1 : return sql[0].Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
753 default : throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
754 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
755 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
756
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
757 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
758 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
759
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
760 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
761 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
762 var ctx = GetContext(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
763
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
764 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
765 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
766 var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
767
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
768 switch (sql.Length)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
769 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
770 case 0 : break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
771 case 1 : return sql[0].Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
772 default : throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
773 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
774 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
775
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
776 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
777 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
778
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
779 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
780 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
781 var e = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
782
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
783 if (e.IsQueryable())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
784 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
785 if (IsSubQuery(context, e))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
786 return SubQueryToSql(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
787
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
788 if (CountBuilder.MethodNames.Concat(AggregationBuilder.MethodNames).Contains(e.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
789 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
790 var ctx = GetContext(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
791
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
792 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
793 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
794 var sql = ctx.ConvertToSql(expression, 0, ConvertFlags.Field);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
795
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
796 if (sql.Length != 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
797 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
798
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
799 return sql[0].Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
800 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
801
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
802 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
803 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
804
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
805 return SubQueryToSql(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
806 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
807
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
808 var attr = GetFunctionAttribute(e.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
809
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
810 if (attr != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
811 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
812 var parms = new List<ISqlExpression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
813
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
814 if (e.Object != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
815 parms.Add(ConvertToSql(context, e.Object, false));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
816
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
817 parms.AddRange(e.Arguments.Select(t => ConvertToSql(context, t, false)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
818
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
819 return Convert(context, attr.GetExpression(e.Method, parms.ToArray()));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
820 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
821
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
822 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
823 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
824
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
825 case ExpressionType.Invoke :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
826 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
827 var pi = (InvocationExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
828 var ex = pi.Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
829
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
830 if (ex.NodeType == ExpressionType.Quote)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
831 ex = ((UnaryExpression)ex).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
832
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
833 if (ex.NodeType == ExpressionType.Lambda)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
834 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
835 var l = (LambdaExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
836 var dic = new Dictionary<Expression,Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
837
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
838 for (var i = 0; i < l.Parameters.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
839 dic.Add(l.Parameters[i], pi.Arguments[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
840
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
841 var pie = l.Body.Convert(wpi =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
842 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
843 Expression ppi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
844 return dic.TryGetValue(wpi, out ppi) ? ppi : wpi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
845 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
846
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
847 return ConvertToSql(context, pie, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
848 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
849
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
850 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
851 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
852
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
853 case ExpressionType.TypeIs :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
854 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
855 var condition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
856 BuildSearchCondition(context, expression, condition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
857 return condition;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
858 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
859
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
860 case (ExpressionType)ChangeTypeExpression.ChangeTypeType :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
861 return ConvertToSql(context, ((ChangeTypeExpression)expression).Expression, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
862 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
863
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
864 if (expression.Type == typeof(bool) && _convertedPredicates.Add(expression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
865 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
866 var predicate = ConvertPredicate(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
867 _convertedPredicates.Remove(expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
868 if (predicate != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
869 return new SqlQuery.SearchCondition(new SqlQuery.Condition(false, predicate));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
870 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
871
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
872 throw new LinqException("'{0}' cannot be converted to SQL.", expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
873 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
874
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
875 readonly HashSet<Expression> _convertedPredicates = new HashSet<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
876
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
877 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
878
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
879 #region IsServerSideOnly
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
880
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
881 bool IsServerSideOnly(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
882 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
883 switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
884 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
885 case ExpressionType.MemberAccess:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
886 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
887 var ex = (MemberExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
888 var l = SqlProvider.ConvertMember(ex.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
889
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
890 if (l != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
891 return IsServerSideOnly(l.Body.Unwrap());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
892
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
893 var attr = GetFunctionAttribute(ex.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
894 return attr != null && attr.ServerSideOnly;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
895 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
896
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
897 case ExpressionType.Call:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
898 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
899 var e = (MethodCallExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
900
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
901 if (e.Method.DeclaringType == typeof(Enumerable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
902 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
903 if (CountBuilder.MethodNames.Concat(AggregationBuilder.MethodNames).Contains(e.Method.Name))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
904 return IsQueryMember(e.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
905 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
906 else if (e.Method.DeclaringType == typeof(Queryable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
907 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
908 switch (e.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
909 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
910 case "Any" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
911 case "All" :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
912 case "Contains" : return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
913 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
914 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
915 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
916 {
3
1ef98bd70424 !bug 100 +3h
cin
parents: 0
diff changeset
917 var l = SqlProvider.ConvertMember(ReflectionHelper.ExtractMethodInfo(e));
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
918
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
919 if (l != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
920 return l.Body.Unwrap().Find(IsServerSideOnly) != null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
921
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
922 var attr = GetFunctionAttribute(e.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
923 return attr != null && attr.ServerSideOnly;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
924 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
925
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
926 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
927 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
928 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
929
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
930 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
931 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
932
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
933 static bool IsQueryMember(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
934 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
935 if (expr != null) switch (expr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
936 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
937 case ExpressionType.Parameter : return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
938 case ExpressionType.MemberAccess : return IsQueryMember(((MemberExpression)expr).Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
939 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
940 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
941 var call = (MethodCallExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
942
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
943 if (call.Method.DeclaringType == typeof(Queryable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
944 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
945
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
946 if (call.Method.DeclaringType == typeof(Enumerable) && call.Arguments.Count > 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
947 return IsQueryMember(call.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
948
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
949 return IsQueryMember(call.Object);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
950 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
951 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
952
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
953 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
954 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
955
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
956 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
957
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
958 #region CanBeConstant
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
959
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
960 bool CanBeConstant(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
961 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
962 return null == expr.Find(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
963 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
964 if (ex is BinaryExpression || ex is UnaryExpression /*|| ex.NodeType == ExpressionType.Convert*/)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
965 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
966
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
967 switch (ex.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
968 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
969 case ExpressionType.Constant :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
970 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
971 var c = (ConstantExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
972
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
973 if (c.Value == null || ExpressionHelper.IsConstant(ex.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
974 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
975
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
976 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
977 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
978
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
979 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
980 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
981 var ma = (MemberExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
982
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
983 if (ExpressionHelper.IsConstant(ma.Member.DeclaringType) || TypeHelper.IsNullableValueMember(ma.Member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
984 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
985
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
986 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
987 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
988
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
989 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
990 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
991 var mc = (MethodCallExpression)ex;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
992
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
993 if (ExpressionHelper.IsConstant(mc.Method.DeclaringType) || mc.Method.DeclaringType == typeof(object))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
994 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
995
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
996 var attr = GetFunctionAttribute(mc.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
997
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
998 if (attr != null && !attr.ServerSideOnly)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
999 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1000
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1001 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1002 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1003 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1004
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1005 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1006 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1007 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1008
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1009 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1010
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1011 #region CanBeCompiled
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1012
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1013 bool CanBeCompiled(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1014 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1015 return null == expr.Find(ex =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1016 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1017 if (IsServerSideOnly(ex))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1018 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1019
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1020 switch (ex.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1021 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1022 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1023 return ex != ParametersParam;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1024
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1025 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1026 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1027 var attr = GetFunctionAttribute(((MemberExpression)ex).Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1028 return attr != null && attr.ServerSideOnly;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1029 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1030
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1031 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1032 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1033 var attr = GetFunctionAttribute(((MethodCallExpression)ex).Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1034 return attr != null && attr.ServerSideOnly;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1035 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1036 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1037
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1038 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1039 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1040 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1041
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1042 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1043
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1044 #region Build Constant
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1045
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1046 readonly Dictionary<Expression,SqlValue> _constants = new Dictionary<Expression,SqlValue>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1047
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1048 SqlValue BuildConstant(Expression expr, bool convertEnum)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1049 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1050 SqlValue value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1051
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1052 if (_constants.TryGetValue(expr, out value))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1053 return value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1054
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1055 var lambda = Expression.Lambda<Func<object>>(Expression.Convert(expr, typeof(object)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1056 var v = lambda.Compile()();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1057
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1058 if (v != null && convertEnum && v.GetType().IsEnum)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1059 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1060 var attrs = v.GetType().GetCustomAttributes(typeof(SqlEnumAttribute), true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1061
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1062 v = Map.EnumToValue(v, attrs.Length == 0);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1063 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1064
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1065 value = new SqlValue(v);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1066
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1067 _constants.Add(expr, value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1068
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1069 return value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1070 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1071
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1072 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1073
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1074 #region Build Parameter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1075
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1076 readonly Dictionary<Expression,ParameterAccessor> _parameters = new Dictionary<Expression, ParameterAccessor>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1077
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1078 public readonly HashSet<Expression> AsParameters = new HashSet<Expression>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1079
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1080 ParameterAccessor BuildParameter(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1081 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1082 ParameterAccessor p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1083
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1084 if (_parameters.TryGetValue(expr, out p))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1085 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1086
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1087 string name = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1088
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1089 var newExpr = ReplaceParameter(_expressionAccessors, expr, nm => name = nm);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1090 var mapper = Expression.Lambda<Func<Expression,object[],object>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1091 Expression.Convert(newExpr, typeof(object)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1092 new [] { ExpressionParam, ParametersParam });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1093
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1094 p = new ParameterAccessor
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1095 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1096 Expression = expr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1097 Accessor = mapper.Compile(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1098 SqlParameter = new SqlParameter(expr.Type, name, null, MappingSchema)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1099 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1100
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1101 _parameters.Add(expr, p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1102 CurrentSqlParameters.Add(p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1103
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1104 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1105 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1106
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1107 Expression ReplaceParameter(IDictionary<Expression,Expression> expressionAccessors, Expression expression, Action<string> setName)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1108 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1109 return expression.Convert(expr =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1110 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1111 if (expr.NodeType == ExpressionType.Constant)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1112 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1113 var c = (ConstantExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1114
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1115 if (!ExpressionHelper.IsConstant(expr.Type) || AsParameters.Contains(c))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1116 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1117 Expression val;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1118
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1119 if (expressionAccessors.TryGetValue(expr, out val))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1120 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1121 expr = Expression.Convert(val, expr.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1122
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1123 if (expression.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1124 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1125 var ma = (MemberExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1126 setName(ma.Member.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1127 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1128 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1129 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1130 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1131
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1132 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1133 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1134 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1136 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1137
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1138 #region Predicate Converter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1139
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1140 ISqlPredicate ConvertPredicate(IBuildContext context, Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1141 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1142 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1143 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1144 case ExpressionType.Equal :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1145 case ExpressionType.NotEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1146 case ExpressionType.GreaterThan :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1147 case ExpressionType.GreaterThanOrEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1148 case ExpressionType.LessThan :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1149 case ExpressionType.LessThanOrEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1150 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1151 var e = (BinaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1152 return ConvertCompare(context, expression.NodeType, e.Left, e.Right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1153 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1154
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1155 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1156 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1157 var e = (MethodCallExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1158
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1159 ISqlPredicate predicate = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1160
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1161 if (e.Method.Name == "Equals" && e.Object != null && e.Arguments.Count == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1162 return ConvertCompare(context, ExpressionType.Equal, e.Object, e.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1163
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1164 if (e.Method.DeclaringType == typeof(string))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1165 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1166 switch (e.Method.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1167 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1168 case "Contains" : predicate = ConvertLikePredicate(context, e, "%", "%"); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1169 case "StartsWith" : predicate = ConvertLikePredicate(context, e, "", "%"); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1170 case "EndsWith" : predicate = ConvertLikePredicate(context, e, "%", ""); break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1171 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1172 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1173 else if (e.Method.Name == "Contains")
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1174 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1175 if (e.Method.DeclaringType == typeof(Enumerable) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1176 TypeHelper.IsSameOrParent(typeof(IList), e.Method.DeclaringType) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1177 TypeHelper.IsSameOrParent(typeof(ICollection<>), e.Method.DeclaringType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1178 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1179 predicate = ConvertInPredicate(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1180 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1181 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1182 else if (e.Method.Name == "ContainsValue" && TypeHelper.IsSameOrParent(typeof(Dictionary<,>), e.Method.DeclaringType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1183 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1184 var args = TypeHelper.GetGenericArguments(e.Method.DeclaringType, typeof(Dictionary<,>));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1185 var minf = EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1186 .First(m => m.Name == "Contains" && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1187 .MakeGenericMethod(args[1]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1188
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1189 var expr = Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1190 minf,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1191 Expression.PropertyOrField(e.Object, "Values"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1192 e.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1193
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1194 predicate = ConvertInPredicate(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1195 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1196 else if (e.Method.Name == "ContainsKey" && TypeHelper.IsSameOrParent(typeof(IDictionary<,>), e.Method.DeclaringType))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1197 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1198 var args = TypeHelper.GetGenericArguments(e.Method.DeclaringType, typeof(IDictionary<,>));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1199 var minf = EnumerableMethods
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1200 .First(m => m.Name == "Contains" && m.GetParameters().Length == 2)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1201 .MakeGenericMethod(args[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1202
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1203 var expr = Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1204 minf,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1205 Expression.PropertyOrField(e.Object, "Keys"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1206 e.Arguments[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1207
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1208 predicate = ConvertInPredicate(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1209 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1210 #if !SILVERLIGHT
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1211 else if (e.Method == ReflectionHelper.Functions.String.Like11) predicate = ConvertLikePredicate(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1212 else if (e.Method == ReflectionHelper.Functions.String.Like12) predicate = ConvertLikePredicate(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1213 #endif
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1214 else if (e.Method == ReflectionHelper.Functions.String.Like21) predicate = ConvertLikePredicate(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1215 else if (e.Method == ReflectionHelper.Functions.String.Like22) predicate = ConvertLikePredicate(context, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1216
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1217 if (predicate != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1218 return Convert(context, predicate);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1219
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1220 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1221 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1222
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1223 case ExpressionType.Conditional :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1224 return Convert(context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1225 new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1226 ConvertToSql(context, expression, false),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1227 SqlQuery.Predicate.Operator.Equal,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1228 new SqlValue(true)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1229
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1230 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1231 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1232 var e = (MemberExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1233
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1234 if (e.Member.Name == "HasValue" &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1235 e.Member.DeclaringType.IsGenericType &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1236 e.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable<>))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1237 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1238 var expr = ConvertToSql(context, e.Expression, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1239 return Convert(context, new SqlQuery.Predicate.IsNull(expr, true));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1240 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1241
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1242 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1243 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1244
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1245 case ExpressionType.TypeIs:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1246 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1247 var e = (TypeBinaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1248 var ctx = GetContext(context, e.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1249
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1250 if (ctx != null && ctx.IsExpression(e.Expression, 0, RequestFor.Table).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1251 return MakeIsPredicate(ctx, e);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1252
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1253 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1254 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1255 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1256
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1257 var ex = ConvertToSql(context, expression, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1258
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1259 if (SqlExpression.NeedsEqual(ex))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1260 return Convert(context, new SqlQuery.Predicate.ExprExpr(ex, SqlQuery.Predicate.Operator.Equal, new SqlValue(true)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1261
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1262 return Convert(context, new SqlQuery.Predicate.Expr(ex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1263 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1265 #region ConvertCompare
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1266
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1267 ISqlPredicate ConvertCompare(IBuildContext context, ExpressionType nodeType, Expression left, Expression right)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1268 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1269 if (left.NodeType == ExpressionType.Convert && left.Type == typeof(int) && right.NodeType == ExpressionType.Constant)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1270 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1271 var conv = (UnaryExpression)left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1272
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1273 if (conv.Operand.Type == typeof(char))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1274 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1275 left = conv.Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1276 right = Expression.Constant(ConvertTo<char>.From(((ConstantExpression)right).Value));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1277 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1278 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1279
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1280 if (right.NodeType == ExpressionType.Convert && right.Type == typeof(int) && left.NodeType == ExpressionType.Constant)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1281 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1282 var conv = (UnaryExpression)right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1283
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1284 if (conv.Operand.Type == typeof(char))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1285 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1286 right = conv.Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1287 left = Expression.Constant(ConvertTo<char>.From(((ConstantExpression)left).Value));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1288 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1289 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1290
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1291 #region special case for char?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1292
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1293 // if (left.NodeType == ExpressionType.Convert && left.Type == typeof(int?) && right.NodeType == ExpressionType.Convert)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1294 // {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1295 // var convLeft = left as UnaryExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1296 // var convRight = right as UnaryExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1297 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1298 // if (convLeft != null && convRight != null && convLeft.Operand.Type == typeof(char?))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1299 // {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1300 // left = convLeft.Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1301 // right = Expression.Constant(ConvertTo<char?>.From(((ConstantExpression)convRight.Operand).Value));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1302 // }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1303 // }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1304
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1305 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1306
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1307 switch (nodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1308 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1309 case ExpressionType.Equal :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1310 case ExpressionType.NotEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1311
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1312 var p = ConvertObjectComparison(nodeType, context, left, context, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1313 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1314 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1315
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1316 p = ConvertObjectNullComparison(context, left, right, nodeType == ExpressionType.Equal);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1317 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1318 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1319
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1320 p = ConvertObjectNullComparison(context, right, left, nodeType == ExpressionType.Equal);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1321 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1322 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1323
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1324 if (left.NodeType == ExpressionType.New || right.NodeType == ExpressionType.New)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1325 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1326 p = ConvertNewObjectComparison(context, nodeType, left, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1327 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1328 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1329 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1330
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1331 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1332 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1333
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1334 SqlQuery.Predicate.Operator op;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1335
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1336 switch (nodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1337 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1338 case ExpressionType.Equal : op = SqlQuery.Predicate.Operator.Equal; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1339 case ExpressionType.NotEqual : op = SqlQuery.Predicate.Operator.NotEqual; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1340 case ExpressionType.GreaterThan : op = SqlQuery.Predicate.Operator.Greater; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1341 case ExpressionType.GreaterThanOrEqual: op = SqlQuery.Predicate.Operator.GreaterOrEqual; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1342 case ExpressionType.LessThan : op = SqlQuery.Predicate.Operator.Less; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1343 case ExpressionType.LessThanOrEqual : op = SqlQuery.Predicate.Operator.LessOrEqual; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1344 default: throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1345 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1346
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1347 if (left.NodeType == ExpressionType.Convert || right.NodeType == ExpressionType.Convert
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1348 || left.NodeType == ExpressionType.MemberAccess || right.NodeType == ExpressionType.MemberAccess)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1349 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1350 var p = ConvertEnumConversion(context, left, op, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1351 if (p != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1352 return p;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1353 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1354
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1355 var l = ConvertToSql(context, left, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1356 var r = ConvertToSql(context, right, true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1357
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1358 switch (nodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1359 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1360 case ExpressionType.Equal :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1361 case ExpressionType.NotEqual:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1362
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1363 if (!context.SqlQuery.IsParameterDependent && (l is SqlParameter || r is SqlParameter) && l.CanBeNull() && r.CanBeNull())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1364 context.SqlQuery.IsParameterDependent = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1365
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1366 // | (SqlQuery(Select([]) as q), SqlValue(null))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1367 // | (SqlValue(null), SqlQuery(Select([]) as q)) =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1368
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1369 SqlQuery q =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1370 l.ElementType == QueryElementType.SqlQuery &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1371 r.ElementType == QueryElementType.SqlValue &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1372 ((SqlValue)r).Value == null &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1373 ((SqlQuery)l).Select.Columns.Count == 0 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1374 (SqlQuery)l :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1375 r.ElementType == QueryElementType.SqlQuery &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1376 l.ElementType == QueryElementType.SqlValue &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1377 ((SqlValue)l).Value == null &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1378 ((SqlQuery)r).Select.Columns.Count == 0 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1379 (SqlQuery)r :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1380 null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1381
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1382 if (q != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1383 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1384 q.Select.Columns.Add(new SqlQuery.Column(q, new SqlValue(1)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1385 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1386
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1387 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1388 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1389
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1390 if (l is SqlQuery.SearchCondition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1391 l = Convert(context, new SqlFunction(typeof(bool), "CASE", l, new SqlValue(true), new SqlValue(false)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1392
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1393 if (r is SqlQuery.SearchCondition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1394 r = Convert(context, new SqlFunction(typeof(bool), "CASE", r, new SqlValue(true), new SqlValue(false)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1395
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1396 return Convert(context, new SqlQuery.Predicate.ExprExpr(l, op, r));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1397 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1398
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1399 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1400
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1401 #region ConvertEnumConversion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1402
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1403 ISqlPredicate ConvertEnumConversion(IBuildContext context, Expression left, SqlQuery.Predicate.Operator op, Expression right)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1404 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1405 Expression value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1406 Expression operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1407
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1408 if (left is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1409 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1410 operand = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1411 value = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1412 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1413 else if (left.NodeType == ExpressionType.Convert && ((UnaryExpression)left).Operand is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1414 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1415 operand = ((UnaryExpression)left).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1416 value = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1417 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1418 else if (right is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1419 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1420 operand = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1421 value = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1422 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1423 else if (right.NodeType == ExpressionType.Convert && ((UnaryExpression)right).Operand is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1424 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1425 operand = ((UnaryExpression)right).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1426 value = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1427 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1428 else if (left.NodeType == ExpressionType.Convert)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1429 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1430 operand = ((UnaryExpression)left).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1431 value = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1432 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1433 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1434 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1435 operand = ((UnaryExpression)right).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1436 value = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1437 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1438
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1439 var type = operand.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1440
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1441 if (!TypeHelper.IsEnumOrNullableEnum(type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1442 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1443
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1444 var dic = new Dictionary<object,object>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1445
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1446 var nullValue = MappingSchema.GetNullValue(type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1447
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1448 if (nullValue != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1449 dic.Add(nullValue, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1450
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1451 var mapValues = MappingSchema.GetMapValues(type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1452
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1453 if (mapValues != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1454 foreach (var mv in mapValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1455 if (!dic.ContainsKey(mv.OrigValue))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1456 dic.Add(mv.OrigValue, mv.MapValues[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1457
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1458 switch (value.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1459 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1460 case ExpressionType.Constant:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1461 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1462 var name = Enum.GetName(type, ((ConstantExpression)value).Value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1463
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1464 // ReSharper disable ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1465 // ReSharper disable HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1466 if (name == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1467 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1468 // ReSharper restore HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1469 // ReSharper restore ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1470
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1471 var origValue = Enum.Parse(type, name, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1472 var mapValue = origValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1473
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1474 if (!(operand is MemberExpression))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1475 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1476 if (!dic.TryGetValue(origValue, out mapValue))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1477 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1478 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1479
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1480 ISqlExpression l, r;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1481
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1482 SqlValue sqlValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1483
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1484 if (left.NodeType == ExpressionType.Convert)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1485 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1486 l = ConvertToSql(context, operand, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1487 r = sqlValue = new SqlValue(mapValue);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1488 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1489 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1490 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1491 r = ConvertToSql(context, operand, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1492 l = sqlValue = new SqlValue(mapValue);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1493 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1494
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1495 if (operand is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1496 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1497 var me = (MemberExpression)operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1498 var memberAccessor = TypeAccessor.GetAccessor(me.Member.DeclaringType)[me.Member.Name];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1499 sqlValue.SetEnumConverter(memberAccessor, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1500 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1501
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1502
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1503 return Convert(context, new SqlQuery.Predicate.ExprExpr(l, op, r));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1504 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1505
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1506 case ExpressionType.Convert:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1507 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1508 value = ((UnaryExpression)value).Operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1509
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1510 var l = ConvertToSql(context, operand, false, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1511 var r = ConvertToSql(context, value, false, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1512
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1513 MemberAccessor memberAccessor = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1514
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1515 if (operand is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1516 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1517 // is it even possible that operand is not MemberExpression?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1518 // if no, then we can remove this two last uses of SetEnumConverter(type, map)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1519 // and other depending code
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1520 // At least currently there is no test coverage for this method and I didn't
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1521 // manage to create such test
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1522 var me = (MemberExpression)operand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1523 memberAccessor = TypeAccessor.GetAccessor(me.Member.DeclaringType)[me.Member.Name];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1524 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1525
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1526 if (l is SqlValueBase)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1527 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1528 if (memberAccessor != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1529 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1530 ((SqlValueBase)l).SetEnumConverter(memberAccessor, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1531 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1532 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1533 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1534 ((SqlValueBase)l).SetEnumConverter(type, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1535 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1536 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1537
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1538 if (r is SqlValueBase)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1539 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1540 if (memberAccessor != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1541 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1542 ((SqlValueBase)r).SetEnumConverter(memberAccessor, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1543 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1544 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1545 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1546 ((SqlValueBase)r).SetEnumConverter(type, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1547 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1548 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1549
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1550 return Convert(context, new SqlQuery.Predicate.ExprExpr(l, op, r));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1551 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1552 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1553
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1554 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1555 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1556
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1557 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1558
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1559 #region ConvertObjectNullComparison
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1560
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1561 ISqlPredicate ConvertObjectNullComparison(IBuildContext context, Expression left, Expression right, bool isEqual)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1562 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1563 if (right.NodeType == ExpressionType.Constant && ((ConstantExpression)right).Value == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1564 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1565 if (left.NodeType == ExpressionType.MemberAccess || left.NodeType == ExpressionType.Parameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1566 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1567 var ctx = GetContext(context, left);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1568
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1569 if (ctx != null && ctx.IsExpression(left, 0, RequestFor.Object).Result ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1570 left.NodeType == ExpressionType.Parameter && ctx.IsExpression(left, 0, RequestFor.Field).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1571 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1572 return new SqlQuery.Predicate.Expr(new SqlValue(!isEqual));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1573 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1574 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1575 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1576
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1577 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1578 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1579
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1580 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1581
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1582 #region ConvertObjectComparison
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1583
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1584 public ISqlPredicate ConvertObjectComparison(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1585 ExpressionType nodeType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1586 IBuildContext leftContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1587 Expression left,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1588 IBuildContext rightContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1589 Expression right)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1590 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1591 var qsl = GetContext(leftContext, left);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1592 var qsr = GetContext(rightContext, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1593
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1594 var sl = qsl != null && qsl.IsExpression(left, 0, RequestFor.Object).Result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1595 var sr = qsr != null && qsr.IsExpression(right, 0, RequestFor.Object).Result;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1596
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1597 bool isNull;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1598 SqlInfo[] lcols;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1599
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1600 var rmembers = new Dictionary<MemberInfo,Expression>(new MemberInfoComparer());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1601
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1602 if (sl == false && sr == false)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1603 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1604 var lmembers = new Dictionary<MemberInfo,Expression>(new MemberInfoComparer());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1605
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1606 if (!ProcessProjection(lmembers, left) && !ProcessProjection(rmembers, right))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1607 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1608
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1609 if (lmembers.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1610 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1611 var r = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1612 right = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1613 left = r;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1614
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1615 var c = rightContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1616 rightContext = leftContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1617 leftContext = c;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1618
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1619 var q = qsr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1620 qsl = q;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1621
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1622 sr = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1623
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1624 var lm = lmembers;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1625 lmembers = rmembers;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1626 rmembers = lm;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1627 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1628
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1629 isNull = right is ConstantExpression && ((ConstantExpression)right).Value == null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1630 lcols = lmembers.Select(m => new SqlInfo(m.Key) { Sql = ConvertToSql(leftContext, m.Value, false) }).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1631 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1632 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1633 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1634 if (sl == false)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1635 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1636 var r = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1637 right = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1638 left = r;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1639
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1640 var c = rightContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1641 rightContext = leftContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1642 leftContext = c;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1643
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1644 var q = qsr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1645 qsl = q;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1646
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1647 sr = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1648 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1649
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1650 isNull = right is ConstantExpression && ((ConstantExpression)right).Value == null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1651 lcols = qsl.ConvertToSql(left, 0, ConvertFlags.Key);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1652
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1653 if (!sr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1654 ProcessProjection(rmembers, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1655 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1656
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1657 if (lcols.Length == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1658 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1659
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1660 var condition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1661
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1662 foreach (var lcol in lcols)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1663 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1664 if (lcol.Members.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1665 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1666
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1667 ISqlExpression rcol = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1668
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1669 var lmember = lcol.Members[lcol.Members.Count - 1];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1670
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1671 if (sr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1672 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1673 var info = rightContext.ConvertToSql(Expression.MakeMemberAccess(right, lmember), 0, ConvertFlags.Field).Single();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1674 rcol = info.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1675 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1676 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1677 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1678 if (rmembers.Count != 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1679 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1680 var info = rightContext.ConvertToSql(rmembers[lmember], 0, ConvertFlags.Field)[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1681 rcol = info.Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1682 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1683 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1684
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1685 var rex =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1686 isNull ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1687 new SqlValue(right.Type, null) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1688 rcol ?? GetParameter(right, lmember);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1689
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1690 var predicate = Convert(leftContext, new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1691 lcol.Sql,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1692 nodeType == ExpressionType.Equal ? SqlQuery.Predicate.Operator.Equal : SqlQuery.Predicate.Operator.NotEqual,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1693 rex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1694
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1695 condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1696 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1697
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1698 if (nodeType == ExpressionType.NotEqual)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1699 foreach (var c in condition.Conditions)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1700 c.IsOr = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1701
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1702 return condition;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1703 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1704
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1705 ISqlPredicate ConvertNewObjectComparison(IBuildContext context, ExpressionType nodeType, Expression left, Expression right)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1706 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1707 left = FindExpression(left);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1708 right = FindExpression(right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1709
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1710 var condition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1711
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1712 if (left.NodeType != ExpressionType.New)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1713 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1714 var temp = left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1715 left = right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1716 right = temp;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1717 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1718
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1719 var newRight = right as NewExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1720 var newExpr = (NewExpression)left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1721
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1722 // ReSharper disable ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1723 // ReSharper disable HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1724 if (newExpr.Members == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1725 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1726 // ReSharper restore HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1727 // ReSharper restore ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1728
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1729 for (var i = 0; i < newExpr.Arguments.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1730 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1731 var lex = ConvertToSql(context, newExpr.Arguments[i], false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1732 var rex =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1733 newRight != null ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1734 ConvertToSql(context, newRight.Arguments[i], false) :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1735 GetParameter(right, newExpr.Members[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1736
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1737 var predicate = Convert(context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1738 new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1739 lex,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1740 nodeType == ExpressionType.Equal ? SqlQuery.Predicate.Operator.Equal : SqlQuery.Predicate.Operator.NotEqual,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1741 rex));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1742
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1743 condition.Conditions.Add(new SqlQuery.Condition(false, predicate));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1744 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1745
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1746 if (nodeType == ExpressionType.NotEqual)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1747 foreach (var c in condition.Conditions)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1748 c.IsOr = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1749
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1750 return condition;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1751 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1752
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1753 ISqlExpression GetParameter(Expression ex, MemberInfo member)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1754 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1755 if (member is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1756 member = TypeHelper.GetPropertyByMethod((MethodInfo)member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1757
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1758 var par = ReplaceParameter(_expressionAccessors, ex, _ => {});
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1759 var expr = Expression.MakeMemberAccess(par.Type == typeof(object) ? Expression.Convert(par, member.DeclaringType) : par, member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1760 var mapper = Expression.Lambda<Func<Expression,object[],object>>(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1761 Expression.Convert(expr, typeof(object)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1762 new [] { ExpressionParam, ParametersParam });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1763
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1764 var p = new ParameterAccessor
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1765 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1766 Expression = expr,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1767 Accessor = mapper.Compile(),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1768 SqlParameter = new SqlParameter(expr.Type, member.Name, null, MappingSchema)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1769 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1770
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1771 _parameters.Add(expr, p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1772 CurrentSqlParameters.Add(p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1773
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1774 return p.SqlParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1775 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1776
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1777 static Expression FindExpression(Expression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1778 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1779 var ret = expr.Find(pi =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1780 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1781 switch (pi.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1782 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1783 case ExpressionType.Convert :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1784 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1785 var e = (UnaryExpression)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1786
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1787 return
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1788 e.Operand.NodeType == ExpressionType.ArrayIndex &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1789 ((BinaryExpression)e.Operand).Left == ParametersParam;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1790 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1791
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1792 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1793 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1794 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1795 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1796
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1797 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1798 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1799
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1800 if (ret == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1801 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1802
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1803 return ret;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1804 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1805
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1806 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1807
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1808 #region ConvertInPredicate
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1809
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1810 private ISqlPredicate ConvertInPredicate(IBuildContext context, MethodCallExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1811 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1812 var e = expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1813 var argIndex = e.Object != null ? 0 : 1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1814 var arr = e.Object ?? e.Arguments[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1815 var arg = e.Arguments[argIndex];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1816
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1817 ISqlExpression expr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1818
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1819 var ctx = GetContext(context, arg);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1820
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1821 if (ctx is TableBuilder.TableContext &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1822 ctx.SqlQuery != context.SqlQuery &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1823 ctx.IsExpression(arg, 0, RequestFor.Object).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1824 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1825 expr = ctx.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1826 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1827
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1828 if (expr == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1829 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1830 var sql = ConvertExpressions(context, arg, ConvertFlags.Key);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1831
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1832 if (sql.Length == 1 && sql[0].Members.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1833 expr = sql[0].Sql;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1834 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1835 expr = new SqlExpression(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1836 '\x1' + string.Join(",", sql.Select(s => s.Members[s.Members.Count - 1].Name).ToArray()),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1837 sql.Select(s => s.Sql).ToArray());
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1838 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1839
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1840 MemberAccessor memberAccessor = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1841
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1842 if (arg is MemberExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1843 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1844 var me = (MemberExpression)arg;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1845 if (TypeHelper.IsEnumOrNullableEnum(me.Type))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1846 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1847 memberAccessor = TypeAccessor.GetAccessor(me.Member.DeclaringType)[me.Member.Name];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1848 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1849 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1850
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1851 switch (arr.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1852 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1853 case ExpressionType.NewArrayInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1854 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1855 var newArr = (NewArrayExpression)arr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1856
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1857 if (newArr.Expressions.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1858 return new SqlQuery.Predicate.Expr(new SqlValue(false));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1859
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1860 var exprs = new ISqlExpression[newArr.Expressions.Count];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1861
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1862 for (var i = 0; i < newArr.Expressions.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1863 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1864 exprs[i] = ConvertToSql(context, newArr.Expressions[i], false, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1865
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1866 if (memberAccessor != null && exprs[i] is SqlValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1867 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1868 ((SqlValue)exprs[i]).SetEnumConverter(memberAccessor, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1869 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1870 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1871
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1872 return new SqlQuery.Predicate.InList(expr, false, exprs);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1873 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1874
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1875 default :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1876
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1877 if (CanBeCompiled(arr))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1878 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1879 var p = BuildParameter(arr).SqlParameter;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1880 p.IsQueryParameter = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1881 if (memberAccessor != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1882 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1883 p.SetEnumConverter(memberAccessor, MappingSchema);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1884 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1885 return new SqlQuery.Predicate.InList(expr, false, p);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1886 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1887
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1888 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1889 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1890
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1891 throw new LinqException("'{0}' cannot be converted to SQL.", expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1892 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1893
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1894 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1895
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1896 #region LIKE predicate
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1897
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1898 ISqlPredicate ConvertLikePredicate(IBuildContext context, MethodCallExpression expression, string start, string end)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1899 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1900 var e = expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1901 var o = ConvertToSql(context, e.Object, false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1902 var a = ConvertToSql(context, e.Arguments[0], false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1903
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1904 if (a is SqlValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1905 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1906 var value = ((SqlValue)a).Value;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1907
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1908 if (value == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1909 throw new LinqException("NULL cannot be used as a LIKE predicate parameter.");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1910
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1911 return value.ToString().IndexOfAny(new[] { '%', '_' }) < 0?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1912 new SqlQuery.Predicate.Like(o, false, new SqlValue(start + value + end), null):
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1913 new SqlQuery.Predicate.Like(o, false, new SqlValue(start + EscapeLikeText(value.ToString()) + end), new SqlValue('~'));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1914 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1915
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1916 if (a is SqlParameter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1917 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1918 var p = (SqlParameter)a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1919 var ep = (from pm in CurrentSqlParameters where pm.SqlParameter == p select pm).First();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1920
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1921 ep = new ParameterAccessor
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1922 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1923 Expression = ep.Expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1924 Accessor = ep.Accessor,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1925 SqlParameter = new SqlParameter(ep.Expression.Type, p.Name, p.Value, GetLikeEscaper(start, end))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1926 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1927
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1928 CurrentSqlParameters.Add(ep);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1929
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1930 return new SqlQuery.Predicate.Like(o, false, ep.SqlParameter, new SqlValue('~'));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1931 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1932
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1933 var mi = ReflectionHelper.Expressor<string>.MethodExpressor(_ => _.Replace("", ""));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1934 var ex =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1935 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1936 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1937 Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1938 e.Arguments[0],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1939 mi, Expression.Constant("~"), Expression.Constant("~~")),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1940 mi, Expression.Constant("%"), Expression.Constant("~%")),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1941 mi, Expression.Constant("_"), Expression.Constant("~_"));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1942
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1943 var expr = ConvertToSql(context, ConvertExpression(ex), false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1944
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1945 if (!string.IsNullOrEmpty(start))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1946 expr = new SqlBinaryExpression(typeof(string), new SqlValue("%"), "+", expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1947
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1948 if (!string.IsNullOrEmpty(end))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1949 expr = new SqlBinaryExpression(typeof(string), expr, "+", new SqlValue("%"));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1950
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1951 return new SqlQuery.Predicate.Like(o, false, expr, new SqlValue('~'));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1952 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1953
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1954 ISqlPredicate ConvertLikePredicate(IBuildContext context, MethodCallExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1955 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1956 var e = expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1957 var a1 = ConvertToSql(context, e.Arguments[0], false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1958 var a2 = ConvertToSql(context, e.Arguments[1], false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1959
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1960 ISqlExpression a3 = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1961
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1962 if (e.Arguments.Count == 3)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1963 a3 = ConvertToSql(context, e.Arguments[2], false);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1964
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1965 return new SqlQuery.Predicate.Like(a1, false, a2, a3);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1966 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1967
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1968 static string EscapeLikeText(string text)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1969 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1970 if (text.IndexOfAny(new[] { '%', '_' }) < 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1971 return text;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1972
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1973 var builder = new StringBuilder(text.Length);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1974
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1975 foreach (var ch in text)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1976 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1977 switch (ch)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1978 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1979 case '%':
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1980 case '_':
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1981 case '~':
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1982 builder.Append('~');
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1983 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1984 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1985
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1986 builder.Append(ch);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1987 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1988
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1989 return builder.ToString();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1990 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1991
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1992 static Converter<object,object> GetLikeEscaper(string start, string end)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1993 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1994 return value => value == null? null: start + EscapeLikeText(value.ToString()) + end;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1995 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1996
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1997 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1998
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1999 #region MakeIsPredicate
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2000
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2001 internal ISqlPredicate MakeIsPredicate(TableBuilder.TableContext table, Type typeOperand)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2002 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2003 if (typeOperand == table.ObjectType && !table.InheritanceMapping.Any(m => m.Type == typeOperand))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2004 return Convert(table, new SqlQuery.Predicate.Expr(new SqlValue(true)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2005
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2006 return MakeIsPredicate(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2007 table, table.InheritanceMapping, table.InheritanceDiscriminators, typeOperand,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2008 name => table.SqlTable.Fields.Values.First(f => f.Name == name));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2009 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2010
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2011 internal ISqlPredicate MakeIsPredicate(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2012 IBuildContext context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2013 List<InheritanceMappingAttribute> inheritanceMapping,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2014 List<string> inheritanceDiscriminators,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2015 Type toType,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2016 Func<string,ISqlExpression> getSql)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2017 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2018 var mapping = inheritanceMapping
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2019 .Select((m,i) => new { m, i })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2020 .Where ( m => m.m.Type == toType && !m.m.IsDefault)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2021 .ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2022
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2023 switch (mapping.Count)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2024 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2025 case 0 :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2026 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2027 var cond = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2028
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2029 foreach (var m in inheritanceMapping.Select((m,i) => new { m, i }).Where(m => !m.m.IsDefault))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2030 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2031 cond.Conditions.Add(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2032 new SqlQuery.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2033 false,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2034 Convert(context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2035 new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2036 getSql(inheritanceDiscriminators[m.i]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2037 SqlQuery.Predicate.Operator.NotEqual,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2038 new SqlValue(m.m.Code)))));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2039 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2040
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2041 return cond;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2042 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2043
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2044 case 1 :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2045 return Convert(context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2046 new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2047 getSql(inheritanceDiscriminators[mapping[0].i]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2048 SqlQuery.Predicate.Operator.Equal,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2049 new SqlValue(mapping[0].m.Code)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2050
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2051 default:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2052 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2053 var cond = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2054
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2055 foreach (var m in mapping)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2056 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2057 cond.Conditions.Add(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2058 new SqlQuery.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2059 false,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2060 Convert(context,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2061 new SqlQuery.Predicate.ExprExpr(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2062 getSql(inheritanceDiscriminators[m.i]),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2063 SqlQuery.Predicate.Operator.Equal,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2064 new SqlValue(m.m.Code))),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2065 true));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2066 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2067
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2068 return cond;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2069 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2070 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2071 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2072
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2073 ISqlPredicate MakeIsPredicate(IBuildContext context, TypeBinaryExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2074 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2075 var typeOperand = expression.TypeOperand;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2076 var table = new TableBuilder.TableContext(this, new BuildInfo((IBuildContext)null, Expression.Constant(null), new SqlQuery()), typeOperand);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2077
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2078 if (typeOperand == table.ObjectType && !table.InheritanceMapping.Any(m => m.Type == typeOperand))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2079 return Convert(table, new SqlQuery.Predicate.Expr(new SqlValue(true)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2080
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2081 var mapping = table.InheritanceMapping.Select((m,i) => new { m, i }).Where(m => m.m.Type == typeOperand && !m.m.IsDefault).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2082 var isEqual = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2083
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2084 if (mapping.Count == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2085 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2086 mapping = table.InheritanceMapping.Select((m,i) => new { m, i }).Where(m => !m.m.IsDefault).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2087 isEqual = false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2088 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2089
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2090 Expression expr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2091
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2092 foreach (var m in mapping)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2093 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2094 var field = table.SqlTable.Fields[table.InheritanceDiscriminators[m.i]];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2095 var ttype = field.MemberMapper.MemberAccessor.TypeAccessor.OriginalType;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2096 var obj = expression.Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2097
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2098 if (obj.Type != ttype)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2099 obj = Expression.Convert(expression.Expression, ttype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2100
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2101 var left = Expression.PropertyOrField(obj, field.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2102 var code = m.m.Code;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2103
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2104 if (code == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2105 code = TypeHelper.GetDefaultValue(left.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2106 else if (left.Type != code.GetType())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2107 code = MappingSchema.ConvertChangeType(code, left.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2109 Expression right = Expression.Constant(code, left.Type);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2110
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2111 var e = isEqual ? Expression.Equal(left, right) : Expression.NotEqual(left, right);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2112
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2113 expr = expr != null ? Expression.AndAlso(expr, e) : e;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2114 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2115
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2116 return ConvertPredicate(context, expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2117 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2118
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2119 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2120
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2121 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2122
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2123 #region Search Condition Builder
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2124
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2125 void BuildSearchCondition(IBuildContext context, Expression expression, List<SqlQuery.Condition> conditions)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2126 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2127 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2128 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2129 case ExpressionType.And :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2130 case ExpressionType.AndAlso :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2131 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2132 var e = (BinaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2133
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2134 BuildSearchCondition(context, e.Left, conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2135 BuildSearchCondition(context, e.Right, conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2136
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2137 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2138 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2139
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2140 case ExpressionType.Or :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2141 case ExpressionType.OrElse :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2142 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2143 var e = (BinaryExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2144 var orCondition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2145
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2146 BuildSearchCondition(context, e.Left, orCondition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2147 orCondition.Conditions[orCondition.Conditions.Count - 1].IsOr = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2148 BuildSearchCondition(context, e.Right, orCondition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2149
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2150 conditions.Add(new SqlQuery.Condition(false, orCondition));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2151
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2152 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2153 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2154
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2155 case ExpressionType.Not :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2156 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2157 var e = expression as UnaryExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2158 var notCondition = new SqlQuery.SearchCondition();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2159
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2160 BuildSearchCondition(context, e.Operand, notCondition.Conditions);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2161
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2162 if (notCondition.Conditions.Count == 1 && notCondition.Conditions[0].Predicate is SqlQuery.Predicate.NotExpr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2163 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2164 var p = notCondition.Conditions[0].Predicate as SqlQuery.Predicate.NotExpr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2165 p.IsNot = !p.IsNot;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2166 conditions.Add(notCondition.Conditions[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2167 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2168 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2169 conditions.Add(new SqlQuery.Condition(true, notCondition));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2170
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2171 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2172 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2173
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2174 default :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2175 var predicate = ConvertPredicate(context, expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2176
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2177 if (predicate is SqlQuery.Predicate.Expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2178 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2179 var expr = ((SqlQuery.Predicate.Expr)predicate).Expr1;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2180
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2181 if (expr.ElementType == QueryElementType.SearchCondition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2182 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2183 var sc = (SqlQuery.SearchCondition)expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2184
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2185 if (sc.Conditions.Count == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2186 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2187 conditions.Add(sc.Conditions[0]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2188 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2189 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2190 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2191 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2192
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2193 conditions.Add(new SqlQuery.Condition(false, predicate));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2194
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2195 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2196 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2197 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2199 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2200
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2201 #region CanBeTranslatedToSql
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2202
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2203 bool CanBeTranslatedToSql(IBuildContext context, Expression expr, bool canBeCompiled)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2204 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2205 List<Expression> ignoredMembers = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2206
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2207 return null == expr.Find(pi =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2208 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2209 if (ignoredMembers != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2210 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2211 if (pi != ignoredMembers[ignoredMembers.Count - 1])
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2212 throw new InvalidOperationException();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2213
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2214 if (ignoredMembers.Count == 1)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2215 ignoredMembers = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2216 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2217 ignoredMembers.RemoveAt(ignoredMembers.Count - 1);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2218
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2219 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2220 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2221
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2222 switch (pi.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2223 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2224 case ExpressionType.MemberAccess :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2225 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2226 var ma = (MemberExpression)pi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2227 var attr = GetFunctionAttribute(ma.Member);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2228
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2229 if (attr == null && !TypeHelper.IsNullableValueMember(ma.Member))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2230 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2231 if (canBeCompiled)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2232 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2233 var ctx = GetContext(context, pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2234
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2235 if (ctx == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2236 return !CanBeCompiled(pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2237
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2238 if (ctx.IsExpression(pi, 0, RequestFor.Object).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2239 return !CanBeCompiled(pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2240
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2241 ignoredMembers = ma.Expression.GetMembers();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2242 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2243 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2244
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2245 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2246 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2247
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2248 case ExpressionType.Parameter :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2249 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2250 var ctx = GetContext(context, pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2251
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2252 if (ctx == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2253 if (canBeCompiled)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2254 return !CanBeCompiled(pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2255
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2256 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2257 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2258
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2259 case ExpressionType.Call :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2260 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2261 var e = (MethodCallExpression)pi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2262
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2263 if (e.Method.DeclaringType != typeof(Enumerable))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2264 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2265 var attr = GetFunctionAttribute(e.Method);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2266
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2267 if (attr == null && canBeCompiled)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2268 return !CanBeCompiled(pi);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2269 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2270
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2271 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2272 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2273
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2274 case ExpressionType.TypeIs : return canBeCompiled;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2275 case ExpressionType.TypeAs :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2276 case ExpressionType.New : return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2277
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2278 case ExpressionType.NotEqual :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2279 case ExpressionType.Equal :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2280 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2281 var e = (BinaryExpression)pi;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2282
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2283 Expression obj = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2284
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2285 if (e.Left.NodeType == ExpressionType.Constant && ((ConstantExpression)e.Left).Value == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2286 obj = e.Right;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2287 else if (e.Right.NodeType == ExpressionType.Constant && ((ConstantExpression)e.Right).Value == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2288 obj = e.Left;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2289
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2290 if (obj != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2291 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2292 var ctx = GetContext(context, obj);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2293
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2294 if (ctx != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2295 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2296 if (ctx.IsExpression(obj, 0, RequestFor.Table). Result ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2297 ctx.IsExpression(obj, 0, RequestFor.Association).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2298 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2299 ignoredMembers = obj.GetMembers();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2300 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2301 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2302 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2303
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2304 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2305 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2306 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2307
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2308 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2309 });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2310 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2311
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2312 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2313
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2314 #region Helpers
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2315
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2316 public IBuildContext GetContext([JetBrains.Annotations.NotNull] IBuildContext current, Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2317 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2318 var root = expression.GetRootObject();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2319
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2320 for (; current != null; current = current.Parent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2321 if (current.IsExpression(root, 0, RequestFor.Root).Result)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2322 return current;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2323
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2324 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2325 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2326
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2327 SqlFunctionAttribute GetFunctionAttribute(ICustomAttributeProvider member)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2328 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2329 var attrs = member.GetCustomAttributes(typeof(SqlFunctionAttribute), true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2330
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2331 if (attrs.Length == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2332 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2333
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2334 SqlFunctionAttribute attr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2335
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2336 foreach (SqlFunctionAttribute a in attrs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2337 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2338 if (a.SqlProvider == SqlProvider.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2339 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2340 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2341 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2342 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2343
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2344 if (a.SqlProvider == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2345 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2346 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2347
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2348 return attr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2349 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2350
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2351 internal TableFunctionAttribute GetTableFunctionAttribute(ICustomAttributeProvider member)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2352 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2353 var attrs = member.GetCustomAttributes(typeof(TableFunctionAttribute), true);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2354
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2355 if (attrs.Length == 0)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2356 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2357
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2358 TableFunctionAttribute attr = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2359
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2360 foreach (TableFunctionAttribute a in attrs)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2361 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2362 if (a.SqlProvider == SqlProvider.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2363 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2364 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2365 break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2366 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2367
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2368 if (a.SqlProvider == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2369 attr = a;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2370 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2371
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2372 return attr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2373 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2374
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2375 public ISqlExpression Convert(IBuildContext context, ISqlExpression expr)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2376 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2377 SqlProvider.SqlQuery = context.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2378 return SqlProvider.ConvertExpression(expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2379 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2380
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2381 public ISqlPredicate Convert(IBuildContext context, ISqlPredicate predicate)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2382 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2383 SqlProvider.SqlQuery = context.SqlQuery;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2384 return SqlProvider.ConvertPredicate(predicate);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2385 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2386
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2387 public ISqlExpression ConvertTimeSpanMember(IBuildContext context, MemberExpression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2388 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2389 if (expression.Member.DeclaringType == typeof(TimeSpan))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2390 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2391 switch (expression.Expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2392 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2393 case ExpressionType.Subtract :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2394 case ExpressionType.SubtractChecked:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2395
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2396 Sql.DateParts datePart;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2397
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2398 switch (expression.Member.Name)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2399 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2400 case "TotalMilliseconds" : datePart = Sql.DateParts.Millisecond; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2401 case "TotalSeconds" : datePart = Sql.DateParts.Second; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2402 case "TotalMinutes" : datePart = Sql.DateParts.Minute; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2403 case "TotalHours" : datePart = Sql.DateParts.Hour; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2404 case "TotalDays" : datePart = Sql.DateParts.Day; break;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2405 default : return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2406 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2407
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2408 var e = (BinaryExpression)expression.Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2409
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2410 return new SqlFunction(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2411 typeof(int),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2412 "DateDiff",
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2413 new SqlValue(datePart),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2414 ConvertToSql(context, e.Right, false),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2415 ConvertToSql(context, e.Left, false));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2416 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2417 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2418
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2419 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2420 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2421
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2422 internal ISqlExpression ConvertSearchCondition(IBuildContext context, ISqlExpression sqlExpression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2423 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2424 if (sqlExpression is SqlQuery.SearchCondition)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2425 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2426 if (sqlExpression.CanBeNull())
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2427 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2428 var notExpr = new SqlQuery.SearchCondition
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2429 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2430 Conditions = { new SqlQuery.Condition(true, new SqlQuery.Predicate.Expr(sqlExpression, sqlExpression.Precedence)) }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2431 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2432
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2433 return Convert(context, new SqlFunction(sqlExpression.SystemType, "CASE", sqlExpression, new SqlValue(1), notExpr, new SqlValue(0), new SqlValue(null)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2434 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2435
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2436 return Convert(context, new SqlFunction(sqlExpression.SystemType, "CASE", sqlExpression, new SqlValue(1), new SqlValue(0)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2437 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2438
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2439 return sqlExpression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2440 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2441
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2442 public bool ProcessProjection(Dictionary<MemberInfo,Expression> members, Expression expression)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2443 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2444 switch (expression.NodeType)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2445 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2446 // new { ... }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2447 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2448 case ExpressionType.New :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2449 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2450 var expr = (NewExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2451
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2452 // ReSharper disable ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2453 // ReSharper disable HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2454 if (expr.Members == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2455 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2456 // ReSharper restore HeuristicUnreachableCode
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2457 // ReSharper restore ConditionIsAlwaysTrueOrFalse
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2458
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2459 for (var i = 0; i < expr.Members.Count; i++)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2460 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2461 var member = expr.Members[i];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2462
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2463 members.Add(member, expr.Arguments[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2464
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2465 if (member is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2466 members.Add(TypeHelper.GetPropertyByMethod((MethodInfo)member), expr.Arguments[i]);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2467 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2468
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2469 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2470 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2471
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2472 // new MyObject { ... }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2473 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2474 case ExpressionType.MemberInit :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2475 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2476 var expr = (MemberInitExpression)expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2477 var dic = TypeAccessor.GetAccessor(expr.Type)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2478 .Select((m,i) => new { m, i })
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2479 .ToDictionary(_ => _.m.MemberInfo.Name, _ => _.i);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2480
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2481 foreach (var binding in expr.Bindings.Cast<MemberAssignment>().OrderBy(b => dic.ContainsKey(b.Member.Name) ? dic[b.Member.Name] : 1000000))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2482 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2483 members.Add(binding.Member, binding.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2484
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2485 if (binding.Member is MethodInfo)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2486 members.Add(TypeHelper.GetPropertyByMethod((MethodInfo)binding.Member), binding.Expression);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2487 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2488
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2489 return true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2490 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2491
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2492 // .Select(p => everything else)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2493 //
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2494 default :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2495 return false;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2496 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2497 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2498
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2499 public void ReplaceParent(IBuildContext oldParent, IBuildContext newParent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2500 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2501 foreach (var context in Contexts)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2502 if (context != newParent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2503 if (context.Parent == oldParent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2504 context.Parent = newParent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2505 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2506
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2507 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2508 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2509 }