0
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3
|
|
4 namespace BLToolkit.Data.Sql
|
|
5 {
|
|
6 using VisitFunc = Func<IQueryElement,bool>;
|
|
7 using FindFunc = Func<IQueryElement,bool>;
|
|
8 using ConvertFunc = Func<IQueryElement,IQueryElement>;
|
|
9
|
|
10 public class QueryVisitor
|
|
11 {
|
|
12 #region Visit
|
|
13
|
|
14 readonly Dictionary<IQueryElement,IQueryElement> _visitedElements = new Dictionary<IQueryElement, IQueryElement>();
|
|
15 public Dictionary<IQueryElement,IQueryElement> VisitedElements
|
|
16 {
|
|
17 get { return _visitedElements; }
|
|
18 }
|
|
19
|
|
20 bool _all;
|
|
21 Func<IQueryElement,bool> _action1;
|
|
22 Action<IQueryElement> _action2;
|
|
23
|
|
24 public void VisitParentFirst(IQueryElement element, Func<IQueryElement,bool> action)
|
|
25 {
|
|
26 _visitedElements.Clear();
|
|
27 _action1 = action;
|
|
28 Visit1(element);
|
|
29 }
|
|
30
|
|
31 void Visit1(IQueryElement element)
|
|
32 {
|
|
33 if (element == null || _visitedElements.ContainsKey(element))
|
|
34 return;
|
|
35
|
|
36 _visitedElements.Add(element, element);
|
|
37
|
|
38 if (!_action1(element))
|
|
39 return;
|
|
40
|
|
41 switch (element.ElementType)
|
|
42 {
|
|
43 case QueryElementType.SqlFunction:
|
|
44 {
|
|
45 foreach (var p in ((SqlFunction)element).Parameters) Visit1(p);
|
|
46 break;
|
|
47 }
|
|
48
|
|
49 case QueryElementType.SqlExpression:
|
|
50 {
|
|
51 foreach (var v in ((SqlExpression)element).Parameters) Visit1(v);
|
|
52 break;
|
|
53 }
|
|
54
|
|
55 case QueryElementType.SqlBinaryExpression:
|
|
56 {
|
|
57 //var bexpr = (SqlBinaryExpression)element;
|
|
58 Visit1(((SqlBinaryExpression)element).Expr1);
|
|
59 Visit1(((SqlBinaryExpression)element).Expr2);
|
|
60 break;
|
|
61 }
|
|
62
|
|
63 case QueryElementType.SqlTable:
|
|
64 {
|
|
65 var table = (SqlTable)element;
|
|
66
|
|
67 Visit1(table.All);
|
|
68 foreach (var field in table.Fields.Values) Visit1(field);
|
|
69 foreach (var join in table.Joins) Visit1(join);
|
|
70
|
|
71 if (table.TableArguments != null)
|
|
72 foreach (var a in table.TableArguments) Visit1(a);
|
|
73
|
|
74 break;
|
|
75 }
|
|
76
|
|
77 case QueryElementType.Join:
|
|
78 {
|
|
79 foreach (var j in ((Join)element).JoinOns) Visit1(j);
|
|
80 break;
|
|
81 }
|
|
82
|
|
83 case QueryElementType.Column:
|
|
84 {
|
|
85 Visit1(((SqlQuery.Column)element).Expression);
|
|
86 break;
|
|
87 }
|
|
88
|
|
89 case QueryElementType.TableSource:
|
|
90 {
|
|
91 //var table = ((SqlQuery.TableSource)element);
|
|
92
|
|
93 Visit1(((SqlQuery.TableSource)element).Source);
|
|
94 foreach (var j in ((SqlQuery.TableSource)element).Joins) Visit1(j);
|
|
95 break;
|
|
96 }
|
|
97
|
|
98 case QueryElementType.JoinedTable:
|
|
99 {
|
|
100 //var join = (SqlQuery.JoinedTable)element;
|
|
101 Visit1(((SqlQuery.JoinedTable)element).Table);
|
|
102 Visit1(((SqlQuery.JoinedTable)element).Condition);
|
|
103 break;
|
|
104 }
|
|
105
|
|
106 case QueryElementType.SearchCondition:
|
|
107 {
|
|
108 foreach (var c in ((SqlQuery.SearchCondition)element).Conditions) Visit1(c);
|
|
109 break;
|
|
110 }
|
|
111
|
|
112 case QueryElementType.Condition:
|
|
113 {
|
|
114 Visit1(((SqlQuery.Condition)element).Predicate);
|
|
115 break;
|
|
116 }
|
|
117
|
|
118 case QueryElementType.ExprPredicate:
|
|
119 {
|
|
120 Visit1(((SqlQuery.Predicate.Expr)element).Expr1);
|
|
121 break;
|
|
122 }
|
|
123
|
|
124 case QueryElementType.NotExprPredicate:
|
|
125 {
|
|
126 Visit1(((SqlQuery.Predicate.NotExpr)element).Expr1);
|
|
127 break;
|
|
128 }
|
|
129
|
|
130 case QueryElementType.ExprExprPredicate:
|
|
131 {
|
|
132 //var p = ((SqlQuery.Predicate.ExprExpr)element);
|
|
133 Visit1(((SqlQuery.Predicate.ExprExpr)element).Expr1);
|
|
134 Visit1(((SqlQuery.Predicate.ExprExpr)element).Expr2);
|
|
135 break;
|
|
136 }
|
|
137
|
|
138 case QueryElementType.LikePredicate:
|
|
139 {
|
|
140 //var p = ((SqlQuery.Predicate.Like)element);
|
|
141 Visit1(((SqlQuery.Predicate.Like)element).Expr1);
|
|
142 Visit1(((SqlQuery.Predicate.Like)element).Expr2);
|
|
143 Visit1(((SqlQuery.Predicate.Like)element).Escape);
|
|
144 break;
|
|
145 }
|
|
146
|
|
147 case QueryElementType.BetweenPredicate:
|
|
148 {
|
|
149 //var p = (SqlQuery.Predicate.Between)element;
|
|
150 Visit1(((SqlQuery.Predicate.Between)element).Expr1);
|
|
151 Visit1(((SqlQuery.Predicate.Between)element).Expr2);
|
|
152 Visit1(((SqlQuery.Predicate.Between)element).Expr3);
|
|
153 break;
|
|
154 }
|
|
155
|
|
156 case QueryElementType.IsNullPredicate:
|
|
157 {
|
|
158 Visit1(((SqlQuery.Predicate.IsNull)element).Expr1);
|
|
159 break;
|
|
160 }
|
|
161
|
|
162 case QueryElementType.InSubQueryPredicate:
|
|
163 {
|
|
164 //var p = (SqlQuery.Predicate.InSubQuery)element;
|
|
165 Visit1(((SqlQuery.Predicate.InSubQuery)element).Expr1);
|
|
166 Visit1(((SqlQuery.Predicate.InSubQuery)element).SubQuery);
|
|
167 break;
|
|
168 }
|
|
169
|
|
170 case QueryElementType.InListPredicate:
|
|
171 {
|
|
172 //var p = (SqlQuery.Predicate.InList)element;
|
|
173 Visit1(((SqlQuery.Predicate.InList)element).Expr1);
|
|
174 foreach (var value in ((SqlQuery.Predicate.InList)element).Values) Visit1(value);
|
|
175 break;
|
|
176 }
|
|
177
|
|
178 case QueryElementType.FuncLikePredicate:
|
|
179 {
|
|
180 Visit1(((SqlQuery.Predicate.FuncLike)element).Function);
|
|
181 break;
|
|
182 }
|
|
183
|
|
184 case QueryElementType.SetExpression:
|
|
185 {
|
|
186 //var s = (SqlQuery.SetExpression)element;
|
|
187 Visit1(((SqlQuery.SetExpression)element).Column);
|
|
188 Visit1(((SqlQuery.SetExpression)element).Expression);
|
|
189 break;
|
|
190 }
|
|
191
|
|
192 case QueryElementType.InsertClause:
|
|
193 {
|
|
194 //var sc = (SqlQuery.InsertClause)element;
|
|
195
|
|
196 if (((SqlQuery.InsertClause)element).Into != null)
|
|
197 Visit1(((SqlQuery.InsertClause)element).Into);
|
|
198
|
|
199 foreach (var c in ((SqlQuery.InsertClause)element).Items.ToArray()) Visit1(c);
|
|
200 break;
|
|
201 }
|
|
202
|
|
203 case QueryElementType.UpdateClause:
|
|
204 {
|
|
205 //var sc = (SqlQuery.UpdateClause)element;
|
|
206
|
|
207 if (((SqlQuery.UpdateClause)element).Table != null)
|
|
208 Visit1(((SqlQuery.UpdateClause)element).Table);
|
|
209
|
|
210 foreach (var c in ((SqlQuery.UpdateClause)element).Items.ToArray()) Visit1(c);
|
|
211 foreach (var c in ((SqlQuery.UpdateClause)element).Keys. ToArray()) Visit1(c);
|
|
212 break;
|
|
213 }
|
|
214
|
|
215 case QueryElementType.DeleteClause:
|
|
216 {
|
|
217 if (((SqlQuery.DeleteClause)element).Table != null)
|
|
218 Visit1(((SqlQuery.DeleteClause)element).Table);
|
|
219 break;
|
|
220 }
|
|
221
|
|
222 case QueryElementType.SelectClause:
|
|
223 {
|
|
224 //var sc = (SqlQuery.SelectClause)element;
|
|
225 Visit1(((SqlQuery.SelectClause)element).TakeValue);
|
|
226 Visit1(((SqlQuery.SelectClause)element).SkipValue);
|
|
227
|
|
228 foreach (var c in ((SqlQuery.SelectClause)element).Columns.ToArray()) Visit1(c);
|
|
229 break;
|
|
230 }
|
|
231
|
|
232 case QueryElementType.FromClause:
|
|
233 {
|
|
234 foreach (var t in ((SqlQuery.FromClause)element).Tables) Visit1(t);
|
|
235 break;
|
|
236 }
|
|
237
|
|
238 case QueryElementType.WhereClause:
|
|
239 {
|
|
240 Visit1(((SqlQuery.WhereClause)element).SearchCondition);
|
|
241 break;
|
|
242 }
|
|
243
|
|
244 case QueryElementType.GroupByClause:
|
|
245 {
|
|
246 foreach (var i in ((SqlQuery.GroupByClause)element).Items) Visit1(i);
|
|
247 break;
|
|
248 }
|
|
249
|
|
250 case QueryElementType.OrderByClause:
|
|
251 {
|
|
252 foreach (var i in ((SqlQuery.OrderByClause)element).Items) Visit1(i);
|
|
253 break;
|
|
254 }
|
|
255
|
|
256 case QueryElementType.OrderByItem:
|
|
257 {
|
|
258 Visit1(((SqlQuery.OrderByItem)element).Expression);
|
|
259 break;
|
|
260 }
|
|
261
|
|
262 case QueryElementType.Union:
|
|
263 Visit1(((SqlQuery.Union)element).SqlQuery);
|
|
264 break;
|
|
265
|
|
266 case QueryElementType.SqlQuery:
|
|
267 {
|
|
268 if (_all)
|
|
269 {
|
|
270 if (_visitedElements.ContainsKey(element))
|
|
271 return;
|
|
272 _visitedElements.Add(element, element);
|
|
273 }
|
|
274
|
|
275 var q = (SqlQuery)element;
|
|
276
|
|
277 switch (q.QueryType)
|
|
278 {
|
|
279 case QueryType.InsertOrUpdate :
|
|
280 Visit1(q.Insert);
|
|
281 Visit1(q.Update);
|
|
282
|
|
283 if (q.From.Tables.Count == 0)
|
|
284 break;
|
|
285
|
|
286 goto default;
|
|
287
|
|
288 case QueryType.Update :
|
|
289 Visit1(q.Update);
|
|
290 break;
|
|
291
|
|
292 case QueryType.Delete :
|
|
293 Visit1(q.Delete);
|
|
294 Visit1(q.Select);
|
|
295 break;
|
|
296
|
|
297 case QueryType.Insert :
|
|
298 Visit1(q.Insert);
|
|
299
|
|
300 if (q.From.Tables.Count != 0)
|
|
301 Visit1(q.Select);
|
|
302
|
|
303 break;
|
|
304
|
|
305 default :
|
|
306 Visit1(q.Select);
|
|
307 break;
|
|
308 }
|
|
309
|
|
310 Visit1(q.From);
|
|
311 Visit1(q.Where);
|
|
312 Visit1(q.GroupBy);
|
|
313 Visit1(q.Having);
|
|
314 Visit1(q.OrderBy);
|
|
315
|
|
316 if (q.HasUnion)
|
|
317 {
|
|
318 foreach (var i in q.Unions)
|
|
319 {
|
|
320 if (i.SqlQuery == q)
|
|
321 throw new InvalidOperationException();
|
|
322
|
|
323 Visit1(i);
|
|
324 }
|
|
325 }
|
|
326
|
|
327 break;
|
|
328 }
|
|
329 }
|
|
330 }
|
|
331
|
|
332 public void Visit(IQueryElement element, Action<IQueryElement> action)
|
|
333 {
|
|
334 _visitedElements.Clear();
|
|
335 _all = false;
|
|
336 _action2 = action;
|
|
337 Visit2(element);
|
|
338 }
|
|
339
|
|
340 public void VisitAll(IQueryElement element, Action<IQueryElement> action)
|
|
341 {
|
|
342 _visitedElements.Clear();
|
|
343 _all = true;
|
|
344 _action2 = action;
|
|
345 Visit2(element);
|
|
346 }
|
|
347
|
|
348 void Visit2(IQueryElement element)
|
|
349 {
|
|
350 if (element == null || !_all && _visitedElements.ContainsKey(element))
|
|
351 return;
|
|
352
|
|
353 switch (element.ElementType)
|
|
354 {
|
|
355 case QueryElementType.SqlFunction:
|
|
356 {
|
|
357 foreach (var p in ((SqlFunction)element).Parameters) Visit2(p);
|
|
358 break;
|
|
359 }
|
|
360
|
|
361 case QueryElementType.SqlExpression:
|
|
362 {
|
|
363 foreach (var v in ((SqlExpression)element).Parameters) Visit2(v);
|
|
364 break;
|
|
365 }
|
|
366
|
|
367 case QueryElementType.SqlBinaryExpression:
|
|
368 {
|
|
369 //var bexpr = (SqlBinaryExpression)element;
|
|
370 Visit2(((SqlBinaryExpression)element).Expr1);
|
|
371 Visit2(((SqlBinaryExpression)element).Expr2);
|
|
372 break;
|
|
373 }
|
|
374
|
|
375 case QueryElementType.SqlTable:
|
|
376 {
|
|
377 var table = (SqlTable)element;
|
|
378
|
|
379 Visit2(table.All);
|
|
380 foreach (var field in table.Fields.Values) Visit2(field);
|
|
381 foreach (var join in table.Joins) Visit2(join);
|
|
382
|
|
383 if (table.TableArguments != null)
|
|
384 foreach (var a in table.TableArguments) Visit2(a);
|
|
385
|
|
386 break;
|
|
387 }
|
|
388
|
|
389 case QueryElementType.Join:
|
|
390 {
|
|
391 foreach (var j in ((Join)element).JoinOns) Visit2(j);
|
|
392 break;
|
|
393 }
|
|
394
|
|
395 case QueryElementType.Column:
|
|
396 {
|
|
397 Visit2(((SqlQuery.Column)element).Expression);
|
|
398 break;
|
|
399 }
|
|
400
|
|
401 case QueryElementType.TableSource:
|
|
402 {
|
|
403 //var table = ((SqlQuery.TableSource)element);
|
|
404
|
|
405 Visit2(((SqlQuery.TableSource)element).Source);
|
|
406 foreach (var j in ((SqlQuery.TableSource)element).Joins) Visit2(j);
|
|
407 break;
|
|
408 }
|
|
409
|
|
410 case QueryElementType.JoinedTable:
|
|
411 {
|
|
412 //var join = (SqlQuery.JoinedTable)element;
|
|
413 Visit2(((SqlQuery.JoinedTable)element).Table);
|
|
414 Visit2(((SqlQuery.JoinedTable)element).Condition);
|
|
415 break;
|
|
416 }
|
|
417
|
|
418 case QueryElementType.SearchCondition:
|
|
419 {
|
|
420 foreach (var c in ((SqlQuery.SearchCondition)element).Conditions) Visit2(c);
|
|
421 break;
|
|
422 }
|
|
423
|
|
424 case QueryElementType.Condition:
|
|
425 {
|
|
426 Visit2(((SqlQuery.Condition)element).Predicate);
|
|
427 break;
|
|
428 }
|
|
429
|
|
430 case QueryElementType.ExprPredicate:
|
|
431 {
|
|
432 Visit2(((SqlQuery.Predicate.Expr)element).Expr1);
|
|
433 break;
|
|
434 }
|
|
435
|
|
436 case QueryElementType.NotExprPredicate:
|
|
437 {
|
|
438 Visit2(((SqlQuery.Predicate.NotExpr)element).Expr1);
|
|
439 break;
|
|
440 }
|
|
441
|
|
442 case QueryElementType.ExprExprPredicate:
|
|
443 {
|
|
444 //var p = ((SqlQuery.Predicate.ExprExpr)element);
|
|
445 Visit2(((SqlQuery.Predicate.ExprExpr)element).Expr1);
|
|
446 Visit2(((SqlQuery.Predicate.ExprExpr)element).Expr2);
|
|
447 break;
|
|
448 }
|
|
449
|
|
450 case QueryElementType.LikePredicate:
|
|
451 {
|
|
452 //var p = ((SqlQuery.Predicate.Like)element);
|
|
453 Visit2(((SqlQuery.Predicate.Like)element).Expr1);
|
|
454 Visit2(((SqlQuery.Predicate.Like)element).Expr2);
|
|
455 Visit2(((SqlQuery.Predicate.Like)element).Escape);
|
|
456 break;
|
|
457 }
|
|
458
|
|
459 case QueryElementType.BetweenPredicate:
|
|
460 {
|
|
461 //var p = (SqlQuery.Predicate.Between)element;
|
|
462 Visit2(((SqlQuery.Predicate.Between)element).Expr1);
|
|
463 Visit2(((SqlQuery.Predicate.Between)element).Expr2);
|
|
464 Visit2(((SqlQuery.Predicate.Between)element).Expr3);
|
|
465 break;
|
|
466 }
|
|
467
|
|
468 case QueryElementType.IsNullPredicate:
|
|
469 {
|
|
470 Visit2(((SqlQuery.Predicate.IsNull)element).Expr1);
|
|
471 break;
|
|
472 }
|
|
473
|
|
474 case QueryElementType.InSubQueryPredicate:
|
|
475 {
|
|
476 //var p = (SqlQuery.Predicate.InSubQuery)element;
|
|
477 Visit2(((SqlQuery.Predicate.InSubQuery)element).Expr1);
|
|
478 Visit2(((SqlQuery.Predicate.InSubQuery)element).SubQuery);
|
|
479 break;
|
|
480 }
|
|
481
|
|
482 case QueryElementType.InListPredicate:
|
|
483 {
|
|
484 //var p = (SqlQuery.Predicate.InList)element;
|
|
485 Visit2(((SqlQuery.Predicate.InList)element).Expr1);
|
|
486 foreach (var value in ((SqlQuery.Predicate.InList)element).Values) Visit2(value);
|
|
487 break;
|
|
488 }
|
|
489
|
|
490 case QueryElementType.FuncLikePredicate:
|
|
491 {
|
|
492 Visit2(((SqlQuery.Predicate.FuncLike)element).Function);
|
|
493 break;
|
|
494 }
|
|
495
|
|
496 case QueryElementType.SetExpression:
|
|
497 {
|
|
498 //var s = (SqlQuery.SetExpression)element;
|
|
499 Visit2(((SqlQuery.SetExpression)element).Column);
|
|
500 Visit2(((SqlQuery.SetExpression)element).Expression);
|
|
501 break;
|
|
502 }
|
|
503
|
|
504 case QueryElementType.InsertClause:
|
|
505 {
|
|
506 //var sc = (SqlQuery.InsertClause)element;
|
|
507
|
|
508 if (((SqlQuery.InsertClause)element).Into != null)
|
|
509 Visit2(((SqlQuery.InsertClause)element).Into);
|
|
510
|
|
511 foreach (var c in ((SqlQuery.InsertClause)element).Items.ToArray()) Visit2(c);
|
|
512 break;
|
|
513 }
|
|
514
|
|
515 case QueryElementType.UpdateClause:
|
|
516 {
|
|
517 //var sc = (SqlQuery.UpdateClause)element;
|
|
518
|
|
519 if (((SqlQuery.UpdateClause)element).Table != null)
|
|
520 Visit2(((SqlQuery.UpdateClause)element).Table);
|
|
521
|
|
522 foreach (var c in ((SqlQuery.UpdateClause)element).Items.ToArray()) Visit2(c);
|
|
523 foreach (var c in ((SqlQuery.UpdateClause)element).Keys. ToArray()) Visit2(c);
|
|
524 break;
|
|
525 }
|
|
526
|
|
527 case QueryElementType.DeleteClause:
|
|
528 {
|
|
529 if (((SqlQuery.DeleteClause)element).Table != null)
|
|
530 Visit2(((SqlQuery.DeleteClause)element).Table);
|
|
531 break;
|
|
532 }
|
|
533
|
|
534 case QueryElementType.SelectClause:
|
|
535 {
|
|
536 //var sc = (SqlQuery.SelectClause)element;
|
|
537 Visit2(((SqlQuery.SelectClause)element).TakeValue);
|
|
538 Visit2(((SqlQuery.SelectClause)element).SkipValue);
|
|
539
|
|
540 foreach (var c in ((SqlQuery.SelectClause)element).Columns.ToArray()) Visit2(c);
|
|
541 break;
|
|
542 }
|
|
543
|
|
544 case QueryElementType.FromClause:
|
|
545 {
|
|
546 foreach (var t in ((SqlQuery.FromClause)element).Tables) Visit2(t);
|
|
547 break;
|
|
548 }
|
|
549
|
|
550 case QueryElementType.WhereClause:
|
|
551 {
|
|
552 Visit2(((SqlQuery.WhereClause)element).SearchCondition);
|
|
553 break;
|
|
554 }
|
|
555
|
|
556 case QueryElementType.GroupByClause:
|
|
557 {
|
|
558 foreach (var i in ((SqlQuery.GroupByClause)element).Items) Visit2(i);
|
|
559 break;
|
|
560 }
|
|
561
|
|
562 case QueryElementType.OrderByClause:
|
|
563 {
|
|
564 foreach (var i in ((SqlQuery.OrderByClause)element).Items) Visit2(i);
|
|
565 break;
|
|
566 }
|
|
567
|
|
568 case QueryElementType.OrderByItem:
|
|
569 {
|
|
570 Visit2(((SqlQuery.OrderByItem)element).Expression);
|
|
571 break;
|
|
572 }
|
|
573
|
|
574 case QueryElementType.Union:
|
|
575 Visit2(((SqlQuery.Union)element).SqlQuery);
|
|
576 break;
|
|
577
|
|
578 case QueryElementType.SqlQuery:
|
|
579 {
|
|
580 if (_all)
|
|
581 {
|
|
582 if (_visitedElements.ContainsKey(element))
|
|
583 return;
|
|
584 _visitedElements.Add(element, element);
|
|
585 }
|
|
586
|
|
587 var q = (SqlQuery)element;
|
|
588
|
|
589 switch (q.QueryType)
|
|
590 {
|
|
591 case QueryType.InsertOrUpdate :
|
|
592 Visit2(q.Insert);
|
|
593 Visit2(q.Update);
|
|
594
|
|
595 if (q.From.Tables.Count == 0)
|
|
596 break;
|
|
597
|
|
598 goto default;
|
|
599
|
|
600 case QueryType.Update :
|
|
601 Visit2(q.Update);
|
|
602 break;
|
|
603
|
|
604 case QueryType.Delete :
|
|
605 Visit2(q.Delete);
|
|
606 Visit2(q.Select);
|
|
607 break;
|
|
608
|
|
609 case QueryType.Insert :
|
|
610 Visit2(q.Insert);
|
|
611
|
|
612 if (q.From.Tables.Count != 0)
|
|
613 Visit2(q.Select);
|
|
614
|
|
615 break;
|
|
616
|
|
617 default :
|
|
618 Visit2(q.Select);
|
|
619 break;
|
|
620 }
|
|
621
|
|
622 // Visit2(q.From);
|
|
623 //
|
|
624 if (q.From != null && (_all || !_visitedElements.ContainsKey(q.From)))
|
|
625 {
|
|
626 foreach (var t in q.From.Tables)
|
|
627 {
|
|
628 //Visit2(t);
|
|
629 //
|
|
630 if (t != null && (_all || !_visitedElements.ContainsKey(t)))
|
|
631 {
|
|
632 Visit2(t.Source);
|
|
633
|
|
634 foreach (var j in t.Joins)
|
|
635 Visit2(j);
|
|
636
|
|
637 _action2(t);
|
|
638 if (!_all)
|
|
639 _visitedElements.Add(t, t);
|
|
640 }
|
|
641 }
|
|
642 _action2(q.From);
|
|
643 if (!_all)
|
|
644 _visitedElements.Add(q.From, q.From);
|
|
645 }
|
|
646
|
|
647 Visit2(q.Where);
|
|
648 Visit2(q.GroupBy);
|
|
649 Visit2(q.Having);
|
|
650 Visit2(q.OrderBy);
|
|
651
|
|
652 if (q.HasUnion)
|
|
653 {
|
|
654 foreach (var i in q.Unions)
|
|
655 {
|
|
656 if (i.SqlQuery == q)
|
|
657 throw new InvalidOperationException();
|
|
658
|
|
659 Visit2(i);
|
|
660 }
|
|
661 }
|
|
662
|
|
663 break;
|
|
664 }
|
|
665 }
|
|
666
|
|
667 _action2(element);
|
|
668 if (!_all)
|
|
669 _visitedElements.Add(element, element);
|
|
670 }
|
|
671
|
|
672 #endregion
|
|
673
|
|
674 #region Find
|
|
675
|
|
676 IQueryElement Find<T>(IEnumerable<T> arr, FindFunc find)
|
|
677 where T : class, IQueryElement
|
|
678 {
|
|
679 if (arr == null)
|
|
680 return null;
|
|
681
|
|
682 foreach (var item in arr)
|
|
683 {
|
|
684 var e = Find(item, find);
|
|
685 if (e != null)
|
|
686 return e;
|
|
687 }
|
|
688
|
|
689 return null;
|
|
690 }
|
|
691
|
|
692 public IQueryElement Find(IQueryElement element, FindFunc find)
|
|
693 {
|
|
694 if (element == null || find(element))
|
|
695 return element;
|
|
696
|
|
697 switch (element.ElementType)
|
|
698 {
|
|
699 case QueryElementType.SqlFunction : return Find(((SqlFunction) element).Parameters, find);
|
|
700 case QueryElementType.SqlExpression : return Find(((SqlExpression) element).Parameters, find);
|
|
701 case QueryElementType.Join : return Find(((Join) element).JoinOns, find);
|
|
702 case QueryElementType.Column : return Find(((SqlQuery.Column) element).Expression, find);
|
|
703 case QueryElementType.SearchCondition : return Find(((SqlQuery.SearchCondition) element).Conditions, find);
|
|
704 case QueryElementType.Condition : return Find(((SqlQuery.Condition) element).Predicate, find);
|
|
705 case QueryElementType.ExprPredicate : return Find(((SqlQuery.Predicate.Expr) element).Expr1, find);
|
|
706 case QueryElementType.NotExprPredicate : return Find(((SqlQuery.Predicate.NotExpr) element).Expr1, find);
|
|
707 case QueryElementType.IsNullPredicate : return Find(((SqlQuery.Predicate.IsNull) element).Expr1, find);
|
|
708 case QueryElementType.FromClause : return Find(((SqlQuery.FromClause) element).Tables, find);
|
|
709 case QueryElementType.WhereClause : return Find(((SqlQuery.WhereClause) element).SearchCondition, find);
|
|
710 case QueryElementType.GroupByClause : return Find(((SqlQuery.GroupByClause) element).Items, find);
|
|
711 case QueryElementType.OrderByClause : return Find(((SqlQuery.OrderByClause) element).Items, find);
|
|
712 case QueryElementType.OrderByItem : return Find(((SqlQuery.OrderByItem) element).Expression, find);
|
|
713 case QueryElementType.Union : return Find(((SqlQuery.Union) element).SqlQuery, find);
|
|
714 case QueryElementType.FuncLikePredicate : return Find(((SqlQuery.Predicate.FuncLike)element).Function, find);
|
|
715
|
|
716 case QueryElementType.SqlBinaryExpression:
|
|
717 {
|
|
718 var bexpr = (SqlBinaryExpression)element;
|
|
719 return
|
|
720 Find(bexpr.Expr1, find) ??
|
|
721 Find(bexpr.Expr2, find);
|
|
722 }
|
|
723
|
|
724 case QueryElementType.SqlTable:
|
|
725 {
|
|
726 var table = (SqlTable)element;
|
|
727 return
|
|
728 Find(table.All, find) ??
|
|
729 Find(table.Fields.Values, find) ??
|
|
730 Find(table.Joins, find) ??
|
|
731 Find(table.TableArguments, find);
|
|
732 }
|
|
733
|
|
734 case QueryElementType.TableSource:
|
|
735 {
|
|
736 var table = (SqlQuery.TableSource)element;
|
|
737 return
|
|
738 Find(table.Source, find) ??
|
|
739 Find(table.Joins, find);
|
|
740 }
|
|
741
|
|
742 case QueryElementType.JoinedTable:
|
|
743 {
|
|
744 var join = (SqlQuery.JoinedTable)element;
|
|
745 return
|
|
746 Find(join.Table, find) ??
|
|
747 Find(join.Condition, find);
|
|
748 }
|
|
749
|
|
750 case QueryElementType.ExprExprPredicate:
|
|
751 {
|
|
752 var p = (SqlQuery.Predicate.ExprExpr)element;
|
|
753 return
|
|
754 Find(p.Expr1, find) ??
|
|
755 Find(p.Expr2, find);
|
|
756 }
|
|
757
|
|
758 case QueryElementType.LikePredicate:
|
|
759 {
|
|
760 var p = (SqlQuery.Predicate.Like)element;
|
|
761 return
|
|
762 Find(p.Expr1, find) ??
|
|
763 Find(p.Expr2, find) ??
|
|
764 Find(p.Escape, find);
|
|
765 }
|
|
766
|
|
767 case QueryElementType.BetweenPredicate:
|
|
768 {
|
|
769 var p = (SqlQuery.Predicate.Between)element;
|
|
770 return
|
|
771 Find(p.Expr1, find) ??
|
|
772 Find(p.Expr2, find) ??
|
|
773 Find(p.Expr3, find);
|
|
774 }
|
|
775
|
|
776 case QueryElementType.InSubQueryPredicate:
|
|
777 {
|
|
778 var p = (SqlQuery.Predicate.InSubQuery)element;
|
|
779 return
|
|
780 Find(p.Expr1, find) ??
|
|
781 Find(p.SubQuery, find);
|
|
782 }
|
|
783
|
|
784 case QueryElementType.InListPredicate:
|
|
785 {
|
|
786 var p = (SqlQuery.Predicate.InList)element;
|
|
787 return
|
|
788 Find(p.Expr1, find) ??
|
|
789 Find(p.Values, find);
|
|
790 }
|
|
791
|
|
792 case QueryElementType.SetExpression:
|
|
793 {
|
|
794 var s = (SqlQuery.SetExpression)element;
|
|
795 return
|
|
796 Find(s.Column, find) ??
|
|
797 Find(s.Expression, find);
|
|
798 }
|
|
799
|
|
800 case QueryElementType.InsertClause:
|
|
801 {
|
|
802 var sc = (SqlQuery.InsertClause)element;
|
|
803 return
|
|
804 Find(sc.Into, find) ??
|
|
805 Find(sc.Items, find);
|
|
806 }
|
|
807
|
|
808 case QueryElementType.UpdateClause:
|
|
809 {
|
|
810 var sc = (SqlQuery.UpdateClause)element;
|
|
811 return
|
|
812 Find(sc.Table, find) ??
|
|
813 Find(sc.Items, find) ??
|
|
814 Find(sc.Keys, find);
|
|
815 }
|
|
816
|
|
817 case QueryElementType.DeleteClause:
|
|
818 {
|
|
819 var sc = (SqlQuery.DeleteClause)element;
|
|
820 return Find(sc.Table, find);
|
|
821 }
|
|
822
|
|
823 case QueryElementType.SelectClause:
|
|
824 {
|
|
825 var sc = (SqlQuery.SelectClause)element;
|
|
826 return
|
|
827 Find(sc.TakeValue, find) ??
|
|
828 Find(sc.SkipValue, find) ??
|
|
829 Find(sc.Columns, find);
|
|
830 }
|
|
831
|
|
832 case QueryElementType.SqlQuery:
|
|
833 {
|
|
834 var q = (SqlQuery)element;
|
|
835 return
|
|
836 Find(q.Select, find) ??
|
|
837 (q.IsInsert ? Find(q.Insert, find) : null) ??
|
|
838 (q.IsUpdate ? Find(q.Update, find) : null) ??
|
|
839 Find(q.From, find) ??
|
|
840 Find(q.Where, find) ??
|
|
841 Find(q.GroupBy, find) ??
|
|
842 Find(q.Having, find) ??
|
|
843 Find(q.OrderBy, find) ??
|
|
844 (q.HasUnion ? Find(q.Unions, find) : null);
|
|
845 }
|
|
846 }
|
|
847
|
|
848 return null;
|
|
849 }
|
|
850
|
|
851 #endregion
|
|
852
|
|
853 #region Convert
|
|
854
|
|
855 public T Convert<T>(T element, ConvertFunc action)
|
|
856 where T : class, IQueryElement
|
|
857 {
|
|
858 _visitedElements.Clear();
|
|
859 return (T)ConvertInternal(element, action) ?? element;
|
|
860 }
|
|
861
|
|
862 IQueryElement ConvertInternal(IQueryElement element, ConvertFunc action)
|
|
863 {
|
|
864 if (element == null)
|
|
865 return null;
|
|
866
|
|
867 IQueryElement newElement;
|
|
868
|
|
869 if (_visitedElements.TryGetValue(element, out newElement))
|
|
870 return newElement;
|
|
871
|
|
872 switch (element.ElementType)
|
|
873 {
|
|
874 case QueryElementType.SqlFunction:
|
|
875 {
|
|
876 var func = (SqlFunction)element;
|
|
877 var parms = Convert(func.Parameters, action);
|
|
878
|
|
879 if (parms != null && !ReferenceEquals(parms, func.Parameters))
|
|
880 newElement = new SqlFunction(func.SystemType, func.Name, func.Precedence, parms);
|
|
881
|
|
882 break;
|
|
883 }
|
|
884
|
|
885 case QueryElementType.SqlExpression:
|
|
886 {
|
|
887 var expr = (SqlExpression)element;
|
|
888 var parameter = Convert(expr.Parameters, action);
|
|
889
|
|
890 if (parameter != null && !ReferenceEquals(parameter, expr.Parameters))
|
|
891 newElement = new SqlExpression(expr.SystemType, expr.Expr, expr.Precedence, parameter);
|
|
892
|
|
893 break;
|
|
894 }
|
|
895
|
|
896 case QueryElementType.SqlBinaryExpression:
|
|
897 {
|
|
898 var bexpr = (SqlBinaryExpression)element;
|
|
899 var expr1 = (ISqlExpression)ConvertInternal(bexpr.Expr1, action);
|
|
900 var expr2 = (ISqlExpression)ConvertInternal(bexpr.Expr2, action);
|
|
901
|
|
902 if (expr1 != null && !ReferenceEquals(expr1, bexpr.Expr1) ||
|
|
903 expr2 != null && !ReferenceEquals(expr2, bexpr.Expr2))
|
|
904 newElement = new SqlBinaryExpression(bexpr.SystemType, expr1 ?? bexpr.Expr1, bexpr.Operation, expr2 ?? bexpr.Expr2, bexpr.Precedence);
|
|
905
|
|
906 break;
|
|
907 }
|
|
908
|
|
909 case QueryElementType.SqlTable:
|
|
910 {
|
|
911 var table = (SqlTable)element;
|
|
912 var fields1 = ToArray(table.Fields);
|
|
913 var fields2 = Convert(fields1, action, f => new SqlField(f));
|
|
914 var joins = Convert(table.Joins, action, j => j.Clone());
|
|
915 var targs = table.TableArguments == null ? null : Convert(table.TableArguments, action);
|
|
916
|
|
917 var fe = fields2 == null || ReferenceEquals(fields1, fields2);
|
|
918 var je = joins == null || ReferenceEquals(table.Joins, joins);
|
|
919 var ta = ReferenceEquals(table.TableArguments, targs);
|
|
920
|
|
921 if (!fe || !je || !ta)
|
|
922 {
|
|
923 if (fe)
|
|
924 {
|
|
925 fields2 = fields1;
|
|
926
|
|
927 for (var i = 0; i < fields2.Length; i++)
|
|
928 {
|
|
929 var field = fields2[i];
|
|
930
|
|
931 fields2[i] = new SqlField(field);
|
|
932
|
|
933 _visitedElements[field] = fields2[i];
|
|
934 }
|
|
935 }
|
|
936
|
|
937 newElement = new SqlTable(table, fields2, joins ?? table.Joins, targs ?? table.TableArguments);
|
|
938
|
|
939 _visitedElements[((SqlTable)newElement).All] = table.All;
|
|
940 }
|
|
941
|
|
942 break;
|
|
943 }
|
|
944
|
|
945 case QueryElementType.Join:
|
|
946 {
|
|
947 var join = (Join)element;
|
|
948 var ons = Convert(join.JoinOns, action);
|
|
949
|
|
950 if (ons != null && !ReferenceEquals(join.JoinOns, ons))
|
|
951 newElement = new Join(join.TableName, join.Alias, ons);
|
|
952
|
|
953 break;
|
|
954 }
|
|
955
|
|
956 case QueryElementType.Column:
|
|
957 {
|
|
958 var col = (SqlQuery.Column)element;
|
|
959 var expr = (ISqlExpression)ConvertInternal(col.Expression, action);
|
|
960
|
|
961 IQueryElement parent;
|
|
962 _visitedElements.TryGetValue(col.Parent, out parent);
|
|
963
|
|
964 if (parent != null || expr != null && !ReferenceEquals(expr, col.Expression))
|
|
965 newElement = new SqlQuery.Column(parent == null ? col.Parent : (SqlQuery)parent, expr ?? col.Expression, col._alias);
|
|
966
|
|
967 break;
|
|
968 }
|
|
969
|
|
970 case QueryElementType.TableSource:
|
|
971 {
|
|
972 var table = (SqlQuery.TableSource)element;
|
|
973 var source = (ISqlTableSource)ConvertInternal(table.Source, action);
|
|
974 var joins = Convert(table.Joins, action);
|
|
975
|
|
976 if (source != null && !ReferenceEquals(source, table.Source) ||
|
|
977 joins != null && !ReferenceEquals(table.Joins, joins))
|
|
978 newElement = new SqlQuery.TableSource(source ?? table.Source, table._alias, joins ?? table.Joins);
|
|
979
|
|
980 break;
|
|
981 }
|
|
982
|
|
983 case QueryElementType.JoinedTable:
|
|
984 {
|
|
985 var join = (SqlQuery.JoinedTable)element;
|
|
986 var table = (SqlQuery.TableSource) ConvertInternal(join.Table, action);
|
|
987 var cond = (SqlQuery.SearchCondition)ConvertInternal(join.Condition, action);
|
|
988
|
|
989 if (table != null && !ReferenceEquals(table, join.Table) ||
|
|
990 cond != null && !ReferenceEquals(cond, join.Condition))
|
|
991 newElement = new SqlQuery.JoinedTable(join.JoinType, table ?? join.Table, join.IsWeak, cond ?? join.Condition);
|
|
992
|
|
993 break;
|
|
994 }
|
|
995
|
|
996 case QueryElementType.SearchCondition:
|
|
997 {
|
|
998 var sc = (SqlQuery.SearchCondition)element;
|
|
999 var conds = Convert(sc.Conditions, action);
|
|
1000
|
|
1001 if (conds != null && !ReferenceEquals(sc.Conditions, conds))
|
|
1002 newElement = new SqlQuery.SearchCondition(conds);
|
|
1003
|
|
1004 break;
|
|
1005 }
|
|
1006
|
|
1007 case QueryElementType.Condition:
|
|
1008 {
|
|
1009 var c = (SqlQuery.Condition)element;
|
|
1010 var p = (ISqlPredicate)ConvertInternal(c.Predicate, action);
|
|
1011
|
|
1012 if (p != null && !ReferenceEquals(c.Predicate, p))
|
|
1013 newElement = new SqlQuery.Condition(c.IsNot, p, c.IsOr);
|
|
1014
|
|
1015 break;
|
|
1016 }
|
|
1017
|
|
1018 case QueryElementType.ExprPredicate:
|
|
1019 {
|
|
1020 var p = (SqlQuery.Predicate.Expr)element;
|
|
1021 var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1022
|
|
1023 if (e != null && !ReferenceEquals(p.Expr1, e))
|
|
1024 newElement = new SqlQuery.Predicate.Expr(e, p.Precedence);
|
|
1025
|
|
1026 break;
|
|
1027 }
|
|
1028
|
|
1029 case QueryElementType.NotExprPredicate:
|
|
1030 {
|
|
1031 var p = (SqlQuery.Predicate.NotExpr)element;
|
|
1032 var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1033
|
|
1034 if (e != null && !ReferenceEquals(p.Expr1, e))
|
|
1035 newElement = new SqlQuery.Predicate.NotExpr(e, p.IsNot, p.Precedence);
|
|
1036
|
|
1037 break;
|
|
1038 }
|
|
1039
|
|
1040 case QueryElementType.ExprExprPredicate:
|
|
1041 {
|
|
1042 var p = (SqlQuery.Predicate.ExprExpr)element;
|
|
1043 var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1044 var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);
|
|
1045
|
|
1046 if (e1 != null && !ReferenceEquals(p.Expr1, e1) || e2 != null && !ReferenceEquals(p.Expr2, e2))
|
|
1047 newElement = new SqlQuery.Predicate.ExprExpr(e1 ?? p.Expr1, p.Operator, e2 ?? p.Expr2);
|
|
1048
|
|
1049 break;
|
|
1050 }
|
|
1051
|
|
1052 case QueryElementType.LikePredicate:
|
|
1053 {
|
|
1054 var p = (SqlQuery.Predicate.Like)element;
|
|
1055 var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1056 var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);
|
|
1057 var es = (ISqlExpression)ConvertInternal(p.Escape, action);
|
|
1058
|
|
1059 if (e1 != null && !ReferenceEquals(p.Expr1, e1) ||
|
|
1060 e2 != null && !ReferenceEquals(p.Expr2, e2) ||
|
|
1061 es != null && !ReferenceEquals(p.Escape, es))
|
|
1062 newElement = new SqlQuery.Predicate.Like(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, es ?? p.Escape);
|
|
1063
|
|
1064 break;
|
|
1065 }
|
|
1066
|
|
1067 case QueryElementType.BetweenPredicate:
|
|
1068 {
|
|
1069 var p = (SqlQuery.Predicate.Between)element;
|
|
1070 var e1 = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1071 var e2 = (ISqlExpression)ConvertInternal(p.Expr2, action);
|
|
1072 var e3 = (ISqlExpression)ConvertInternal(p.Expr3, action);
|
|
1073
|
|
1074 if (e1 != null && !ReferenceEquals(p.Expr1, e1) ||
|
|
1075 e2 != null && !ReferenceEquals(p.Expr2, e2) ||
|
|
1076 e3 != null && !ReferenceEquals(p.Expr3, e3))
|
|
1077 newElement = new SqlQuery.Predicate.Between(e1 ?? p.Expr1, p.IsNot, e2 ?? p.Expr2, e3 ?? p.Expr3);
|
|
1078
|
|
1079 break;
|
|
1080 }
|
|
1081
|
|
1082 case QueryElementType.IsNullPredicate:
|
|
1083 {
|
|
1084 var p = (SqlQuery.Predicate.IsNull)element;
|
|
1085 var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1086
|
|
1087 if (e != null && !ReferenceEquals(p.Expr1, e))
|
|
1088 newElement = new SqlQuery.Predicate.IsNull(e, p.IsNot);
|
|
1089
|
|
1090 break;
|
|
1091 }
|
|
1092
|
|
1093 case QueryElementType.InSubQueryPredicate:
|
|
1094 {
|
|
1095 var p = (SqlQuery.Predicate.InSubQuery)element;
|
|
1096 var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1097 var q = (SqlQuery)ConvertInternal(p.SubQuery, action);
|
|
1098
|
|
1099 if (e != null && !ReferenceEquals(p.Expr1, e) || q != null && !ReferenceEquals(p.SubQuery, q))
|
|
1100 newElement = new SqlQuery.Predicate.InSubQuery(e ?? p.Expr1, p.IsNot, q ?? p.SubQuery);
|
|
1101
|
|
1102 break;
|
|
1103 }
|
|
1104
|
|
1105 case QueryElementType.InListPredicate:
|
|
1106 {
|
|
1107 var p = (SqlQuery.Predicate.InList)element;
|
|
1108 var e = (ISqlExpression)ConvertInternal(p.Expr1, action);
|
|
1109 var v = Convert(p.Values, action);
|
|
1110
|
|
1111 if (e != null && !ReferenceEquals(p.Expr1, e) || v != null && !ReferenceEquals(p.Values, v))
|
|
1112 newElement = new SqlQuery.Predicate.InList(e ?? p.Expr1, p.IsNot, v ?? p.Values);
|
|
1113
|
|
1114 break;
|
|
1115 }
|
|
1116
|
|
1117 case QueryElementType.FuncLikePredicate:
|
|
1118 {
|
|
1119 var p = (SqlQuery.Predicate.FuncLike)element;
|
|
1120 var f = (SqlFunction)ConvertInternal(p.Function, action);
|
|
1121
|
|
1122 if (f != null && !ReferenceEquals(p.Function, f))
|
|
1123 newElement = new SqlQuery.Predicate.FuncLike(f);
|
|
1124
|
|
1125 break;
|
|
1126 }
|
|
1127
|
|
1128 case QueryElementType.SetExpression:
|
|
1129 {
|
|
1130 var s = (SqlQuery.SetExpression)element;
|
|
1131 var c = (ISqlExpression)ConvertInternal(s.Column, action);
|
|
1132 var e = (ISqlExpression)ConvertInternal(s.Expression, action);
|
|
1133
|
|
1134 if (c != null && !ReferenceEquals(s.Column, c) || e != null && !ReferenceEquals(s.Expression, e))
|
|
1135 newElement = new SqlQuery.SetExpression(c ?? s.Column, e ?? s.Expression);
|
|
1136
|
|
1137 break;
|
|
1138 }
|
|
1139
|
|
1140 case QueryElementType.InsertClause:
|
|
1141 {
|
|
1142 var s = (SqlQuery.InsertClause)element;
|
|
1143 var t = s.Into != null ? (SqlTable)ConvertInternal(s.Into, action) : null;
|
|
1144 var i = Convert(s.Items, action);
|
|
1145
|
|
1146 if (t != null && !ReferenceEquals(s.Into, t) || i != null && !ReferenceEquals(s.Items, i))
|
|
1147 {
|
|
1148 var sc = new SqlQuery.InsertClause { Into = t ?? s.Into };
|
|
1149
|
|
1150 sc.Items.AddRange(i ?? s.Items);
|
|
1151 sc.WithIdentity = s.WithIdentity;
|
|
1152
|
|
1153 newElement = sc;
|
|
1154 }
|
|
1155
|
|
1156 break;
|
|
1157 }
|
|
1158
|
|
1159 case QueryElementType.UpdateClause:
|
|
1160 {
|
|
1161 var s = (SqlQuery.UpdateClause)element;
|
|
1162 var t = s.Table != null ? (SqlTable)ConvertInternal(s.Table, action) : null;
|
|
1163 var i = Convert(s.Items, action);
|
|
1164 var k = Convert(s.Keys, action);
|
|
1165
|
|
1166 if (t != null && !ReferenceEquals(s.Table, t) ||
|
|
1167 i != null && !ReferenceEquals(s.Items, i) ||
|
|
1168 k != null && !ReferenceEquals(s.Keys, k))
|
|
1169 {
|
|
1170 var sc = new SqlQuery.UpdateClause { Table = t ?? s.Table };
|
|
1171
|
|
1172 sc.Items.AddRange(i ?? s.Items);
|
|
1173 sc.Keys. AddRange(k ?? s.Keys);
|
|
1174
|
|
1175 newElement = sc;
|
|
1176 }
|
|
1177
|
|
1178 break;
|
|
1179 }
|
|
1180
|
|
1181 case QueryElementType.DeleteClause:
|
|
1182 {
|
|
1183 var s = (SqlQuery.DeleteClause)element;
|
|
1184 var t = s.Table != null ? (SqlTable)ConvertInternal(s.Table, action) : null;
|
|
1185
|
|
1186 if (t != null && !ReferenceEquals(s.Table, t))
|
|
1187 {
|
|
1188 newElement = new SqlQuery.DeleteClause { Table = t ?? s.Table };
|
|
1189 }
|
|
1190
|
|
1191 break;
|
|
1192 }
|
|
1193
|
|
1194 case QueryElementType.SelectClause:
|
|
1195 {
|
|
1196 var sc = (SqlQuery.SelectClause)element;
|
|
1197 var cols = Convert(sc.Columns, action);
|
|
1198 var take = (ISqlExpression)ConvertInternal(sc.TakeValue, action);
|
|
1199 var skip = (ISqlExpression)ConvertInternal(sc.SkipValue, action);
|
|
1200
|
|
1201 IQueryElement parent;
|
|
1202 _visitedElements.TryGetValue(sc.SqlQuery, out parent);
|
|
1203
|
|
1204 if (parent != null ||
|
|
1205 cols != null && !ReferenceEquals(sc.Columns, cols) ||
|
|
1206 take != null && !ReferenceEquals(sc.TakeValue, take) ||
|
|
1207 skip != null && !ReferenceEquals(sc.SkipValue, skip))
|
|
1208 {
|
|
1209 newElement = new SqlQuery.SelectClause(sc.IsDistinct, take ?? sc.TakeValue, skip ?? sc.SkipValue, cols ?? sc.Columns);
|
|
1210 ((SqlQuery.SelectClause)newElement).SetSqlQuery((SqlQuery)parent);
|
|
1211 }
|
|
1212
|
|
1213 break;
|
|
1214 }
|
|
1215
|
|
1216 case QueryElementType.FromClause:
|
|
1217 {
|
|
1218 var fc = (SqlQuery.FromClause)element;
|
|
1219 var ts = Convert(fc.Tables, action);
|
|
1220
|
|
1221 IQueryElement parent;
|
|
1222 _visitedElements.TryGetValue(fc.SqlQuery, out parent);
|
|
1223
|
|
1224 if (parent != null || ts != null && !ReferenceEquals(fc.Tables, ts))
|
|
1225 {
|
|
1226 newElement = new SqlQuery.FromClause(ts ?? fc.Tables);
|
|
1227 ((SqlQuery.FromClause)newElement).SetSqlQuery((SqlQuery)parent);
|
|
1228 }
|
|
1229
|
|
1230 break;
|
|
1231 }
|
|
1232
|
|
1233 case QueryElementType.WhereClause:
|
|
1234 {
|
|
1235 var wc = (SqlQuery.WhereClause)element;
|
|
1236 var cond = (SqlQuery.SearchCondition)ConvertInternal(wc.SearchCondition, action);
|
|
1237
|
|
1238 IQueryElement parent;
|
|
1239 _visitedElements.TryGetValue(wc.SqlQuery, out parent);
|
|
1240
|
|
1241 if (parent != null || cond != null && !ReferenceEquals(wc.SearchCondition, cond))
|
|
1242 {
|
|
1243 newElement = new SqlQuery.WhereClause(cond ?? wc.SearchCondition);
|
|
1244 ((SqlQuery.WhereClause)newElement).SetSqlQuery((SqlQuery)parent);
|
|
1245 }
|
|
1246
|
|
1247 break;
|
|
1248 }
|
|
1249
|
|
1250 case QueryElementType.GroupByClause:
|
|
1251 {
|
|
1252 var gc = (SqlQuery.GroupByClause)element;
|
|
1253 var es = Convert(gc.Items, action);
|
|
1254
|
|
1255 IQueryElement parent;
|
|
1256 _visitedElements.TryGetValue(gc.SqlQuery, out parent);
|
|
1257
|
|
1258 if (parent != null || es != null && !ReferenceEquals(gc.Items, es))
|
|
1259 {
|
|
1260 newElement = new SqlQuery.GroupByClause(es ?? gc.Items);
|
|
1261 ((SqlQuery.GroupByClause)newElement).SetSqlQuery((SqlQuery)parent);
|
|
1262 }
|
|
1263
|
|
1264 break;
|
|
1265 }
|
|
1266
|
|
1267 case QueryElementType.OrderByClause:
|
|
1268 {
|
|
1269 var oc = (SqlQuery.OrderByClause)element;
|
|
1270 var es = Convert(oc.Items, action);
|
|
1271
|
|
1272 IQueryElement parent;
|
|
1273 _visitedElements.TryGetValue(oc.SqlQuery, out parent);
|
|
1274
|
|
1275 if (parent != null || es != null && !ReferenceEquals(oc.Items, es))
|
|
1276 {
|
|
1277 newElement = new SqlQuery.OrderByClause(es ?? oc.Items);
|
|
1278 ((SqlQuery.OrderByClause)newElement).SetSqlQuery((SqlQuery)parent);
|
|
1279 }
|
|
1280
|
|
1281 break;
|
|
1282 }
|
|
1283
|
|
1284 case QueryElementType.OrderByItem:
|
|
1285 {
|
|
1286 var i = (SqlQuery.OrderByItem)element;
|
|
1287 var e = (ISqlExpression)ConvertInternal(i.Expression, action);
|
|
1288
|
|
1289 if (e != null && !ReferenceEquals(i.Expression, e))
|
|
1290 newElement = new SqlQuery.OrderByItem(e, i.IsDescending);
|
|
1291
|
|
1292 break;
|
|
1293 }
|
|
1294
|
|
1295 case QueryElementType.Union:
|
|
1296 {
|
|
1297 var u = (SqlQuery.Union)element;
|
|
1298 var q = (SqlQuery)ConvertInternal(u.SqlQuery, action);
|
|
1299
|
|
1300 if (q != null && !ReferenceEquals(u.SqlQuery, q))
|
|
1301 newElement = new SqlQuery.Union(q, u.IsAll);
|
|
1302
|
|
1303 break;
|
|
1304 }
|
|
1305
|
|
1306 case QueryElementType.SqlQuery:
|
|
1307 {
|
|
1308 var q = (SqlQuery)element;
|
|
1309 IQueryElement parent = null;
|
|
1310
|
|
1311 var doConvert = q.ParentSql != null && !_visitedElements.TryGetValue(q.ParentSql, out parent);
|
|
1312
|
|
1313 if (!doConvert)
|
|
1314 {
|
|
1315 doConvert = null != Find(q, e =>
|
|
1316 {
|
|
1317 if (_visitedElements.ContainsKey(e) && _visitedElements[e] != e)
|
|
1318 return true;
|
|
1319
|
|
1320 var ret = action(e);
|
|
1321
|
|
1322 if (ret != null && !ReferenceEquals(e, ret))
|
|
1323 {
|
|
1324 _visitedElements.Add(e, ret);
|
|
1325 return true;
|
|
1326 }
|
|
1327
|
|
1328 return false;
|
|
1329 });
|
|
1330 }
|
|
1331
|
|
1332 if (!doConvert)
|
|
1333 break;
|
|
1334
|
|
1335 var nq = new SqlQuery { QueryType = q.QueryType };
|
|
1336
|
|
1337 _visitedElements.Add(q, nq);
|
|
1338
|
|
1339 var fc = (SqlQuery.FromClause) ConvertInternal(q.From, action) ?? q.From;
|
|
1340 var sc = (SqlQuery.SelectClause) ConvertInternal(q.Select, action) ?? q.Select;
|
|
1341 var ic = q.IsInsert ? ((SqlQuery.InsertClause)ConvertInternal(q.Insert, action) ?? q.Insert) : null;
|
|
1342 var uc = q.IsUpdate ? ((SqlQuery.UpdateClause)ConvertInternal(q.Update, action) ?? q.Update) : null;
|
|
1343 var dc = q.IsDelete ? ((SqlQuery.DeleteClause)ConvertInternal(q.Delete, action) ?? q.Delete) : null;
|
|
1344 var wc = (SqlQuery.WhereClause) ConvertInternal(q.Where, action) ?? q.Where;
|
|
1345 var gc = (SqlQuery.GroupByClause)ConvertInternal(q.GroupBy, action) ?? q.GroupBy;
|
|
1346 var hc = (SqlQuery.WhereClause) ConvertInternal(q.Having, action) ?? q.Having;
|
|
1347 var oc = (SqlQuery.OrderByClause)ConvertInternal(q.OrderBy, action) ?? q.OrderBy;
|
|
1348 var us = q.HasUnion ? Convert(q.Unions, action) : q.Unions;
|
|
1349
|
|
1350 var ps = new List<SqlParameter>(q.Parameters.Count);
|
|
1351
|
|
1352 foreach (var p in q.Parameters)
|
|
1353 {
|
|
1354 IQueryElement e;
|
|
1355
|
|
1356 if (_visitedElements.TryGetValue(p, out e))
|
|
1357 {
|
|
1358 if (e == null)
|
|
1359 ps.Add(p);
|
|
1360 else if (e is SqlParameter)
|
|
1361 ps.Add((SqlParameter)e);
|
|
1362 }
|
|
1363 }
|
|
1364
|
|
1365 nq.Init(ic, uc, dc, sc, fc, wc, gc, hc, oc, us, (SqlQuery)parent, q.IsParameterDependent, ps);
|
|
1366
|
|
1367 _visitedElements[q] = action(nq) ?? nq;
|
|
1368
|
|
1369 return nq;
|
|
1370 }
|
|
1371 }
|
|
1372
|
|
1373 newElement = newElement == null ? action(element) : (action(newElement) ?? newElement);
|
|
1374
|
|
1375 _visitedElements.Add(element, newElement);
|
|
1376
|
|
1377 return newElement;
|
|
1378 }
|
|
1379
|
|
1380 static TE[] ToArray<TK,TE>(IDictionary<TK,TE> dic)
|
|
1381 {
|
|
1382 var es = new TE[dic.Count];
|
|
1383 var i = 0;
|
|
1384
|
|
1385 foreach (var e in dic.Values)
|
|
1386 es[i++] = e;
|
|
1387
|
|
1388 return es;
|
|
1389 }
|
|
1390
|
|
1391 delegate T Clone<T>(T obj);
|
|
1392
|
|
1393 T[] Convert<T>(T[] arr, ConvertFunc action)
|
|
1394 where T : class, IQueryElement
|
|
1395 {
|
|
1396 return Convert(arr, action, null);
|
|
1397 }
|
|
1398
|
|
1399 T[] Convert<T>(T[] arr1, ConvertFunc action, Clone<T> clone)
|
|
1400 where T : class, IQueryElement
|
|
1401 {
|
|
1402 T[] arr2 = null;
|
|
1403
|
|
1404 for (var i = 0; i < arr1.Length; i++)
|
|
1405 {
|
|
1406 var elem1 = arr1[i];
|
|
1407 var elem2 = (T)ConvertInternal(elem1, action);
|
|
1408
|
|
1409 if (elem2 != null && !ReferenceEquals(elem1, elem2))
|
|
1410 {
|
|
1411 if (arr2 == null)
|
|
1412 {
|
|
1413 arr2 = new T[arr1.Length];
|
|
1414
|
|
1415 for (var j = 0; j < i; j++)
|
|
1416 arr2[j] = clone == null ? arr1[j] : clone(arr1[j]);
|
|
1417 }
|
|
1418
|
|
1419 arr2[i] = elem2;
|
|
1420 }
|
|
1421 else if (arr2 != null)
|
|
1422 arr2[i] = clone == null ? elem1 : clone(elem1);
|
|
1423 }
|
|
1424
|
|
1425 return arr2;
|
|
1426 }
|
|
1427
|
|
1428 List<T> Convert<T>(List<T> list, ConvertFunc action)
|
|
1429 where T : class, IQueryElement
|
|
1430 {
|
|
1431 return Convert(list, action, null);
|
|
1432 }
|
|
1433
|
|
1434 List<T> Convert<T>(List<T> list1, ConvertFunc action, Clone<T> clone)
|
|
1435 where T : class, IQueryElement
|
|
1436 {
|
|
1437 List<T> list2 = null;
|
|
1438
|
|
1439 for (var i = 0; i < list1.Count; i++)
|
|
1440 {
|
|
1441 var elem1 = list1[i];
|
|
1442 var elem2 = (T)ConvertInternal(elem1, action);
|
|
1443
|
|
1444 if (elem2 != null && !ReferenceEquals(elem1, elem2))
|
|
1445 {
|
|
1446 if (list2 == null)
|
|
1447 {
|
|
1448 list2 = new List<T>(list1.Count);
|
|
1449
|
|
1450 for (var j = 0; j < i; j++)
|
|
1451 list2.Add(clone == null ? list1[j] : clone(list1[j]));
|
|
1452 }
|
|
1453
|
|
1454 list2.Add(elem2);
|
|
1455 }
|
|
1456 else if (list2 != null)
|
|
1457 list2.Add(clone == null ? elem1 : clone(elem1));
|
|
1458 }
|
|
1459
|
|
1460 return list2;
|
|
1461 }
|
|
1462
|
|
1463 #endregion
|
|
1464 }
|
|
1465 }
|