1 //---------------------------------------------------------------------
2 // <copyright file="ExpressionDumper.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
11 using System
.Collections
.Generic
;
12 using System
.Diagnostics
;
14 using System
.Data
.Common
;
15 using System
.Data
.Metadata
.Edm
;
16 using System
.Data
.Common
.CommandTrees
;
18 namespace System
.Data
.Common
.CommandTrees
.Internal
21 /// Writes a description of a given expression, in a format determined by the specific implementation of a derived type
23 internal abstract class ExpressionDumper
: DbExpressionVisitor
26 internal ExpressionDumper() { }
29 #region (Pseudo) Public API
32 /// Begins a new Dump block with the specified name
34 /// <param name="name">The name of the block</param>
35 internal void Begin(string name
) { Begin(name, (Dictionary<string, object>)null); }
38 /// Begins a new Dump block with the specified name and specified attributes
40 /// <param name="name">The name of the block</param>
41 /// <param name="attrs">The named attributes of the block. May be null</param>
42 internal abstract void Begin(string name
, Dictionary
<string, object> attrs
);
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.
49 /// <param name="name">The name of the block</param>
50 internal abstract void End(string name
);
53 /// Dumps a DbExpression by visiting it.
55 /// <param name="target">The DbExpression to dump</param>
56 internal void Dump(DbExpression target
)
62 /// Dumps a DbExpression with the specified block name preceeding and succeeding (decorating) it.
64 /// <param name="e">The DbExpression to dump</param>
65 /// <param name="name">The decorating block name</param>
66 internal void Dump(DbExpression e
, string name
)
74 /// Dumps a DbExpressionBinding with the specified decoration
76 /// <param name="binding">The DbExpressionBinding to dump</param>
77 /// <param name="name">The decorating block name</param>
78 internal void Dump(DbExpressionBinding binding
, string name
)
86 /// Dumps a DbExpressionBinding including its VariableName and DbExpression
88 /// <param name="binding">The DbExpressionBinding to dump</param>
89 internal void Dump(DbExpressionBinding binding
)
91 Begin("DbExpressionBinding", "VariableName", binding
.VariableName
);
93 Dump(binding
.Expression
);
95 End("DbExpressionBinding");
100 /// Dumps a DbGroupExpressionBinding with the specified decoration
102 /// <param name="binding">The DbGroupExpressionBinding to dump</param>
103 /// <param name="name">The decorating block name</param>
104 internal void Dump(DbGroupExpressionBinding binding
, string name
)
112 /// Dumps a DbGroupExpressionBinding including its VariableName, GroupVariableName and DbExpression
114 /// <param name="binding">The DbGroupExpressionBinding to dump</param>
115 internal void Dump(DbGroupExpressionBinding binding
)
117 Begin("DbGroupExpressionBinding", "VariableName", binding
.VariableName
, "GroupVariableName", binding
.GroupVariableName
);
119 Dump(binding
.Expression
);
121 End("DbGroupExpressionBinding");
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.
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>
132 internal void Dump(IEnumerable
<DbExpression
> exprs
, string pluralName
, string singularName
)
136 foreach (DbExpression expr
in exprs
)
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.
151 /// <param name="paramList">The enumerable list of Parameter metadata to dump</param>
152 internal void Dump(IEnumerable
<FunctionParameter
> paramList
)
155 foreach (FunctionParameter param
in paramList
)
157 Begin("Parameter", "Name", param
.Name
);
158 Dump(param
.TypeUsage
, "ParameterType");
165 /// Dumps the specified Type metadata instance with the specified decoration
167 /// <param name="type">The Type metadata to dump</param>
168 /// <param name="name">The decorating block name</param>
169 internal void Dump(TypeUsage type
, string name
)
177 /// Dumps the specified Type metadata instance
179 /// <param name="type">The Type metadata to dump</param>
180 internal void Dump(TypeUsage type
)
182 Dictionary
<string, object> facetInfo
= new Dictionary
<string, object>();
183 foreach (Facet facet
in type
.Facets
)
185 facetInfo
.Add(facet
.Name
, facet
.Value
);
188 Begin("TypeUsage", facetInfo
);
194 /// Dumps the specified EDM type metadata instance with the specified decoration
196 /// <param name="type">The type metadata to dump</param>
197 /// <param name="name">The decorating block name</param>
198 internal void Dump(EdmType type
, string name
)
206 /// Dumps the specified type metadata instance
208 /// <param name="type">The type metadata to dump</param>
209 internal void Dump(EdmType type
)
212 "BuiltInTypeKind", Enum
.GetName(typeof(BuiltInTypeKind
), type
.BuiltInTypeKind
),
213 "Namespace", type
.NamespaceName
,
219 /// Dumps the specified Relation metadata instance with the specified decoration
221 /// <param name="type">The Relation metadata to dump</param>
222 /// <param name="name">The decorating block name</param>
223 internal void Dump(RelationshipType type
, string name
)
231 /// Dumps the specified Relation metadata instance
233 /// <param name="type">The Relation metadata to dump</param>
234 internal void Dump(RelationshipType type
)
238 "Namespace", type
.NamespaceName
,
242 End("RelationshipType");
246 /// Dumps the specified EdmFunction metadata instance
248 /// <param name="function">The EdmFunction metadata to dump.</param>
249 internal void Dump(EdmFunction function
)
251 Begin("Function", "Name", function
.Name
, "Namespace", function
.NamespaceName
);
252 Dump(function
.Parameters
);
253 if (function
.ReturnParameters
.Count
== 1)
255 Dump(function
.ReturnParameters
[0].TypeUsage
, "ReturnType");
259 Begin("ReturnTypes");
260 foreach (var returnParameter
in function
.ReturnParameters
)
262 Dump(returnParameter
.TypeUsage
, returnParameter
.Name
);
270 /// Dumps the specified EdmProperty metadata instance
272 /// <param name="prop">The EdmProperty metadata to dump</param>
273 internal void Dump(EdmProperty prop
)
275 Begin("Property", "Name", prop
.Name
, "Nullable", prop
.Nullable
);
276 Dump(prop
.DeclaringType
, "DeclaringType");
277 Dump(prop
.TypeUsage
, "PropertyType");
282 /// Dumps the specified Relation End EdmMember metadata instance with the specified decoration
284 /// <param name="end">The Relation End metadata to dump</param>
285 /// <param name="name">The decorating block name</param>
286 internal void Dump(RelationshipEndMember end
, string name
)
290 "RelationshipEndMember",
292 //"IsParent", end.IsParent,
293 "RelationshipMultiplicity", Enum
.GetName(typeof(RelationshipMultiplicity
), end
.RelationshipMultiplicity
)
295 Dump(end
.DeclaringType
, "DeclaringRelation");
296 Dump(end
.TypeUsage
, "EndType");
297 End("RelationshipEndMember");
302 /// Dumps the specified Navigation Property EdmMember metadata instance with the specified decoration
304 /// <param name="navProp">The Navigation Property metadata to dump</param>
305 /// <param name="name">The decorating block name</param>
306 internal void Dump(NavigationProperty navProp
, string name
)
310 "NavigationProperty",
311 "Name", navProp
.Name
,
312 //"IsParent", end.IsParent,
313 "RelationshipTypeName", navProp
.RelationshipType
.FullName
,
314 "ToEndMemberName", navProp
.ToEndMember
.Name
316 Dump(navProp
.DeclaringType
, "DeclaringType");
317 Dump(navProp
.TypeUsage
, "PropertyType");
318 End("NavigationProperty");
322 #if METHOD_EXPRESSION
324 /// Dumps the specified Method metadata instance
326 /// <param name="meth">The Method metadata to dump</param>
327 internal void Dump(MethodMetadata meth
)
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");
338 /// Dumps the specified DbLambda instance
340 /// <param name="lambda">The DbLambda to dump.</param>
341 internal void Dump(DbLambda lambda
)
344 Dump(System
.Linq
.Enumerable
.Cast
<DbExpression
>(lambda
.Variables
), "Variables", "Variable");
345 Dump(lambda
.Body
, "Body");
351 #region Private Implementation
352 private void Begin(DbExpression expr
)
354 Begin(expr
, new Dictionary
<string, object>());
357 private void Begin(DbExpression expr
, Dictionary
<string, object> attrs
)
359 attrs
.Add("DbExpressionKind", Enum
.GetName(typeof(DbExpressionKind
), expr
.ExpressionKind
));
360 Begin(expr
.GetType().Name
, attrs
);
361 Dump(expr
.ResultType
, "ResultType");
364 private void Begin(DbExpression expr
, string attributeName
, object attributeValue
)
366 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
367 attrs
.Add(attributeName
, attributeValue
);
371 private void Begin(string expr
, string attributeName
, object attributeValue
)
373 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
374 attrs
.Add(attributeName
, attributeValue
);
378 private void Begin(string expr
,
379 string attributeName1
,
380 object attributeValue1
,
381 string attributeName2
,
382 object attributeValue2
)
384 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
385 attrs
.Add(attributeName1
, attributeValue1
);
386 attrs
.Add(attributeName2
, attributeValue2
);
390 private void Begin(string expr
,
391 string attributeName1
,
392 object attributeValue1
,
393 string attributeName2
,
394 object attributeValue2
,
395 string attributeName3
,
396 object attributeValue3
)
398 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
399 attrs
.Add(attributeName1
, attributeValue1
);
400 attrs
.Add(attributeName2
, attributeValue2
);
401 attrs
.Add(attributeName3
, attributeValue3
);
405 private void End(DbExpression expr
)
407 End(expr
.GetType().Name
);
410 private void BeginUnary(DbUnaryExpression e
)
418 private void BeginBinary(DbBinaryExpression e
)
430 #region DbExpressionVisitor<DbExpression> Members
432 public override void Visit(DbExpression e
)
438 public override void Visit(DbConstantExpression e
)
440 Dictionary
<string, object> attrs
= new Dictionary
<string,object>();
441 attrs
.Add("Value", e
.Value
);
446 public override void Visit(DbNullExpression e
)
452 public override void Visit(DbVariableReferenceExpression e
)
454 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
455 attrs
.Add("VariableName", e
.VariableName
);
460 public override void Visit(DbParameterReferenceExpression e
)
462 Dictionary
<string, object> attrs
= new Dictionary
<string, object>();
463 attrs
.Add("ParameterName", e
.ParameterName
);
468 public override void Visit(DbFunctionExpression e
)
472 Dump(e
.Arguments
, "Arguments", "Argument");
476 public override void Visit(DbLambdaExpression expression
)
479 Dump(expression
.Lambda
);
480 Dump(expression
.Arguments
, "Arguments", "Argument");
484 #if METHOD_EXPRESSION
485 public override void Visit(MethodExpression e
)
489 Dump(e
.Arguments
, "Arguments", "Argument");
490 if (e
.Instance
!= null)
492 Dump(e
.Instance
, "Instance");
498 public override void Visit(DbPropertyExpression e
)
501 // Currently the DbPropertyExpression.EdmProperty member property may only be either:
503 // - RelationshipEndMember
504 // - NavigationProperty
507 RelationshipEndMember end
= e
.Property
as RelationshipEndMember
;
510 Dump(end
, "Property");
512 else if (Helper
.IsNavigationProperty(e
.Property
))
514 Dump((NavigationProperty
)e
.Property
, "Property");
518 Dump((EdmProperty
)e
.Property
);
521 if (e
.Instance
!= null)
523 Dump(e
.Instance
, "Instance");
528 public override void Visit(DbComparisonExpression e
)
534 public override void Visit(DbLikeExpression e
)
537 Dump(e
.Argument
, "Argument");
538 Dump(e
.Pattern
, "Pattern");
539 Dump(e
.Escape
, "Escape");
543 public override void Visit(DbLimitExpression e
)
545 Begin(e
, "WithTies", e
.WithTies
);
546 Dump(e
.Argument
, "Argument");
547 Dump(e
.Limit
, "Limit");
551 public override void Visit(DbIsNullExpression e
)
557 public override void Visit(DbArithmeticExpression e
)
560 Dump(e
.Arguments
, "Arguments", "Argument");
564 public override void Visit(DbAndExpression e
)
570 public override void Visit(DbOrExpression e
)
576 public override void Visit(DbNotExpression e
)
582 public override void Visit(DbDistinctExpression e
)
588 public override void Visit(DbElementExpression e
)
594 public override void Visit(DbIsEmptyExpression e
)
600 public override void Visit(DbUnionAllExpression e
)
606 public override void Visit(DbIntersectExpression e
)
612 public override void Visit(DbExceptExpression e
)
618 public override void Visit(DbTreatExpression e
)
624 public override void Visit(DbIsOfExpression e
)
627 Dump(e
.OfType
, "OfType") ;
631 public override void Visit(DbCastExpression e
)
637 public override void Visit(DbCaseExpression e
)
640 Dump(e
.When
, "Whens", "When");
641 Dump(e
.Then
, "Thens", "Then");
642 Dump(e
.Else
, "Else");
645 public override void Visit(DbOfTypeExpression e
)
648 Dump(e
.OfType
, "OfType");
652 public override void Visit(DbNewInstanceExpression e
)
655 Dump(e
.Arguments
, "Arguments", "Argument");
656 if (e
.HasRelatedEntityReferences
)
658 Begin("RelatedEntityReferences");
659 foreach (DbRelatedEntityRef relatedRef
in e
.RelatedEntityReferences
)
661 Begin("DbRelatedEntityRef");
662 Dump(relatedRef
.SourceEnd
, "SourceEnd");
663 Dump(relatedRef
.TargetEnd
, "TargetEnd");
664 Dump(relatedRef
.TargetEntityReference
, "TargetEntityReference");
665 End("DbRelatedEntityRef");
667 End("RelatedEntityReferences");
672 public override void Visit(DbRelationshipNavigationExpression e
)
675 Dump(e
.NavigateFrom
, "NavigateFrom");
676 Dump(e
.NavigateTo
, "NavigateTo");
677 Dump(e
.Relationship
, "Relationship");
678 Dump(e
.NavigationSource
, "NavigationSource");
682 public override void Visit(DbRefExpression e
)
688 public override void Visit(DbDerefExpression e
)
694 public override void Visit(DbRefKeyExpression e
)
700 public override void Visit(DbEntityRefExpression e
)
706 public override void Visit(DbScanExpression e
)
709 Begin("Target", "Name", e
.Target
.Name
, "Container", e
.Target
.EntityContainer
.Name
);
710 Dump(e
.Target
.ElementType
, "TargetElementType");
715 public override void Visit(DbFilterExpression e
)
718 Dump(e
.Input
, "Input");
719 Dump(e
.Predicate
, "Predicate");
723 public override void Visit(DbProjectExpression e
)
726 Dump(e
.Input
, "Input");
727 Dump(e
.Projection
, "Projection");
731 public override void Visit(DbCrossJoinExpression e
)
735 foreach (DbExpressionBinding binding
in e
.Inputs
)
737 Dump(binding
, "Input");
743 public override void Visit(DbJoinExpression e
)
746 Dump(e
.Left
, "Left");
747 Dump(e
.Right
, "Right");
748 Dump(e
.JoinCondition
, "JoinCondition");
752 public override void Visit(DbApplyExpression e
)
755 Dump(e
.Input
, "Input");
756 Dump(e
.Apply
, "Apply");
760 public override void Visit(DbGroupByExpression e
)
763 Dump(e
.Input
, "Input");
764 Dump(e
.Keys
, "Keys", "Key");
766 foreach (DbAggregate agg
in e
.Aggregates
)
768 DbFunctionAggregate funcAgg
= agg
as DbFunctionAggregate
;
772 Begin("DbFunctionAggregate");
773 Dump(funcAgg
.Function
);
774 Dump(funcAgg
.Arguments
, "Arguments", "Argument");
775 End("DbFunctionAggregate");
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");
790 protected virtual void Dump(IList
<DbSortClause
> sortOrder
)
793 foreach (DbSortClause clause
in sortOrder
)
795 string collStr
= clause
.Collation
;
801 Begin("DbSortClause", "Ascending", clause
.Ascending
, "Collation", collStr
);
802 Dump(clause
.Expression
, "Expression");
808 public override void Visit(DbSkipExpression e
)
811 Dump(e
.Input
, "Input");
813 Dump(e
.Count
, "Count");
817 public override void Visit(DbSortExpression e
)
820 Dump(e
.Input
, "Input");
825 public override void Visit(DbQuantifierExpression e
)
828 Dump(e
.Input
, "Input");
829 Dump(e
.Predicate
, "Predicate");