Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / Dump.cs / 2 / Dump.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....], [....]
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Query.PlanCompiler;
using System.Globalization;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Xml;
using md = System.Data.Metadata.Edm;
//
// This module serves as a dump routine for an IQT
// The output is a weird form of Sql - closer to Quel (and perhaps, C#
// comprehensions)
//
namespace System.Data.Query.InternalTrees {
///
/// A dump module for the Iqt
///
internal class Dump : BasicOpVisitor, IDisposable {
#region private state
private XmlWriter _writer;
#endregion
#region constructors
private Dump(Stream stream)
: this(stream, Dump.DefaultEncoding, true) { }
private Dump(Stream stream, Encoding encoding, bool indent)
: base() {
XmlWriterSettings settings = new XmlWriterSettings();
settings.CheckCharacters = false;
settings.Indent = true;
settings.Encoding = encoding;
_writer = XmlWriter.Create(stream, settings);
_writer.WriteStartDocument(true);
}
#endregion
#region "public" surface
internal static readonly Encoding DefaultEncoding = Encoding.UTF8;
///
/// Driver method to dump the entire tree
///
///
///
static internal string ToXml(Command itree) {
return ToXml(itree, itree.Root);
}
///
/// Driver method to dump the a subtree of a tree
///
///
///
///
static internal string ToXml(Command itree, Node subtree) {
MemoryStream stream = new MemoryStream();
using (Dump dumper = new Dump(stream)) {
// Just in case the node we're provided doesn't dump as XML, we'll always stick
// an XML wrapper around it -- this happens when we're dumping scalarOps, for
// example, and it's a bummer if you can't debug them using a dump...
using (new AutoXml(dumper, "nodes")) {
dumper.VisitNode(subtree);
}
}
return DefaultEncoding.GetString(stream.ToArray());
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Scope = "member", Target = "System.Data.Query.InternalTrees.Dump.ToXml")]
static internal string ToXml(ColumnMap columnMap) {
MemoryStream stream = new MemoryStream();
using (Dump dumper = new Dump(stream)) {
// Just in case the node we're provided doesn't dump as XML, we'll always stick
// an XML wrapper around it -- this happens when we're dumping scalarOps, for
// example, and it's a bummer if you can't debug them using a dump...
using (new AutoXml(dumper, "columnMap")) {
columnMap.Accept(ColumnMapDumper.Instance, dumper);
}
}
return DefaultEncoding.GetString(stream.ToArray());
}
#endregion
#region Begin/End management
void IDisposable.Dispose() {
try {
_writer.WriteEndDocument();
_writer.Flush();
_writer.Close();
}
catch (Exception e) {
if (!EntityUtil.IsCatchableExceptionType(e)) {
throw;
}
// eat this exception; we don't care if the dumper is failing...
}
}
internal void Begin(string name, Dictionary attrs) {
_writer.WriteStartElement(name);
if (attrs != null) {
foreach (KeyValuePair attr in attrs) {
_writer.WriteAttributeString(attr.Key, attr.Value.ToString());
}
}
}
internal void BeginExpression() {
WriteString("(");
}
internal void EndExpression() {
WriteString(")");
}
internal void End(string name) {
_writer.WriteEndElement();
}
internal void WriteString(string value) {
_writer.WriteString(value);
}
#endregion
#region VisitorMethods
protected override void VisitDefault(Node n) {
using (new AutoXml(this, n.Op)) {
base.VisitDefault(n);
}
}
protected override void VisitScalarOpDefault(ScalarOp op, Node n) {
using (new AutoString(this, op)) {
string separator = string.Empty;
foreach (Node chi in n.Children) {
WriteString(separator);
VisitNode(chi);
separator = ",";
}
}
}
protected override void VisitJoinOp(JoinBaseOp op, Node n) {
using (new AutoXml(this, op)) {
if (n.Children.Count > 2) {
using (new AutoXml(this, "condition")) {
VisitNode(n.Child2);
}
}
using (new AutoXml(this, "input")) {
VisitNode(n.Child0);
}
using (new AutoXml(this, "input")) {
VisitNode(n.Child1);
}
}
}
public override void Visit(CaseOp op, Node n) {
using (new AutoXml(this, op)) {
int i = 0;
while (i < n.Children.Count) {
if ((i + 1) < n.Children.Count) {
using (new AutoXml(this, "when")) {
VisitNode(n.Children[i++]);
}
using (new AutoXml(this, "then")) {
VisitNode(n.Children[i++]);
}
}
else {
using (new AutoXml(this, "else")) {
VisitNode(n.Children[i++]);
}
}
}
}
}
public override void Visit(CollectOp op, Node n) {
using (new AutoXml(this, op)) {
VisitChildren(n);
}
}
protected override void VisitConstantOp(ConstantBaseOp op, Node n) {
using (new AutoString(this, op)) {
if (null == op.Value) {
WriteString("null");
}
else {
WriteString("(");
WriteString(op.Value.GetType().Name);
WriteString(")");
WriteString(String.Format(CultureInfo.InvariantCulture,"{0}",op.Value));
}
VisitChildren(n);
}
}
public override void Visit(DistinctOp op, Node n) {
Dictionary attrs = new Dictionary();
StringBuilder sb = new StringBuilder();
string separator = string.Empty;
foreach (Var v in op.Keys) {
sb.Append(separator);
sb.Append(v.Id);
separator = ",";
}
if (0 != sb.Length) {
attrs.Add("Keys", sb.ToString());
}
using (new AutoXml(this, op, attrs)) {
VisitChildren(n);
}
}
public override void Visit(GroupByOp op, Node n) {
Dictionary attrs = new Dictionary();
StringBuilder sb = new StringBuilder();
string separator = string.Empty;
foreach (Var v in op.Keys) {
sb.Append(separator);
sb.Append(v.Id);
separator = ",";
}
if (0 != sb.Length) {
attrs.Add("Keys", sb.ToString());
}
using (new AutoXml(this, op, attrs)) {
using (new AutoXml(this, "outputs")) {
foreach (Var v in op.Outputs) {
DumpVar(v);
}
}
VisitChildren(n);
}
}
public override void Visit(IsOfOp op, Node n)
{
using (new AutoXml(this, ( op.IsOfOnly ? "IsOfOnly" : "IsOf" )))
{
string separator = string.Empty;
foreach (Node chi in n.Children)
{
WriteString(separator);
VisitNode(chi);
separator = ",";
}
}
}
protected override void VisitNestOp(NestBaseOp op, Node n) {
Dictionary attrs = new Dictionary();
SingleStreamNestOp ssnOp = op as SingleStreamNestOp;
if (null != ssnOp) {
attrs.Add("Discriminator", (ssnOp.Discriminator == null) ? "" : ssnOp.Discriminator.ToString());
}
StringBuilder sb = new StringBuilder();
string separator;
if (null != ssnOp) {
sb.Length = 0;
separator = string.Empty;
foreach (Var v in ssnOp.Keys) {
sb.Append(separator);
sb.Append(v.Id);
separator = ",";
}
if (0 != sb.Length) {
attrs.Add("Keys", sb.ToString());
}
}
using (new AutoXml(this, op, attrs)) {
using (new AutoXml(this, "outputs")) {
foreach (Var v in op.Outputs) {
DumpVar(v);
}
}
foreach (CollectionInfo ci in op.CollectionInfo) {
Dictionary attrs2 = new Dictionary();
attrs2.Add("CollectionVar", ci.CollectionVar);
if (null != ci.DiscriminatorValue) {
attrs2.Add("DiscriminatorValue", ci.DiscriminatorValue);
}
if (0 != ci.FlattenedElementVars.Count) {
attrs2.Add("FlattenedElementVars", FormatVarList(sb, ci.FlattenedElementVars));
}
if (0 != ci.Keys.Count) {
attrs2.Add("Keys", ci.Keys);
}
if (0 != ci.SortKeys.Count) {
attrs2.Add("SortKeys", FormatVarList(sb, ci.SortKeys));
}
using (new AutoXml(this, "collection", attrs2)) {
ci.ColumnMap.Accept(ColumnMapDumper.Instance, this);
}
}
VisitChildren(n);
}
}
private static string FormatVarList(StringBuilder sb, VarList varList) {
string separator;
sb.Length = 0;
separator = string.Empty;
foreach (Var v in varList) {
sb.Append(separator);
sb.Append(v.Id);
separator = ",";
}
return sb.ToString();
}
private static string FormatVarList(StringBuilder sb, List varList) {
string separator;
sb.Length = 0;
separator = string.Empty;
foreach (SortKey v in varList) {
sb.Append(separator);
sb.Append(v.Var.Id);
separator = ",";
}
return sb.ToString();
}
private void VisitNewOp(Op op, Node n) {
using (new AutoXml(this, op)) {
foreach (Node chi in n.Children) {
using (new AutoXml(this, "argument", null)) {
VisitNode(chi);
}
}
}
}
public override void Visit(NewEntityOp op, Node n) {
VisitNewOp(op, n);
}
public override void Visit(NewInstanceOp op, Node n) {
VisitNewOp(op, n);
}
public override void Visit(DiscriminatedNewEntityOp op, Node n) {
VisitNewOp(op, n);
}
public override void Visit(NewMultisetOp op, Node n) {
VisitNewOp(op, n);
}
public override void Visit(NewRecordOp op, Node n) {
VisitNewOp(op, n);
}
public override void Visit(PhysicalProjectOp op, Node n) {
using (new AutoXml(this, op)) {
using (new AutoXml(this, "outputs")) {
foreach (Var v in op.Outputs) {
DumpVar(v);
}
}
using (new AutoXml(this, "columnMap")) {
op.ColumnMap.Accept(ColumnMapDumper.Instance, this);
}
using (new AutoXml(this, "input")) {
VisitChildren(n);
}
}
}
public override void Visit(ProjectOp op, Node n) {
using (new AutoXml(this, op)) {
using (new AutoXml(this, "outputs")) {
foreach (Var v in op.Outputs) {
DumpVar(v);
}
}
VisitChildren(n);
}
}
public override void Visit(PropertyOp op, Node n) {
using (new AutoString(this, op)) {
VisitChildren(n);
WriteString(".");
WriteString(op.PropertyInfo.Name);
}
}
public override void Visit(RelPropertyOp op, Node n) {
using (new AutoString(this, op)) {
VisitChildren(n);
WriteString(".NAVIGATE(");
WriteString(op.PropertyInfo.Relationship.Name);
WriteString(",");
WriteString(op.PropertyInfo.FromEnd.Name);
WriteString(",");
WriteString(op.PropertyInfo.ToEnd.Name);
WriteString(")");
}
}
public override void Visit(ScanTableOp op, Node n) {
using (new AutoXml(this, op)) {
DumpTable(op.Table);
VisitChildren(n);
}
}
public override void Visit(ScanViewOp op, Node n) {
using (new AutoXml(this, op)) {
DumpTable(op.Table);
VisitChildren(n);
}
}
protected override void VisitSetOp(SetOp op, Node n) {
Dictionary attrs = new Dictionary();
if (OpType.UnionAll == op.OpType) {
UnionAllOp uallOp = (UnionAllOp)op;
if (null != uallOp.BranchDiscriminator) {
attrs.Add("branchDiscriminator", uallOp.BranchDiscriminator);
}
}
using (new AutoXml(this, op, attrs)) {
using (new AutoXml(this, "outputs")) {
foreach (Var v in op.Outputs) {
DumpVar(v);
}
}
int i = 0;
foreach (Node chi in n.Children) {
Dictionary attrs2 = new Dictionary();
attrs2.Add("VarMap", op.VarMap[i++].ToString());
using (new AutoXml(this, "input", attrs2)) {
VisitNode(chi);
}
}
}
}
public override void Visit(SortOp op, Node n) {
using (new AutoXml(this, op)) {
base.Visit(op, n);
}
}
public override void Visit(ConstrainedSortOp op, Node n) {
Dictionary attrs = new Dictionary();
attrs.Add("WithTies", op.WithTies);
using (new AutoXml(this, op, attrs)) {
base.Visit(op, n);
}
}
protected override void VisitSortOp(SortBaseOp op, Node n)
{
using (new AutoXml(this, "keys")) {
foreach (InternalTrees.SortKey sortKey in op.Keys) {
Dictionary attrs = new Dictionary();
attrs.Add("Var", sortKey.Var);
attrs.Add("Ascending", sortKey.AscendingSort);
attrs.Add("Collation", sortKey.Collation);
using (new AutoXml(this, "sortKey", attrs)) {
}
}
}
VisitChildren(n);
}
public override void Visit(UnnestOp op, Node n) {
Dictionary attrs = new Dictionary();
if (null != op.Var) {
attrs.Add("Var", op.Var.Id);
}
using (new AutoXml(this, op, attrs)) {
DumpTable(op.Table);
VisitChildren(n);
}
}
public override void Visit(VarDefOp op, Node n) {
Dictionary attrs = new Dictionary();
attrs.Add("Var", op.Var.Id);
using (new AutoXml(this, op, attrs)) {
VisitChildren(n);
}
}
public override void Visit(VarRefOp op, Node n) {
using (new AutoString(this, op)) {
VisitChildren(n);
if (null != op.Type) {
WriteString("Type=");
WriteString(TypeHelpers.GetFullName(op.Type));
WriteString(", ");
}
WriteString("Var=");
WriteString(op.Var.Id.ToString(CultureInfo.InvariantCulture));
}
}
#endregion
#region dumper helpers
private void DumpVar(Var v) {
Dictionary attrs = new Dictionary();
attrs.Add("Var", v.Id);
ColumnVar cv = v as ColumnVar;
if (null != cv) {
attrs.Add("Name", cv.ColumnMetadata.Name);
attrs.Add("Type", TypeHelpers.GetFullName(cv.ColumnMetadata.Type));
}
using (new AutoXml(this, v.GetType().Name, attrs)) {
}
}
private void DumpVars(List vars) {
foreach (Var v in vars) {
DumpVar(v);
}
}
private void DumpTable(Table table) {
Dictionary attrs = new Dictionary();
attrs.Add("Table", table.TableId);
if (null != table.TableMetadata.Extent) {
attrs.Add("Extent", table.TableMetadata.Extent.Name);
}
using (new AutoXml(this, "Table", attrs)) {
DumpVars(table.Columns);
}
}
#region ColumnMap dumper
internal class ColumnMapDumper : ColumnMapVisitor {
static internal ColumnMapDumper Instance = new ColumnMapDumper();
///
/// Private constructor
///
private ColumnMapDumper()
{
}
#region Helpers
///
/// Common CollectionColumnMap code
///
private void DumpCollection(CollectionColumnMap columnMap, Dump dumper) {
if (columnMap.ForeignKeys.Length > 0) {
using (new AutoXml(dumper, "foreignKeys")) {
VisitList(columnMap.ForeignKeys, dumper);
}
}
if (columnMap.Keys.Length > 0) {
using (new AutoXml(dumper, "keys")) {
VisitList(columnMap.Keys, dumper);
}
}
using (new AutoXml(dumper, "element")) {
columnMap.Element.Accept(this, dumper);
}
}
///
/// Common code to produce an the attributes for the dumper's XML node
///
///
///
private static Dictionary GetAttributes(ColumnMap columnMap) {
Dictionary attrs = new Dictionary();
attrs.Add("Type", columnMap.Type.ToString());
return attrs;
}
#endregion
///
/// ComplexTypeColumnMap
///
///
///
///
internal override void Visit(ComplexTypeColumnMap columnMap, Dump dumper) {
using (new AutoXml(dumper, "ComplexType", GetAttributes(columnMap))) {
if (columnMap.NullSentinel != null) {
using (new AutoXml(dumper, "nullSentinel")) {
columnMap.NullSentinel.Accept(this, dumper);
}
}
VisitList(columnMap.Properties, dumper);
}
}
///
/// DiscriminatedCollectionColumnMap
///
///
///
///
internal override void Visit(DiscriminatedCollectionColumnMap columnMap, Dump dumper) {
using (new AutoXml(dumper, "DiscriminatedCollection", GetAttributes(columnMap))) {
Dictionary attrs = new Dictionary();
attrs.Add("Value", columnMap.DiscriminatorValue);
using (new AutoXml(dumper, "discriminator", attrs)) {
columnMap.Discriminator.Accept(this, dumper);
}
DumpCollection(columnMap, dumper);
}
}
///
/// EntityColumnMap
///
///
///
///
internal override void Visit(EntityColumnMap columnMap, Dump dumper) {
using (new AutoXml(dumper, "Entity", GetAttributes(columnMap))) {
using (new AutoXml(dumper, "entityIdentity")) {
VisitEntityIdentity(columnMap.EntityIdentity, dumper);
}
VisitList(columnMap.Properties, dumper);
}
}
///
/// PolymorphicColumnMap
///
///
///
///
internal override void Visit(SimplePolymorphicColumnMap columnMap, Dump dumper) {
using (new AutoXml(dumper, "SimplePolymorphic", GetAttributes(columnMap))) {
using (new AutoXml(dumper, "typeDiscriminator")) {
columnMap.TypeDiscriminator.Accept(this, dumper);
}
Dictionary attrs = new Dictionary();
foreach (KeyValuePair