Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Common / CommandTrees / Internal / ExpressionDumper.cs
blob3f57a0ac57405c0762d2401bdf141a112c2864df
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 //---------------------------------------------------------------------
10 using System;
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
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
25 #region Constructors
26 internal ExpressionDumper() { }
27 #endregion
29 #region (Pseudo) Public API
31 /// <summary>
32 /// Begins a new Dump block with the specified name
33 /// </summary>
34 /// <param name="name">The name of the block</param>
35 internal void Begin(string name) { Begin(name, (Dictionary<string, object>)null); }
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>
42 internal abstract void Begin(string name, Dictionary<string, object> attrs);
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>
50 internal abstract void End(string name);
52 /// <summary>
53 /// Dumps a DbExpression by visiting it.
54 /// </summary>
55 /// <param name="target">The DbExpression to dump</param>
56 internal void Dump(DbExpression target)
58 target.Accept(this);
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>
66 internal void Dump(DbExpression e, string name)
68 Begin(name);
69 Dump(e);
70 End(name);
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>
78 internal void Dump(DbExpressionBinding binding, string name)
80 Begin(name);
81 Dump(binding);
82 End(name);
85 /// <summary>
86 /// Dumps a DbExpressionBinding including its VariableName and DbExpression
87 /// </summary>
88 /// <param name="binding">The DbExpressionBinding to dump</param>
89 internal void Dump(DbExpressionBinding binding)
91 Begin("DbExpressionBinding", "VariableName", binding.VariableName);
92 Begin("Expression");
93 Dump(binding.Expression);
94 End("Expression");
95 End("DbExpressionBinding");
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>
104 internal void Dump(DbGroupExpressionBinding binding, string name)
106 Begin(name);
107 Dump(binding);
108 End(name);
111 /// <summary>
112 /// Dumps a DbGroupExpressionBinding including its VariableName, GroupVariableName and DbExpression
113 /// </summary>
114 /// <param name="binding">The DbGroupExpressionBinding to dump</param>
115 internal void Dump(DbGroupExpressionBinding binding)
117 Begin("DbGroupExpressionBinding", "VariableName", binding.VariableName, "GroupVariableName", binding.GroupVariableName);
118 Begin("Expression");
119 Dump(binding.Expression);
120 End("Expression");
121 End("DbGroupExpressionBinding");
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>
132 internal void Dump(IEnumerable<DbExpression> exprs, string pluralName, string singularName)
134 Begin(pluralName);
136 foreach (DbExpression expr in exprs)
138 Begin(singularName);
139 this.Dump(expr);
140 End(singularName);
143 End(pluralName);
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>
152 internal void Dump(IEnumerable<FunctionParameter> paramList)
154 Begin("Parameters");
155 foreach (FunctionParameter param in paramList)
157 Begin("Parameter", "Name", param.Name);
158 Dump(param.TypeUsage, "ParameterType");
159 End("Parameter");
161 End("Parameters");
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>
169 internal void Dump(TypeUsage type, string name)
171 Begin(name);
172 Dump(type);
173 End(name);
176 /// <summary>
177 /// Dumps the specified Type metadata instance
178 /// </summary>
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);
189 Dump(type.EdmType);
190 End("TypeUsage");
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>
198 internal void Dump(EdmType type, string name)
200 Begin(name);
201 Dump(type);
202 End(name);
205 /// <summary>
206 /// Dumps the specified type metadata instance
207 /// </summary>
208 /// <param name="type">The type metadata to dump</param>
209 internal void Dump(EdmType type)
211 Begin("EdmType",
212 "BuiltInTypeKind", Enum.GetName(typeof(BuiltInTypeKind), type.BuiltInTypeKind),
213 "Namespace", type.NamespaceName,
214 "Name", type.Name);
215 End("EdmType");
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>
223 internal void Dump(RelationshipType type, string name)
225 Begin(name);
226 Dump(type);
227 End(name);
230 /// <summary>
231 /// Dumps the specified Relation metadata instance
232 /// </summary>
233 /// <param name="type">The Relation metadata to dump</param>
234 internal void Dump(RelationshipType type)
236 Begin(
237 "RelationshipType",
238 "Namespace", type.NamespaceName,
239 "Name",
240 type.Name
242 End("RelationshipType");
245 /// <summary>
246 /// Dumps the specified EdmFunction metadata instance
247 /// </summary>
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");
257 else
259 Begin("ReturnTypes");
260 foreach (var returnParameter in function.ReturnParameters)
262 Dump(returnParameter.TypeUsage, returnParameter.Name);
264 End("ReturnTypes");
266 End("Function");
269 /// <summary>
270 /// Dumps the specified EdmProperty metadata instance
271 /// </summary>
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");
278 End("Property");
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>
286 internal void Dump(RelationshipEndMember end, string name)
288 Begin(name);
289 Begin(
290 "RelationshipEndMember",
291 "Name", end.Name,
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");
298 End(name);
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>
306 internal void Dump(NavigationProperty navProp, string name)
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
316 Dump(navProp.DeclaringType, "DeclaringType");
317 Dump(navProp.TypeUsage, "PropertyType");
318 End("NavigationProperty");
319 End(name);
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>
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");
335 #endif
337 /// <summary>
338 /// Dumps the specified DbLambda instance
339 /// </summary>
340 /// <param name="lambda">The DbLambda to dump.</param>
341 internal void Dump(DbLambda lambda)
343 Begin("DbLambda");
344 Dump(System.Linq.Enumerable.Cast<DbExpression>(lambda.Variables), "Variables", "Variable");
345 Dump(lambda.Body, "Body");
346 End("DbLambda");
349 #endregion
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);
368 Begin(expr, attrs);
371 private void Begin(string expr, string attributeName, object attributeValue)
373 Dictionary<string, object> attrs = new Dictionary<string, object>();
374 attrs.Add(attributeName, attributeValue);
375 Begin(expr, attrs);
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);
387 Begin(expr, attrs);
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);
402 Begin(expr, attrs);
405 private void End(DbExpression expr)
407 End(expr.GetType().Name);
410 private void BeginUnary(DbUnaryExpression e)
412 Begin(e);
413 Begin("Argument");
414 Dump(e.Argument);
415 End("Argument");
418 private void BeginBinary(DbBinaryExpression e)
420 Begin(e);
421 Begin("Left");
422 Dump(e.Left);
423 End("Left");
424 Begin("Right");
425 Dump(e.Right);
426 End("Right");
428 #endregion
430 #region DbExpressionVisitor<DbExpression> Members
432 public override void Visit(DbExpression e)
434 Begin(e);
435 End(e);
438 public override void Visit(DbConstantExpression e)
440 Dictionary<string, object> attrs = new Dictionary<string,object>();
441 attrs.Add("Value", e.Value);
442 Begin(e, attrs);
443 End(e);
446 public override void Visit(DbNullExpression e)
448 Begin(e);
449 End(e);
452 public override void Visit(DbVariableReferenceExpression e)
454 Dictionary<string, object> attrs = new Dictionary<string, object>();
455 attrs.Add("VariableName", e.VariableName);
456 Begin(e, attrs);
457 End(e);
460 public override void Visit(DbParameterReferenceExpression e)
462 Dictionary<string, object> attrs = new Dictionary<string, object>();
463 attrs.Add("ParameterName", e.ParameterName);
464 Begin(e, attrs);
465 End(e);
468 public override void Visit(DbFunctionExpression e)
470 Begin(e);
471 Dump(e.Function);
472 Dump(e.Arguments, "Arguments", "Argument");
473 End(e);
476 public override void Visit(DbLambdaExpression expression)
478 Begin(expression);
479 Dump(expression.Lambda);
480 Dump(expression.Arguments, "Arguments", "Argument");
481 End(expression);
484 #if METHOD_EXPRESSION
485 public override void Visit(MethodExpression e)
487 Begin(e);
488 Dump(e.Method);
489 Dump(e.Arguments, "Arguments", "Argument");
490 if (e.Instance != null)
492 Dump(e.Instance, "Instance");
494 End(e);
496 #endif
498 public override void Visit(DbPropertyExpression e)
501 // Currently the DbPropertyExpression.EdmProperty member property may only be either:
502 // - EdmProperty
503 // - RelationshipEndMember
504 // - NavigationProperty
506 Begin(e);
507 RelationshipEndMember end = e.Property as RelationshipEndMember;
508 if (end != null)
510 Dump(end, "Property");
512 else if (Helper.IsNavigationProperty(e.Property))
514 Dump((NavigationProperty)e.Property, "Property");
516 else
518 Dump((EdmProperty)e.Property);
521 if (e.Instance != null)
523 Dump(e.Instance, "Instance");
525 End(e);
528 public override void Visit(DbComparisonExpression e)
530 BeginBinary(e);
531 End(e);
534 public override void Visit(DbLikeExpression e)
536 Begin(e);
537 Dump(e.Argument, "Argument");
538 Dump(e.Pattern, "Pattern");
539 Dump(e.Escape, "Escape");
540 End(e);
543 public override void Visit(DbLimitExpression e)
545 Begin(e, "WithTies", e.WithTies);
546 Dump(e.Argument, "Argument");
547 Dump(e.Limit, "Limit");
548 End(e);
551 public override void Visit(DbIsNullExpression e)
553 BeginUnary(e);
554 End(e);
557 public override void Visit(DbArithmeticExpression e)
559 Begin(e);
560 Dump(e.Arguments, "Arguments", "Argument");
561 End(e);
564 public override void Visit(DbAndExpression e)
566 BeginBinary(e);
567 End(e);
570 public override void Visit(DbOrExpression e)
572 BeginBinary(e);
573 End(e);
576 public override void Visit(DbNotExpression e)
578 BeginUnary(e);
579 End(e);
582 public override void Visit(DbDistinctExpression e)
584 BeginUnary(e);
585 End(e);
588 public override void Visit(DbElementExpression e)
590 BeginUnary(e);
591 End(e);
594 public override void Visit(DbIsEmptyExpression e)
596 BeginUnary(e);
597 End(e);
600 public override void Visit(DbUnionAllExpression e)
602 BeginBinary(e);
603 End(e);
606 public override void Visit(DbIntersectExpression e)
608 BeginBinary(e);
609 End(e);
612 public override void Visit(DbExceptExpression e)
614 BeginBinary(e);
615 End(e);
618 public override void Visit(DbTreatExpression e)
620 BeginUnary(e);
621 End(e);
624 public override void Visit(DbIsOfExpression e)
626 BeginUnary(e);
627 Dump(e.OfType, "OfType") ;
628 End(e);
631 public override void Visit(DbCastExpression e)
633 BeginUnary(e);
634 End(e);
637 public override void Visit(DbCaseExpression e)
639 Begin(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)
647 BeginUnary(e);
648 Dump(e.OfType, "OfType");
649 End(e);
652 public override void Visit(DbNewInstanceExpression e)
654 Begin(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");
669 End(e);
672 public override void Visit(DbRelationshipNavigationExpression e)
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);
682 public override void Visit(DbRefExpression e)
684 BeginUnary(e);
685 End(e);
688 public override void Visit(DbDerefExpression e)
690 BeginUnary(e);
691 End(e);
694 public override void Visit(DbRefKeyExpression e)
696 BeginUnary(e);
697 End(e);
700 public override void Visit(DbEntityRefExpression e)
702 BeginUnary(e);
703 End(e);
706 public override void Visit(DbScanExpression e)
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);
715 public override void Visit(DbFilterExpression e)
717 Begin(e);
718 Dump(e.Input, "Input");
719 Dump(e.Predicate, "Predicate");
720 End(e);
723 public override void Visit(DbProjectExpression e)
725 Begin(e);
726 Dump(e.Input, "Input");
727 Dump(e.Projection, "Projection");
728 End(e);
731 public override void Visit(DbCrossJoinExpression e)
733 Begin(e);
734 Begin("Inputs");
735 foreach (DbExpressionBinding binding in e.Inputs)
737 Dump(binding, "Input");
739 End("Inputs");
740 End(e);
743 public override void Visit(DbJoinExpression e)
745 Begin(e);
746 Dump(e.Left, "Left");
747 Dump(e.Right, "Right");
748 Dump(e.JoinCondition, "JoinCondition");
749 End(e);
752 public override void Visit(DbApplyExpression e)
754 Begin(e);
755 Dump(e.Input, "Input");
756 Dump(e.Apply, "Apply");
757 End(e);
760 public override void Visit(DbGroupByExpression e)
762 Begin(e);
763 Dump(e.Input, "Input");
764 Dump(e.Keys, "Keys", "Key");
765 Begin("Aggregates");
766 foreach (DbAggregate agg in e.Aggregates)
768 DbFunctionAggregate funcAgg = agg as DbFunctionAggregate;
770 if (funcAgg != null)
772 Begin("DbFunctionAggregate");
773 Dump(funcAgg.Function);
774 Dump(funcAgg.Arguments, "Arguments", "Argument");
775 End("DbFunctionAggregate");
777 else
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");
786 End("Aggregates");
787 End(e);
790 protected virtual void Dump(IList<DbSortClause> sortOrder)
792 Begin("SortOrder");
793 foreach (DbSortClause clause in sortOrder)
795 string collStr = clause.Collation;
796 if (null == collStr)
798 collStr = "";
801 Begin("DbSortClause", "Ascending", clause.Ascending, "Collation", collStr);
802 Dump(clause.Expression, "Expression");
803 End("DbSortClause");
805 End("SortOrder");
808 public override void Visit(DbSkipExpression e)
810 Begin(e);
811 Dump(e.Input, "Input");
812 Dump(e.SortOrder);
813 Dump(e.Count, "Count");
814 End(e);
817 public override void Visit(DbSortExpression e)
819 Begin(e);
820 Dump(e.Input, "Input");
821 Dump(e.SortOrder);
822 End(e);
825 public override void Visit(DbQuantifierExpression e)
827 Begin(e);
828 Dump(e.Input, "Input");
829 Dump(e.Predicate, "Predicate");
830 End(e);
833 #endregion