You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,304 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ColumnMapCopier.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
using System.Data.Query.InternalTrees;
|
||||
using System.Data.Query.PlanCompiler;
|
||||
using System.Linq;
|
||||
using System.Data.Mapping;
|
||||
using System.Data.Metadata.Edm;
|
||||
|
||||
namespace System.Data.Query.InternalTrees
|
||||
{
|
||||
/// <summary>
|
||||
/// The ColumnMapCopier clones an entire ColumnMap hierarchy; this is different
|
||||
/// than the ColumnMapTranslator, which only copies things that need to be copied.
|
||||
///
|
||||
/// Note that this is a stateless visitor; it uses the visitor's argument for its
|
||||
/// state management.
|
||||
///
|
||||
/// The Visitor's argument is a VarMap; anytime a Var is found in the ColumnMap
|
||||
/// hierarchy, it is replaced with the replacement from the VarMap.
|
||||
///
|
||||
/// Note also that previous implementations of this class attempted to avoid re-
|
||||
/// processing ColumnMaps by caching the results for each input and returning it.
|
||||
/// I wasn't convinced that we were buying much with all that caching, since the
|
||||
/// only ColumnMaps that should be repeated in the hierarchy are simple ones; there
|
||||
/// is about as much object creation either way. The only reason I see that we
|
||||
/// want to cache these is if we really cared to have only one VarRefColumnMap
|
||||
/// instance for a given Var and be able to use reference equality instead of
|
||||
/// comparing the Vars themselves. I don't believe we're making that guarantee
|
||||
/// anywhere else, so I've removed that for now because I don't want the added
|
||||
/// complexity that the caching adds. If performance analysis indicates there is
|
||||
/// a problem, we can considier addding the cache back in.
|
||||
/// </summary>
|
||||
internal class ColumnMapCopier : ColumnMapVisitorWithResults<ColumnMap, VarMap>
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance for the "public" methods to use;
|
||||
/// </summary>
|
||||
static private ColumnMapCopier Instance = new ColumnMapCopier();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor; no one should use this.
|
||||
/// </summary>
|
||||
private ColumnMapCopier()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region "Public" surface area
|
||||
|
||||
/// <summary>
|
||||
/// Return a copy of the column map, replacing all vars with the replacements
|
||||
/// found in the replacementVarMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal static ColumnMap Copy(ColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
return columnMap.Accept(Instance, replacementVarMap);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Visitor Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Returns the var to use in the copy, either the original or the
|
||||
/// replacement. Note that we will follow the chain of replacements, in
|
||||
/// case the replacement was also replaced.
|
||||
/// </summary>
|
||||
/// <param name="originalVar"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
private static Var GetReplacementVar(Var originalVar, VarMap replacementVarMap)
|
||||
{
|
||||
// SQLBUDT #478509: Follow the chain of mapped vars, don't
|
||||
// just stop at the first one
|
||||
Var replacementVar = originalVar;
|
||||
|
||||
while (replacementVarMap.TryGetValue(replacementVar, out originalVar))
|
||||
{
|
||||
if (originalVar == replacementVar)
|
||||
{
|
||||
break;
|
||||
}
|
||||
replacementVar = originalVar;
|
||||
}
|
||||
return replacementVar;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Visitor Methods
|
||||
|
||||
#region List handling
|
||||
|
||||
/// <summary>
|
||||
/// Copies the List of ColumnMaps or SimpleColumnMaps
|
||||
/// </summary>
|
||||
/// <typeparam name="TListType"></typeparam>
|
||||
/// <param name="tList"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal TListType[] VisitList<TListType>(TListType[] tList, VarMap replacementVarMap)
|
||||
where TListType : ColumnMap
|
||||
{
|
||||
TListType[] newTList = new TListType[tList.Length];
|
||||
for(int i = 0; i < tList.Length; ++i) {
|
||||
newTList[i] = (TListType)tList[i].Accept(this, replacementVarMap);
|
||||
}
|
||||
return newTList;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EntityIdentity handling
|
||||
|
||||
/// <summary>
|
||||
/// Copies the DiscriminatedEntityIdentity
|
||||
/// </summary>
|
||||
/// <param name="entityIdentity"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
protected override EntityIdentity VisitEntityIdentity(DiscriminatedEntityIdentity entityIdentity, VarMap replacementVarMap)
|
||||
{
|
||||
SimpleColumnMap newEntitySetCol = (SimpleColumnMap)entityIdentity.EntitySetColumnMap.Accept(this, replacementVarMap);
|
||||
SimpleColumnMap[] newKeys = VisitList(entityIdentity.Keys, replacementVarMap);
|
||||
return new DiscriminatedEntityIdentity(newEntitySetCol, entityIdentity.EntitySetMap, newKeys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the SimpleEntityIdentity
|
||||
/// </summary>
|
||||
/// <param name="entityIdentity"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
protected override EntityIdentity VisitEntityIdentity(SimpleEntityIdentity entityIdentity, VarMap replacementVarMap)
|
||||
{
|
||||
SimpleColumnMap[] newKeys = VisitList(entityIdentity.Keys, replacementVarMap);
|
||||
return new SimpleEntityIdentity(entityIdentity.EntitySet, newKeys);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// ComplexTypeColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(ComplexTypeColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
SimpleColumnMap newNullability = columnMap.NullSentinel;
|
||||
if (null != newNullability)
|
||||
{
|
||||
newNullability = (SimpleColumnMap)newNullability.Accept(this, replacementVarMap);
|
||||
}
|
||||
ColumnMap[] fieldList = VisitList(columnMap.Properties, replacementVarMap);
|
||||
return new ComplexTypeColumnMap(columnMap.Type, columnMap.Name, fieldList, newNullability);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DiscriminatedCollectionColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(DiscriminatedCollectionColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
ColumnMap newElementColumnMap = columnMap.Element.Accept(this, replacementVarMap);
|
||||
SimpleColumnMap newDiscriminator = (SimpleColumnMap)columnMap.Discriminator.Accept(this, replacementVarMap);
|
||||
SimpleColumnMap[] newKeys = VisitList(columnMap.Keys, replacementVarMap);
|
||||
SimpleColumnMap[] newForeignKeys = VisitList(columnMap.ForeignKeys, replacementVarMap);
|
||||
return new DiscriminatedCollectionColumnMap(columnMap.Type, columnMap.Name, newElementColumnMap, newKeys, newForeignKeys, newDiscriminator, columnMap.DiscriminatorValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EntityColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(EntityColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
EntityIdentity newEntityIdentity = VisitEntityIdentity(columnMap.EntityIdentity, replacementVarMap);
|
||||
ColumnMap[] fieldList = VisitList(columnMap.Properties, replacementVarMap);
|
||||
return new EntityColumnMap(columnMap.Type, columnMap.Name, fieldList, newEntityIdentity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SimplePolymorphicColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(SimplePolymorphicColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
SimpleColumnMap newDiscriminator = (SimpleColumnMap)columnMap.TypeDiscriminator.Accept(this, replacementVarMap);
|
||||
|
||||
Dictionary<object, TypedColumnMap> newTypeChoices = new Dictionary<object, TypedColumnMap>(columnMap.TypeChoices.Comparer);
|
||||
foreach (KeyValuePair<object, TypedColumnMap> kv in columnMap.TypeChoices)
|
||||
{
|
||||
TypedColumnMap newMap = (TypedColumnMap)kv.Value.Accept(this, replacementVarMap);
|
||||
newTypeChoices[kv.Key] = newMap;
|
||||
}
|
||||
ColumnMap[] newBaseFieldList = VisitList(columnMap.Properties, replacementVarMap);
|
||||
return new SimplePolymorphicColumnMap(columnMap.Type, columnMap.Name, newBaseFieldList, newDiscriminator, newTypeChoices);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MultipleDiscriminatorPolymorphicColumnMap
|
||||
/// </summary>
|
||||
internal override ColumnMap Visit(MultipleDiscriminatorPolymorphicColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
// At this time, we shouldn't ever see this type here; it's for SPROCS which don't use
|
||||
// the plan compiler.
|
||||
System.Data.Query.PlanCompiler.PlanCompiler.Assert(false, "unexpected MultipleDiscriminatorPolymorphicColumnMap in ColumnMapCopier");
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RecordColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(RecordColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
SimpleColumnMap newNullability = columnMap.NullSentinel;
|
||||
if (null != newNullability)
|
||||
{
|
||||
newNullability = (SimpleColumnMap)newNullability.Accept(this, replacementVarMap);
|
||||
}
|
||||
ColumnMap[] fieldList = VisitList(columnMap.Properties, replacementVarMap);
|
||||
return new RecordColumnMap(columnMap.Type, columnMap.Name, fieldList, newNullability);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RefColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(RefColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
EntityIdentity newEntityIdentity = VisitEntityIdentity(columnMap.EntityIdentity, replacementVarMap);
|
||||
return new RefColumnMap(columnMap.Type, columnMap.Name, newEntityIdentity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ScalarColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(ScalarColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
return new ScalarColumnMap(columnMap.Type, columnMap.Name, columnMap.CommandId, columnMap.ColumnPos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SimpleCollectionColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(SimpleCollectionColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
ColumnMap newElementColumnMap = columnMap.Element.Accept(this, replacementVarMap);
|
||||
SimpleColumnMap[] newKeys = VisitList(columnMap.Keys, replacementVarMap);
|
||||
SimpleColumnMap[] newForeignKeys = VisitList(columnMap.ForeignKeys, replacementVarMap);
|
||||
return new SimpleCollectionColumnMap(columnMap.Type, columnMap.Name, newElementColumnMap, newKeys, newForeignKeys);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// VarRefColumnMap
|
||||
/// </summary>
|
||||
/// <param name="columnMap"></param>
|
||||
/// <param name="replacementVarMap"></param>
|
||||
/// <returns></returns>
|
||||
internal override ColumnMap Visit(VarRefColumnMap columnMap, VarMap replacementVarMap)
|
||||
{
|
||||
Var replacementVar = GetReplacementVar(columnMap.Var, replacementVarMap);
|
||||
return new VarRefColumnMap(columnMap.Type, columnMap.Name, replacementVar);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user