1 //---------------------------------------------------------------------
2 // <copyright file="ExpressionDumper.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner  Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9 
10 using System;
11 using System.Collections.Generic;
12 using System.Diagnostics;
13 
14 using System.Data.Common;
15 using System.Data.Metadata.Edm;
16 using System.Data.Common.CommandTrees;
17 
18 namespace System.Data.Common.CommandTrees.Internal
19 {
20     /// <summary>
21     /// Writes a description of a given expression, in a format determined by the specific implementation of a derived type
22     /// </summary>
23     internal abstract class ExpressionDumper : DbExpressionVisitor
24     {
25         #region Constructors
ExpressionDumper()26         internal ExpressionDumper() { }
27         #endregion
28 
29         #region (Pseudo) Public API
30 
31         /// <summary>
32         /// Begins a new Dump block with the specified name
33         /// </summary>
34         /// <param name="name">The name of the block</param>
Begin(string name)35         internal void Begin(string name) { Begin(name, (Dictionary<string, object>)null); }
36 
37         /// <summary>
38         /// Begins a new Dump block with the specified name and specified attributes
39         /// </summary>
40         /// <param name="name">The name of the block</param>
41         /// <param name="attrs">The named attributes of the block. May be null</param>
Begin(string name, Dictionary<string, object> attrs)42         internal abstract void  Begin(string name, Dictionary<string, object> attrs);
43 
44         /// <summary>
45         /// Ends the Dump block with the specified name.
46         /// The caller should not assumer that this name will be verified
47         /// against the last name used in a Begin call.
48         /// </summary>
49         /// <param name="name">The name of the block</param>
End(string name)50         internal abstract void  End(string name);
51 
52         /// <summary>
53         /// Dumps a DbExpression by visiting it.
54         /// </summary>
55         /// <param name="target">The DbExpression to dump</param>
Dump(DbExpression target)56         internal void Dump(DbExpression target)
57         {
58             target.Accept(this);
59         }
60 
61         /// <summary>
62         /// Dumps a DbExpression with the specified block name preceeding and succeeding (decorating) it.
63         /// </summary>
64         /// <param name="e">The DbExpression to dump</param>
65         /// <param name="name">The decorating block name</param>
Dump(DbExpression e, string name)66         internal void Dump(DbExpression e, string name)
67         {
68             Begin(name);
69             Dump(e);
70             End(name);
71         }
72 
73         /// <summary>
74         /// Dumps a DbExpressionBinding with the specified decoration
75         /// </summary>
76         /// <param name="binding">The DbExpressionBinding to dump</param>
77         /// <param name="name">The decorating block name</param>
Dump(DbExpressionBinding binding, string name)78         internal void Dump(DbExpressionBinding binding, string name)
79         {
80             Begin(name);
81             Dump(binding);
82             End(name);
83         }
84 
85         /// <summary>
86         /// Dumps a DbExpressionBinding including its VariableName and DbExpression
87         /// </summary>
88         /// <param name="binding">The DbExpressionBinding to dump</param>
Dump(DbExpressionBinding binding)89         internal void Dump(DbExpressionBinding binding)
90         {
91             Begin("DbExpressionBinding", "VariableName", binding.VariableName);
92             Begin("Expression");
93             Dump(binding.Expression);
94             End("Expression");
95             End("DbExpressionBinding");
96 
97         }
98 
99         /// <summary>
100         /// Dumps a DbGroupExpressionBinding with the specified decoration
101         /// </summary>
102         /// <param name="binding">The DbGroupExpressionBinding to dump</param>
103         /// <param name="name">The decorating block name</param>
Dump(DbGroupExpressionBinding binding, string name)104         internal void Dump(DbGroupExpressionBinding binding, string name)
105         {
106             Begin(name);
107             Dump(binding);
108             End(name);
109         }
110 
111         /// <summary>
112         /// Dumps a DbGroupExpressionBinding including its VariableName, GroupVariableName and DbExpression
113         /// </summary>
114         /// <param name="binding">The DbGroupExpressionBinding to dump</param>
Dump(DbGroupExpressionBinding binding)115         internal void Dump(DbGroupExpressionBinding binding)
116         {
117             Begin("DbGroupExpressionBinding", "VariableName", binding.VariableName, "GroupVariableName", binding.GroupVariableName);
118             Begin("Expression");
119             Dump(binding.Expression);
120             End("Expression");
121             End("DbGroupExpressionBinding");
122         }
123 
124         /// <summary>
125         /// Dumps each DbExpression in the specified enumerable. The entire output is decorated with the 'pluralName'
126         /// block name while each element DbExpression is decorated with the 'singularName' block name.
127         /// If the list is empty only the pluralName decoration start/end will appear.
128         /// </summary>
129         /// <param name="exprs">The enumerable list of Expressions to dump</param>
130         /// <param name="pluralName">The overall list decoration block name</param>
131         /// <param name="singularName">The decoration block name that will be applied to each element DbExpression</param>
Dump(IEnumerable<DbExpression> exprs, string pluralName, string singularName)132         internal void Dump(IEnumerable<DbExpression> exprs, string pluralName, string singularName)
133         {
134             Begin(pluralName);
135 
136             foreach (DbExpression expr in exprs)
137             {
138                 Begin(singularName);
139                 this.Dump(expr);
140                 End(singularName);
141             }
142 
143             End(pluralName);
144         }
145 
146         /// <summary>
147         /// Dumps each Parameter metadata in the specified enumerable. The entire output is decorated with the "Parameters"
148         /// block name while each metadata element is decorated with the "Parameter" block name.
149         /// If the list is empty only the "Parameters" decoration start/end will appear.
150         /// </summary>
151         /// <param name="paramList">The enumerable list of Parameter metadata to dump</param>
Dump(IEnumerable<FunctionParameter> paramList)152         internal void Dump(IEnumerable<FunctionParameter> paramList)
153         {
154             Begin("Parameters");
155             foreach (FunctionParameter param in paramList)
156             {
157                 Begin("Parameter", "Name", param.Name);
158                 Dump(param.TypeUsage, "ParameterType");
159                 End("Parameter");
160             }
161             End("Parameters");
162         }
163 
164         /// <summary>
165         /// Dumps the specified Type metadata instance with the specified decoration
166         /// </summary>
167         /// <param name="type">The Type metadata to dump</param>
168         /// <param name="name">The decorating block name</param>
Dump(TypeUsage type, string name)169         internal void Dump(TypeUsage type, string name)
170         {
171             Begin(name);
172             Dump(type);
173             End(name);
174         }
175 
176         /// <summary>
177         /// Dumps the specified Type metadata instance
178         /// </summary>
179         /// <param name="type">The Type metadata to dump</param>
Dump(TypeUsage type)180         internal void Dump(TypeUsage type)
181         {
182             Dictionary<string, object> facetInfo = new Dictionary<string, object>();
183             foreach (Facet facet in type.Facets)
184             {
185                 facetInfo.Add(facet.Name, facet.Value);
186             }
187 
188             Begin("TypeUsage", facetInfo);
189             Dump(type.EdmType);
190             End("TypeUsage");
191         }
192 
193         /// <summary>
194         /// Dumps the specified EDM type metadata instance with the specified decoration
195         /// </summary>
196         /// <param name="type">The type metadata to dump</param>
197         /// <param name="name">The decorating block name</param>
Dump(EdmType type, string name)198         internal void Dump(EdmType type, string name)
199         {
200             Begin(name);
201             Dump(type);
202             End(name);
203         }
204 
205         /// <summary>
206         /// Dumps the specified type metadata instance
207         /// </summary>
208         /// <param name="type">The type metadata to dump</param>
Dump(EdmType type)209         internal void Dump(EdmType type)
210         {
211             Begin("EdmType",
212                     "BuiltInTypeKind", Enum.GetName(typeof(BuiltInTypeKind), type.BuiltInTypeKind),
213                     "Namespace", type.NamespaceName,
214                     "Name", type.Name);
215             End("EdmType");
216         }
217 
218         /// <summary>
219         /// Dumps the specified Relation metadata instance with the specified decoration
220         /// </summary>
221         /// <param name="type">The Relation metadata to dump</param>
222         /// <param name="name">The decorating block name</param>
Dump(RelationshipType type, string name)223         internal void Dump(RelationshipType type, string name)
224         {
225             Begin(name);
226             Dump(type);
227             End(name);
228         }
229 
230         /// <summary>
231         /// Dumps the specified Relation metadata instance
232         /// </summary>
233         /// <param name="type">The Relation metadata to dump</param>
Dump(RelationshipType type)234         internal void Dump(RelationshipType type)
235         {
236             Begin(
237                 "RelationshipType",
238                 "Namespace", type.NamespaceName,
239                 "Name",
240                 type.Name
241             );
242             End("RelationshipType");
243         }
244 
245         /// <summary>
246         /// Dumps the specified EdmFunction metadata instance
247         /// </summary>
248         /// <param name="function">The EdmFunction metadata to dump.</param>
Dump(EdmFunction function)249         internal void Dump(EdmFunction function)
250         {
251             Begin("Function", "Name", function.Name, "Namespace", function.NamespaceName);
252             Dump(function.Parameters);
253             if (function.ReturnParameters.Count == 1)
254             {
255                 Dump(function.ReturnParameters[0].TypeUsage, "ReturnType");
256             }
257             else
258             {
259                 Begin("ReturnTypes");
260                 foreach (var returnParameter in function.ReturnParameters)
261                 {
262                     Dump(returnParameter.TypeUsage, returnParameter.Name);
263                 }
264                 End("ReturnTypes");
265             }
266             End("Function");
267         }
268 
269         /// <summary>
270         /// Dumps the specified EdmProperty metadata instance
271         /// </summary>
272         /// <param name="prop">The EdmProperty metadata to dump</param>
Dump(EdmProperty prop)273         internal void Dump(EdmProperty prop)
274         {
275             Begin("Property", "Name", prop.Name, "Nullable", prop.Nullable);
276             Dump(prop.DeclaringType, "DeclaringType");
277             Dump(prop.TypeUsage, "PropertyType");
278             End("Property");
279         }
280 
281         /// <summary>
282         /// Dumps the specified Relation End EdmMember metadata instance with the specified decoration
283         /// </summary>
284         /// <param name="end">The Relation End metadata to dump</param>
285         /// <param name="name">The decorating block name</param>
Dump(RelationshipEndMember end, string name)286         internal void Dump(RelationshipEndMember end, string name)
287         {
288             Begin(name);
289             Begin(
290                 "RelationshipEndMember",
291                 "Name", end.Name,
292                 //"IsParent", end.IsParent,
293                 "RelationshipMultiplicity", Enum.GetName(typeof(RelationshipMultiplicity), end.RelationshipMultiplicity)
294             );
295             Dump(end.DeclaringType, "DeclaringRelation");
296             Dump(end.TypeUsage, "EndType");
297             End("RelationshipEndMember");
298             End(name);
299         }
300 
301         /// <summary>
302         /// Dumps the specified Navigation Property EdmMember metadata instance with the specified decoration
303         /// </summary>
304         /// <param name="navProp">The Navigation Property metadata to dump</param>
305         /// <param name="name">The decorating block name</param>
Dump(NavigationProperty navProp, string name)306         internal void Dump(NavigationProperty navProp, string name)
307         {
308             Begin(name);
309             Begin(
310                 "NavigationProperty",
311                 "Name", navProp.Name,
312                 //"IsParent", end.IsParent,
313                 "RelationshipTypeName", navProp.RelationshipType.FullName,
314                 "ToEndMemberName", navProp.ToEndMember.Name
315             );
316             Dump(navProp.DeclaringType, "DeclaringType");
317             Dump(navProp.TypeUsage, "PropertyType");
318             End("NavigationProperty");
319             End(name);
320         }
321 
322 #if METHOD_EXPRESSION
323         /// <summary>
324         /// Dumps the specified Method metadata instance
325         /// </summary>
326         /// <param name="meth">The Method metadata to dump</param>
Dump(MethodMetadata meth)327         internal void Dump(MethodMetadata meth)
328         {
329             Begin("MethodMetadata", "Name", meth.Name, "IsStatic", meth.IsStatic);
330             Dump(meth.DefiningType, "DeclaringType");
331             Dump(meth.Parameters);
332             Dump(meth.Type, "ReturnType");
333             End("MethodMetadata");
334         }
335 #endif
336 
337         /// <summary>
338         /// Dumps the specified DbLambda instance
339         /// </summary>
340         /// <param name="lambda">The DbLambda to dump.</param>
Dump(DbLambda lambda)341         internal void Dump(DbLambda lambda)
342         {
343             Begin("DbLambda");
344             Dump(System.Linq.Enumerable.Cast<DbExpression>(lambda.Variables), "Variables", "Variable");
345             Dump(lambda.Body, "Body");
346             End("DbLambda");
347         }
348 
349         #endregion
350 
351         #region Private Implementation
Begin(DbExpression expr)352         private void Begin(DbExpression expr)
353         {
354             Begin(expr, new Dictionary<string, object>());
355         }
356 
Begin(DbExpression expr, Dictionary<string, object> attrs)357         private void Begin(DbExpression expr, Dictionary<string, object> attrs)
358         {
359             attrs.Add("DbExpressionKind", Enum.GetName(typeof(DbExpressionKind), expr.ExpressionKind));
360             Begin(expr.GetType().Name, attrs);
361             Dump(expr.ResultType, "ResultType");
362         }
363 
Begin(DbExpression expr, string attributeName, object attributeValue)364         private void Begin(DbExpression expr, string attributeName, object attributeValue)
365         {
366             Dictionary<string, object> attrs = new Dictionary<string, object>();
367             attrs.Add(attributeName, attributeValue);
368             Begin(expr, attrs);
369         }
370 
Begin(string expr, string attributeName, object attributeValue)371         private void Begin(string expr, string attributeName, object attributeValue)
372         {
373             Dictionary<string, object> attrs = new Dictionary<string, object>();
374             attrs.Add(attributeName, attributeValue);
375             Begin(expr, attrs);
376         }
377 
Begin(string expr, string attributeName1, object attributeValue1, string attributeName2, object attributeValue2)378         private void Begin(string expr,
379                            string attributeName1,
380                            object attributeValue1,
381                            string attributeName2,
382                            object attributeValue2)
383         {
384             Dictionary<string, object> attrs = new Dictionary<string, object>();
385             attrs.Add(attributeName1, attributeValue1);
386             attrs.Add(attributeName2, attributeValue2);
387             Begin(expr, attrs);
388         }
389 
Begin(string expr, string attributeName1, object attributeValue1, string attributeName2, object attributeValue2, string attributeName3, object attributeValue3)390         private void Begin(string expr,
391                            string attributeName1,
392                            object attributeValue1,
393                            string attributeName2,
394                            object attributeValue2,
395                            string attributeName3,
396                            object attributeValue3)
397         {
398             Dictionary<string, object> attrs = new Dictionary<string, object>();
399             attrs.Add(attributeName1, attributeValue1);
400             attrs.Add(attributeName2, attributeValue2);
401             attrs.Add(attributeName3, attributeValue3);
402             Begin(expr, attrs);
403         }
404 
End(DbExpression expr)405         private void End(DbExpression expr)
406         {
407             End(expr.GetType().Name);
408         }
409 
BeginUnary(DbUnaryExpression e)410         private void BeginUnary(DbUnaryExpression e)
411         {
412             Begin(e);
413             Begin("Argument");
414             Dump(e.Argument);
415             End("Argument");
416         }
417 
BeginBinary(DbBinaryExpression e)418         private void BeginBinary(DbBinaryExpression e)
419         {
420             Begin(e);
421             Begin("Left");
422             Dump(e.Left);
423             End("Left");
424             Begin("Right");
425             Dump(e.Right);
426             End("Right");
427         }
428         #endregion
429 
430         #region DbExpressionVisitor<DbExpression> Members
431 
Visit(DbExpression e)432         public override void Visit(DbExpression e)
433         {
434             Begin(e);
435             End(e);
436         }
437 
Visit(DbConstantExpression e)438         public override void Visit(DbConstantExpression e)
439         {
440             Dictionary<string, object> attrs = new Dictionary<string,object>();
441             attrs.Add("Value", e.Value);
442             Begin(e, attrs);
443             End(e);
444         }
445 
Visit(DbNullExpression e)446         public override void Visit(DbNullExpression e)
447         {
448             Begin(e);
449             End(e);
450         }
451 
Visit(DbVariableReferenceExpression e)452         public override void Visit(DbVariableReferenceExpression e)
453         {
454             Dictionary<string, object> attrs = new Dictionary<string, object>();
455             attrs.Add("VariableName", e.VariableName);
456             Begin(e, attrs);
457             End(e);
458         }
459 
Visit(DbParameterReferenceExpression e)460         public override void Visit(DbParameterReferenceExpression e)
461         {
462             Dictionary<string, object> attrs = new Dictionary<string, object>();
463             attrs.Add("ParameterName", e.ParameterName);
464             Begin(e, attrs);
465             End(e);
466         }
467 
Visit(DbFunctionExpression e)468         public override void Visit(DbFunctionExpression e)
469         {
470             Begin(e);
471             Dump(e.Function);
472             Dump(e.Arguments, "Arguments", "Argument");
473             End(e);
474         }
475 
Visit(DbLambdaExpression expression)476         public override void Visit(DbLambdaExpression expression)
477         {
478             Begin(expression);
479             Dump(expression.Lambda);
480             Dump(expression.Arguments, "Arguments", "Argument");
481             End(expression);
482         }
483 
484 #if METHOD_EXPRESSION
Visit(MethodExpression e)485         public override void Visit(MethodExpression e)
486         {
487             Begin(e);
488             Dump(e.Method);
489             Dump(e.Arguments, "Arguments", "Argument");
490             if (e.Instance != null)
491             {
492                 Dump(e.Instance, "Instance");
493             }
494             End(e);
495         }
496 #endif
497 
Visit(DbPropertyExpression e)498         public override void Visit(DbPropertyExpression e)
499         {
500             //
501             // Currently the DbPropertyExpression.EdmProperty member property may only be either:
502             // - EdmProperty
503             // - RelationshipEndMember
504             // - NavigationProperty
505             //
506             Begin(e);
507             RelationshipEndMember end = e.Property as RelationshipEndMember;
508             if (end != null)
509             {
510                 Dump(end, "Property");
511             }
512             else if (Helper.IsNavigationProperty(e.Property))
513             {
514                 Dump((NavigationProperty)e.Property, "Property");
515             }
516             else
517             {
518                 Dump((EdmProperty)e.Property);
519             }
520 
521             if (e.Instance != null)
522             {
523                 Dump(e.Instance, "Instance");
524             }
525             End(e);
526         }
527 
Visit(DbComparisonExpression e)528         public override void Visit(DbComparisonExpression e)
529         {
530             BeginBinary(e);
531             End(e);
532         }
533 
Visit(DbLikeExpression e)534         public override void Visit(DbLikeExpression e)
535         {
536             Begin(e);
537             Dump(e.Argument, "Argument");
538             Dump(e.Pattern, "Pattern");
539             Dump(e.Escape, "Escape");
540             End(e);
541         }
542 
Visit(DbLimitExpression e)543         public override void Visit(DbLimitExpression e)
544         {
545             Begin(e, "WithTies", e.WithTies);
546             Dump(e.Argument, "Argument");
547             Dump(e.Limit, "Limit");
548             End(e);
549         }
550 
Visit(DbIsNullExpression e)551         public override void Visit(DbIsNullExpression e)
552         {
553             BeginUnary(e);
554             End(e);
555         }
556 
Visit(DbArithmeticExpression e)557         public override void Visit(DbArithmeticExpression e)
558         {
559             Begin(e);
560             Dump(e.Arguments, "Arguments", "Argument");
561             End(e);
562         }
563 
Visit(DbAndExpression e)564         public override void Visit(DbAndExpression e)
565         {
566             BeginBinary(e);
567             End(e);
568         }
569 
Visit(DbOrExpression e)570         public override void Visit(DbOrExpression e)
571         {
572             BeginBinary(e);
573             End(e);
574         }
575 
Visit(DbNotExpression e)576         public override void Visit(DbNotExpression e)
577         {
578             BeginUnary(e);
579             End(e);
580         }
581 
Visit(DbDistinctExpression e)582         public override void Visit(DbDistinctExpression e)
583         {
584             BeginUnary(e);
585             End(e);
586         }
587 
Visit(DbElementExpression e)588         public override void Visit(DbElementExpression e)
589         {
590             BeginUnary(e);
591             End(e);
592         }
593 
Visit(DbIsEmptyExpression e)594         public override void Visit(DbIsEmptyExpression e)
595         {
596             BeginUnary(e);
597             End(e);
598         }
599 
Visit(DbUnionAllExpression e)600         public override void Visit(DbUnionAllExpression e)
601         {
602             BeginBinary(e);
603             End(e);
604         }
605 
Visit(DbIntersectExpression e)606         public override void Visit(DbIntersectExpression e)
607         {
608             BeginBinary(e);
609             End(e);
610         }
611 
Visit(DbExceptExpression e)612         public override void Visit(DbExceptExpression e)
613         {
614             BeginBinary(e);
615             End(e);
616         }
617 
Visit(DbTreatExpression e)618         public override void Visit(DbTreatExpression e)
619         {
620             BeginUnary(e);
621             End(e);
622         }
623 
Visit(DbIsOfExpression e)624         public override void Visit(DbIsOfExpression e)
625         {
626             BeginUnary(e);
627             Dump(e.OfType, "OfType") ;
628             End(e);
629         }
630 
Visit(DbCastExpression e)631         public override void Visit(DbCastExpression e)
632         {
633             BeginUnary(e);
634             End(e);
635         }
636 
Visit(DbCaseExpression e)637         public override void Visit(DbCaseExpression e)
638         {
639             Begin(e);
640             Dump(e.When, "Whens", "When");
641             Dump(e.Then, "Thens", "Then");
642             Dump(e.Else, "Else");
643         }
644 
Visit(DbOfTypeExpression e)645         public override void Visit(DbOfTypeExpression e)
646         {
647             BeginUnary(e);
648             Dump(e.OfType, "OfType");
649             End(e);
650         }
651 
Visit(DbNewInstanceExpression e)652         public override void Visit(DbNewInstanceExpression e)
653         {
654             Begin(e);
655             Dump(e.Arguments, "Arguments", "Argument");
656             if (e.HasRelatedEntityReferences)
657             {
658                 Begin("RelatedEntityReferences");
659                 foreach (DbRelatedEntityRef relatedRef in e.RelatedEntityReferences)
660                 {
661                     Begin("DbRelatedEntityRef");
662                     Dump(relatedRef.SourceEnd, "SourceEnd");
663                     Dump(relatedRef.TargetEnd, "TargetEnd");
664                     Dump(relatedRef.TargetEntityReference, "TargetEntityReference");
665                     End("DbRelatedEntityRef");
666                 }
667                 End("RelatedEntityReferences");
668             }
669             End(e);
670         }
671 
Visit(DbRelationshipNavigationExpression e)672         public override void Visit(DbRelationshipNavigationExpression e)
673         {
674             Begin(e);
675             Dump(e.NavigateFrom, "NavigateFrom");
676             Dump(e.NavigateTo, "NavigateTo");
677             Dump(e.Relationship, "Relationship");
678             Dump(e.NavigationSource, "NavigationSource");
679             End(e);
680         }
681 
Visit(DbRefExpression e)682         public override void Visit(DbRefExpression e)
683         {
684             BeginUnary(e);
685             End(e);
686         }
687 
Visit(DbDerefExpression e)688         public override void Visit(DbDerefExpression e)
689         {
690             BeginUnary(e);
691             End(e);
692         }
693 
Visit(DbRefKeyExpression e)694         public override void Visit(DbRefKeyExpression e)
695         {
696             BeginUnary(e);
697             End(e);
698         }
699 
Visit(DbEntityRefExpression e)700         public override void Visit(DbEntityRefExpression e)
701         {
702             BeginUnary(e);
703             End(e);
704         }
705 
Visit(DbScanExpression e)706         public override void Visit(DbScanExpression e)
707         {
708             Begin(e);
709             Begin("Target", "Name", e.Target.Name, "Container", e.Target.EntityContainer.Name);
710             Dump(e.Target.ElementType, "TargetElementType");
711             End("Target");
712             End(e);
713         }
714 
Visit(DbFilterExpression e)715         public override void Visit(DbFilterExpression e)
716         {
717             Begin(e);
718             Dump(e.Input, "Input");
719             Dump(e.Predicate, "Predicate");
720             End(e);
721         }
722 
Visit(DbProjectExpression e)723         public override void Visit(DbProjectExpression e)
724         {
725             Begin(e);
726             Dump(e.Input, "Input");
727             Dump(e.Projection, "Projection");
728             End(e);
729         }
730 
Visit(DbCrossJoinExpression e)731         public override void Visit(DbCrossJoinExpression e)
732         {
733             Begin(e);
734             Begin("Inputs");
735             foreach (DbExpressionBinding binding in e.Inputs)
736             {
737                 Dump(binding, "Input");
738             }
739             End("Inputs");
740             End(e);
741         }
742 
Visit(DbJoinExpression e)743         public override void Visit(DbJoinExpression e)
744         {
745             Begin(e);
746             Dump(e.Left, "Left");
747             Dump(e.Right, "Right");
748             Dump(e.JoinCondition, "JoinCondition");
749             End(e);
750         }
751 
Visit(DbApplyExpression e)752         public override void Visit(DbApplyExpression e)
753         {
754             Begin(e);
755             Dump(e.Input, "Input");
756             Dump(e.Apply, "Apply");
757             End(e);
758         }
759 
Visit(DbGroupByExpression e)760         public override void Visit(DbGroupByExpression e)
761         {
762             Begin(e);
763             Dump(e.Input, "Input");
764             Dump(e.Keys, "Keys", "Key");
765             Begin("Aggregates");
766             foreach (DbAggregate agg in e.Aggregates)
767             {
768                 DbFunctionAggregate funcAgg = agg as DbFunctionAggregate;
769 
770                 if (funcAgg != null)
771                 {
772                     Begin("DbFunctionAggregate");
773                     Dump(funcAgg.Function);
774                     Dump(funcAgg.Arguments, "Arguments", "Argument");
775                     End("DbFunctionAggregate");
776                 }
777                 else
778                 {
779                     DbGroupAggregate groupAgg = agg as DbGroupAggregate;
780                     Debug.Assert(groupAgg != null, "Invalid DbAggregate");
781                     Begin("DbGroupAggregate");
782                     Dump(groupAgg.Arguments, "Arguments", "Argument");
783                     End("DbGroupAggregate");
784                 }
785             }
786             End("Aggregates");
787             End(e);
788         }
789 
Dump(IList<DbSortClause> sortOrder)790         protected virtual void Dump(IList<DbSortClause> sortOrder)
791         {
792             Begin("SortOrder");
793             foreach (DbSortClause clause in sortOrder)
794             {
795                 string collStr = clause.Collation;
796                 if (null == collStr)
797                 {
798                     collStr = "";
799                 }
800 
801                 Begin("DbSortClause", "Ascending", clause.Ascending, "Collation", collStr);
802                 Dump(clause.Expression, "Expression");
803                 End("DbSortClause");
804             }
805             End("SortOrder");
806         }
807 
Visit(DbSkipExpression e)808         public override void Visit(DbSkipExpression e)
809         {
810             Begin(e);
811             Dump(e.Input, "Input");
812             Dump(e.SortOrder);
813             Dump(e.Count, "Count");
814             End(e);
815         }
816 
Visit(DbSortExpression e)817         public override void Visit(DbSortExpression e)
818         {
819             Begin(e);
820             Dump(e.Input, "Input");
821             Dump(e.SortOrder);
822             End(e);
823         }
824 
Visit(DbQuantifierExpression e)825         public override void Visit(DbQuantifierExpression e)
826         {
827             Begin(e);
828             Dump(e.Input, "Input");
829             Dump(e.Predicate, "Predicate");
830             End(e);
831         }
832 
833         #endregion
834     }
835 }
836