comparison Source/Data/Sql/QueryVisitor.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
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 }