OpCopier.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / OpCopier.cs / 1305376 / OpCopier.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Data.Metadata.Edm;
using System.Data.Query.PlanCompiler;
 
// Interesting cases: Unnest
// More generally, note that any subtree that is left-correlated will stay as such. 
// 

namespace System.Data.Query.InternalTrees 
{
    /// 
    /// Handles copying of operators
    ///  
    internal class OpCopier : BasicOpVisitorOfNode
    { 
        #region (pseudo) Public API 
        internal static Node Copy(Command cmd, Node n)
        { 
            VarMap varMap;
            return Copy(cmd, n, out varMap);
        }
 
        /// 
        /// Make a copy of the current node. Also return an ordered list of the new 
        /// Vars corresponding to the vars in "varList" 
        /// 
        /// current command 
        /// the node to clone
        /// list of Vars
        /// list of "new" Vars
        /// the cloned node 
        internal static Node Copy(Command cmd, Node node, VarList varList, out VarList newVarList)
        { 
            VarMap varMap; 
            Node newNode = Copy(cmd, node, out varMap);
            newVarList = Command.CreateVarList(); 
            foreach (Var v in varList)
            {
                Var newVar = varMap[v];
                newVarList.Add(newVar); 
            }
            return newNode; 
        } 

        internal static Node Copy(Command cmd, Node n, out VarMap varMap) 
        {
            OpCopier oc = new OpCopier(cmd);
            Node newNode = oc.CopyNode(n);
            varMap = oc.m_varMap; 
            return newNode;
        } 
 
        internal static List Copy(Command cmd, List sortKeys)
        { 
            OpCopier oc = new OpCopier(cmd);
            return oc.Copy(sortKeys);
        }
        #endregion 

        // WARNING 
        // Everything below this line should be local to this class 
        // WARNING
 
        #region Private State
        private Command m_srcCmd;
        protected Command m_destCmd;
        // Map of var to cloned Var 
        protected VarMap m_varMap;
        #endregion 
 
        #region Constructors (private)
        ///  
        /// Constructor. Allows for cloning of nodes within the same command
        /// 
        /// The command
        protected OpCopier(Command cmd) : this(cmd, cmd) {} 

        ///  
        /// Constructor. Allows for cloning of nodes across commands 
        /// 
        /// The Command to which Nodes to be cloned must belong 
        /// The Command to which cloned Nodes will belong
        private OpCopier(Command destCommand, Command sourceCommand)
        {
            m_srcCmd = sourceCommand; 
            m_destCmd = destCommand;
            m_varMap = new VarMap(); 
        } 
        #endregion
 
        #region Private State Management

        /// 
        /// Get the "cloned" var for a given Var. 
        /// If no cloned var exists, return the input Var itself
        ///  
        /// The Var for which the cloned Var should be retrieved 
        /// The cloned Var that corresponds to the specified Var if this OpCopier is cloning across two different Commands; otherwise it is safe to return the specified Var itself
        private Var GetMappedVar(Var v) 
        {
            Var mappedVar;

            // 
            // Return a mapping if there is one
            // 
            if (m_varMap.TryGetValue(v, out mappedVar)) 
            {
                return mappedVar; 
            }

            //
            // No mapping found. 
            // If we're cloning to a different command, this is an error
            // 
            if (m_destCmd != m_srcCmd) 
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UnknownVar, 6); 
            }

            //
            // otherwise return the current Var itself 
            //
            return v; 
        } 

        ///  
        /// Set the "cloned" var for a given Var
        /// WARNING: If a mapping already exists, an exception is raised
        /// 
        /// The original Var 
        /// The cloned Var
        private void SetMappedVar(Var v, Var mappedVar) 
        { 
            m_varMap.Add(v, mappedVar);
        } 

        /// 
        /// Maps columns of an existing table to those of the cloned table
        ///  
        /// The original Table
        /// The cloned Table 
        private void MapTable(Table newTable, Table oldTable) 
        {
            // Map the corresponding columns of the table 
            // Now set up the column map
            for (int i = 0; i < oldTable.Columns.Count; i++)
            {
                SetMappedVar(oldTable.Columns[i], newTable.Columns[i]); 
            }
        } 
 
        /// 
        /// Produce the "mapped" Vars for each Var in the input sequence, while 
        /// preserving the original order
        /// 
        /// input var sequence
        /// output mapped vars 
        private IEnumerable MapVars(IEnumerable vars)
        { 
            foreach (Var v in vars) 
            {
                Var mappedVar = GetMappedVar(v); 
                yield return mappedVar;
            }
        }
 
        /// 
        /// Create a mapped varvec. A new varvec that "maps" all the Vars from 
        /// the original Varvec 
        /// 
        /// the varvec to clone 
        /// a mapped varvec
        private VarVec Copy(VarVec vars)
        {
            VarVec newVarVec = m_destCmd.CreateVarVec(MapVars(vars)); 
            return newVarVec;
        } 
 
        /// 
        /// Create a mapped copy of the input VarList - each var from the input varlist 
        /// is represented by its mapped var (and in exactly the same order) in the output
        /// varlist
        /// 
        /// varList to map 
        /// mapped varlist
        private VarList Copy(VarList varList) 
        { 
            VarList newVarList = Command.CreateVarList(MapVars(varList));
            return newVarList; 
        }

        /// 
        /// Copies a sortkey 
        /// 
        /// The SortKey to clone 
        /// A new SortKey that is a clone of sortKey 
        private SortKey Copy(SortKey sortKey)
        { 
            return Command.CreateSortKey(
                GetMappedVar(sortKey.Var),
                sortKey.AscendingSort,
                sortKey.Collation 
            );
        } 
 
        /// 
        /// Copies a list of Sortkeys 
        /// 
        /// The list of SortKeys
        /// A new list containing clones of the specified SortKeys
        private List Copy(List sortKeys) 
        {
            List newSortKeys = new List(); 
            foreach (SortKey k in sortKeys) 
            {
                newSortKeys.Add(Copy(k)); 
            }
            return newSortKeys;
        }
 
        #endregion
 
        #region Visitor Helpers 

        ///  
        /// Simple wrapper for all copy operations
        /// 
        /// The Node to copy
        /// A new Node that is a copy of the specified Node 
        protected Node CopyNode(Node n)
        { 
            return n.Op.Accept(this, n); 
        }
 
        /// 
        /// Copies all the Child Nodes of the specified Node
        /// 
        /// The Node for which the child Nodes should be copied 
        /// A new list containing copies of the specified Node's children
        private List ProcessChildren(Node n) 
        { 
            List children = new List();
            foreach (Node chi in n.Children) 
            {
                children.Add(CopyNode(chi));
            }
            return children; 
        }
 
        ///  
        /// Creates a new Node with the specified Op as its Op and the result of visiting the specified Node's children as its children
        ///  
        /// The Op that the new Node should reference
        /// The Node for which the children should be visited and the resulting cloned Nodes used as the children of the new Node returned by this method
        /// A new Node with the specified Op as its Op and the cloned child Nodes as its children
        private Node CopyDefault(Op op, Node original) 
        {
            return m_destCmd.CreateNode(op, ProcessChildren(original)); 
        } 
        #endregion
 
        #region IOpVisitor Members

        /// 
        /// Default Visitor pattern method for unrecognized Ops 
        /// 
        /// The unrecognized Op 
        /// The Node that references the Op 
        /// This method always throws NotSupportedException
        /// By design to indicate that the Op was not recognized and is therefore unsupported 
        public override Node Visit(Op op, Node n)
        {
            throw new NotSupportedException(System.Data.Entity.Strings.Iqt_General_UnsupportedOp(op.GetType().FullName));
        } 

        #region ScalarOps 
 
        /// 
        /// Copies a ConstantOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConstantOp op, Node n)
        { 
            ConstantBaseOp newOp = m_destCmd.CreateConstantOp(op.Type, op.Value); 
            return m_destCmd.CreateNode(newOp);
        } 

        /// 
        /// Copies a NullOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(NullOp op, Node n)
        { 
            return m_destCmd.CreateNode(m_destCmd.CreateNullOp(op.Type));
        }

        ///  
        /// Copies a ConstantPredicateOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConstantPredicateOp op, Node n)
        {
            return m_destCmd.CreateNode(m_destCmd.CreateConstantPredicateOp(op.Value));
        } 

        ///  
        /// Copies an InternalConstantOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(InternalConstantOp op, Node n)
        { 
            InternalConstantOp newOp = m_destCmd.CreateInternalConstantOp(op.Type, op.Value);
            return m_destCmd.CreateNode(newOp); 
        } 

        ///  
        /// Copies a NullSentinelOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NullSentinelOp op, Node n) 
        { 
            NullSentinelOp newOp = m_destCmd.CreateNullSentinelOp();
            return m_destCmd.CreateNode(newOp); 
        }

        /// 
        /// Copies a FunctionOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(FunctionOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateFunctionOp(op.Function), n);
        }
 
        /// 
        /// Copies a PropertyOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(PropertyOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreatePropertyOp(op.PropertyInfo), n); 
        }
 
        ///  
        /// Copies a RelPropertyOp
        ///  
        /// the RelPropertyOp to copy
        /// node tree corresponding to 'op'
        /// a copy of the node tree
        public override Node Visit(RelPropertyOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateRelPropertyOp(op.PropertyInfo), n); 
        } 

        ///  
        /// Copies a CaseOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CaseOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCaseOp(op.Type), n);
        } 

        /// 
        /// Copies a ComparisonOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ComparisonOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateComparisonOp(op.OpType), n);
        }

        ///  
        /// Copies a like-op
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(LikeOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateLikeOp(), n);
        } 

        ///  
        /// Clone an aggregateop 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(AggregateOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateAggregateOp(op.AggFunc, op.IsDistinctAggregate), n);
        } 
 
        /// 
        /// Copies a type constructor 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(NewInstanceOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateNewInstanceOp(op.Type), n); 
        }
 
        /// 
        /// Copies a NewEntityOp
        /// 
        /// the NewEntityOp to copy 
        /// node tree corresponding to the NewEntityOp
        /// a copy of the node tree 
        public override Node Visit(NewEntityOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateNewEntityOp(op.Type, op.RelationshipProperties, op.EntitySet), n); 
        }

        /// 
        /// Copies a discriminated type constructor 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(DiscriminatedNewEntityOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateDiscriminatedNewEntityOp(op.Type, op.DiscriminatorMap, op.EntitySet, op.RelationshipProperties), n);
        }
 
        /// 
        /// Copies a multiset constructor 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NewMultisetOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateNewMultisetOp(op.Type), n); 
        }
 
        ///  
        /// Copies a record constructor
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NewRecordOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateNewRecordOp(op.Type), n); 
        } 

        ///  
        /// Copies a RefOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(RefOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateRefOp(op.EntitySet, op.Type), n);
        } 

        /// 
        /// Copies a VarRefOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(VarRefOp op, Node n)
        { 
            // Look up the newVar.
            // If no var is available in the map, that implies that the Var is defined
            // outside this subtree (and it is therefore safe to use it).
            Var newVar; 
            if (!m_varMap.TryGetValue(op.Var, out newVar))
                newVar = op.Var; 
            // no children for a VarRef 
            return m_destCmd.CreateNode(m_destCmd.CreateVarRefOp(newVar));
        } 

        /// 
        /// Copies a ConditionalOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConditionalOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateConditionalOp(op.OpType), n);
        }

        ///  
        /// Copies an ArithmeticOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ArithmeticOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateArithmeticOp(op.OpType, op.Type), n);
        } 

        ///  
        /// Copies a TreatOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(TreatOp op, Node n)
        { 
            TreatOp newTreatOp = op.IsFakeTreat ? m_destCmd.CreateFakeTreatOp(op.Type) : m_destCmd.CreateTreatOp(op.Type);
            return CopyDefault(newTreatOp, n); 
        } 

        ///  
        /// Copies a CastOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CastOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCastOp(op.Type), n);
        } 

        /// 
        /// Copies a SoftCastOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(SoftCastOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateSoftCastOp(op.Type), n);
        }

        ///  
        /// Copies a DerefOp
        ///  
        /// the derefOp to copy 
        /// the subtree
        /// a copy of the subtree 
        public override Node Visit(DerefOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateDerefOp(op.Type), n);
        } 

        ///  
        /// Copies a NavigateOp 
        /// 
        /// the NavigateOp 
        /// the subtree
        /// a copy of the subtree
        public override Node Visit(NavigateOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateNavigateOp(op.Type, op.RelProperty), n);
        } 
 
        /// 
        /// Clone an IsOfOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(IsOfOp op, Node n)
        { 
            if (op.IsOfOnly) 
                return CopyDefault(m_destCmd.CreateIsOfOnlyOp(op.IsOfType), n);
            else 
                return CopyDefault(m_destCmd.CreateIsOfOp(op.IsOfType), n);
        }

        ///  
        /// Clone an ExistsOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ExistsOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateExistsOp(), n);
        } 

        ///  
        /// Clone an ElementOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ElementOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateElementOp(op.Type), n);
        } 
 
        /// 
        /// Copies a GetRefKeyOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GetRefKeyOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateGetRefKeyOp(op.Type), n); 
        }
 
        /// 
        /// Copies a GetEntityRefOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GetEntityRefOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateGetEntityRefOp(op.Type), n); 
        }

        /// 
        /// Copies a CollectOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CollectOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateCollectOp(op.Type), n);
        }
 
        #endregion
 
        #region RelOps 

        ///  
        /// Copies a ScanTableOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ScanTableOp op, Node n) 
        { 
            // First create a new ScanTableOp based on the metadata of the existing Op
            ScanTableOp newScan = m_destCmd.CreateScanTableOp(op.Table.TableMetadata); 
            // Map the corresponding tables/columns
            MapTable(newScan.Table, op.Table);

            // Create the new node 
            Debug.Assert(!n.HasChild0);
            return m_destCmd.CreateNode(newScan); 
        } 

        ///  
        /// Copies a ScanViewOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ScanViewOp op, Node n) 
        { 
            // First create a new ScanViewOp based on the metadata of the existing Op
            ScanViewOp newScan = m_destCmd.CreateScanViewOp(op.Table.TableMetadata); 
            // Map the corresponding tables/columns
            MapTable(newScan.Table, op.Table);

            // Create the new node 
            Debug.Assert(n.HasChild0);
            List children = ProcessChildren(n); 
            return m_destCmd.CreateNode(newScan, children); 
        }
 
        /// 
        /// Clone an UnnestOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(UnnestOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Get the mapped unnest-var
            Var mappedVar = GetMappedVar(op.Var); 

            // Create a new unnestOp 
            Table newTable = m_destCmd.CreateTableInstance(op.Table.TableMetadata); 
            UnnestOp newUnnest = m_destCmd.CreateUnnestOp(mappedVar, newTable);
 
            // Map the corresponding tables/columns
            MapTable(newUnnest.Table, op.Table);

            // create the unnest node 
            return m_destCmd.CreateNode(newUnnest, children);
        } 
 
        /// 
        /// Copies a ProjectOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ProjectOp op, Node n)
        { 
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);
 
            // Copy the ProjectOp's VarSet
            VarVec newVarSet = Copy(op.Outputs);

            // Create a new ProjectOp based on the copied VarSet 
            ProjectOp newProject = m_destCmd.CreateProjectOp(newVarSet);
 
            // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newProject, children);
        } 

        /// 
        /// Copies a filterOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(FilterOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateFilterOp(), n);
        }

        ///  
        /// Copies a sort node
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(SortOp op, Node n)
        {
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n); 

            // Copy the SortOp's SortKeys 
            List newSortKeys = Copy(op.Keys); 

            // Create a new SortOp that uses the copied SortKeys 
            SortOp newSortOp = m_destCmd.CreateSortOp(newSortKeys);

            // Return a new Node that references the copied SortOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newSortOp, children); 
        }
 
        ///  
        /// Copies a constrained sort node
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ConstrainedSortOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n); 

            // Copy the ConstrainedSortOp's SortKeys 
            List newSortKeys = Copy(op.Keys);

            // Create a new ConstrainedSortOp that uses the copied SortKeys and the original Op's WithTies value
            ConstrainedSortOp newSortOp = m_destCmd.CreateConstrainedSortOp(newSortKeys, op.WithTies); 

            // Return a new Node that references the copied SortOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newSortOp, children); 
        }
 
        /// 
        /// Copies a group-by node
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GroupByOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
            GroupByOp newGroupOp = m_destCmd.CreateGroupByOp(Copy(op.Keys), Copy(op.Outputs)); 

            // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newGroupOp, children); 
        }
 
        /// 
        /// Copies a group by into node
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GroupByIntoOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
            GroupByIntoOp newGroupOp = m_destCmd.CreateGroupByIntoOp(Copy(op.Keys), Copy(op.Inputs),  Copy(op.Outputs)); 

            // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newGroupOp, children); 
        }
 
        /// 
        /// Copies a CrossJoinOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(CrossJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateCrossJoinOp(), n); 
        }

        /// 
        /// Copies an InnerJoinOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(InnerJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateInnerJoinOp(), n);
        }
 
        /// 
        /// Copies a LeftOuterJoinOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(LeftOuterJoinOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateLeftOuterJoinOp(), n); 
        }
 
        ///  
        /// Copies a FullOuterJoinOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(FullOuterJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateFullOuterJoinOp(), n); 
        } 

        ///  
        /// Copies a crossApplyOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CrossApplyOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCrossApplyOp(), n);
        } 

        /// 
        /// Clone an OuterApplyOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(OuterApplyOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateOuterApplyOp(), n);
        }

        ///  
        /// Common copy path for all SetOps
        ///  
        /// The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp) 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        private Node CopySetOp(SetOp op, Node n)
        {
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n); 

            VarMap leftMap = new VarMap(); 
            VarMap rightMap = new VarMap(); 

 
            foreach (KeyValuePair kv in op.VarMap[0])
            {
                // Create a new output Var that is a copy of the original output Var
                Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type); 

                // Add a mapping for the new output var we've just created 
                SetMappedVar(kv.Key, outputVar); 

                // Add this output var's entries to the new VarMaps 
                leftMap.Add(outputVar, GetMappedVar(kv.Value));
                rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key]));
            }
 
            SetOp newSetOp = null;
            switch(op.OpType) 
            { 
                case OpType.UnionAll:
                    { 
                        Var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator;
                        if (null != branchDiscriminator)
                        {
                            branchDiscriminator = GetMappedVar(branchDiscriminator); 
                        }
                        newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator); 
                    } 
                    break;
 
                case OpType.Intersect:
                    {
                        newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap);
                    } 
                    break;
 
                case OpType.Except: 
                    {
                        newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap); 
                    }
                    break;

                default: 
                    {
                        Debug.Assert(false, "Unexpected SetOpType"); 
                    } 
                    break;
            } 

            return m_destCmd.CreateNode(newSetOp, children);
        }
 
        /// 
        /// Copies a UnionAllOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(UnionAllOp op, Node n)
        {
            return CopySetOp(op, n); 
        }
 
        ///  
        /// Copies an IntersectOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(IntersectOp op, Node n) 
        {
            return CopySetOp(op, n); 
        } 

        ///  
        /// Copies an ExceptOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ExceptOp op, Node n) 
        { 
            return CopySetOp(op, n);
        } 

        /// 
        /// Copies a DistinctOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(DistinctOp op, Node n)
        { 
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n);

            // Copy the DistinctOp's Keys 
            VarVec newDistinctKeys = Copy(op.Keys);
 
            // Create a new DistinctOp that uses the copied keys 
            DistinctOp newDistinctOp = m_destCmd.CreateDistinctOp(newDistinctKeys);
 
            // Return a new Node that references the copied DistinctOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newDistinctOp, children);
        }
 
        public override Node Visit(SingleRowOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateSingleRowOp(), n); 
        }
 
        public override Node Visit(SingleRowTableOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateSingleRowTableOp(), n);
        } 

        #endregion 
 
        #region AncillaryOps
        ///  
        /// Copies a VarDefOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(VarDefOp op, Node n) 
        { 
            // First create a new Var
            List children = ProcessChildren(n); 
            Debug.Assert(op.Var.VarType == VarType.Computed, "Unexpected VarType");
            Var newVar = m_destCmd.CreateComputedVar(op.Var.Type);
            SetMappedVar(op.Var, newVar);
            return m_destCmd.CreateNode(m_destCmd.CreateVarDefOp(newVar), children); 
        }
 
        ///  
        /// Copies a VarDefListOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(VarDefListOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateVarDefListOp(), n); 
        } 
        #endregion
 
        #region RulePatternOps
        #endregion

        #region PhysicalOps 
        private ColumnMap Copy(ColumnMap columnMap)
        { 
            return ColumnMapCopier.Copy(columnMap, m_varMap); 
        }
 
        /// 
        /// Copies a PhysicalProjectOp
        /// 
        ///  
        /// 
        ///  
        public override Node Visit(PhysicalProjectOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Copy the ProjectOp's VarSet
            VarList newVarList = Copy(op.Outputs); 

            SimpleCollectionColumnMap newColumnMap = Copy(op.ColumnMap) as SimpleCollectionColumnMap; 
            Debug.Assert(newColumnMap != null, "Coping of a physical project's columnMap did not return a SimpleCollectionColumnMap" ); 
            // Create a new ProjectOp based on the copied VarSet
            PhysicalProjectOp newProject = m_destCmd.CreatePhysicalProjectOp(newVarList, newColumnMap); 

            // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newProject, children);
        } 

        private Node VisitNestOp(Node n) 
        { 
            NestBaseOp op = n.Op as NestBaseOp;
            SingleStreamNestOp ssnOp = op as SingleStreamNestOp; 
            Debug.Assert(op != null);

            // Visit the Node's children and map their Vars
            List newChildren = ProcessChildren(n); 

            Var newDiscriminator = null; 
            if (ssnOp != null) 
            {
                newDiscriminator = GetMappedVar(ssnOp.Discriminator); 
            }
            List newCollectionInfoList = new List();
            foreach (CollectionInfo ci in op.CollectionInfo)
            { 
                ColumnMap newColumnMap = Copy(ci.ColumnMap);
 
                Var newCollectionVar = m_destCmd.CreateComputedVar(ci.CollectionVar.Type); 
                SetMappedVar(ci.CollectionVar, newCollectionVar);
 
                VarList newFlattendElementVars = Copy(ci.FlattenedElementVars);
                VarVec newKeys = Copy(ci.Keys);
                List newSortKeys = Copy(ci.SortKeys);
                CollectionInfo newCollectionInfo = Command.CreateCollectionInfo(newCollectionVar, newColumnMap, newFlattendElementVars, newKeys, newSortKeys, ci.DiscriminatorValue); 
                newCollectionInfoList.Add(newCollectionInfo);
            } 
 
            VarVec newOutputs = Copy(op.Outputs);
 
            NestBaseOp newOp = null;
            List newPrefixSortKeys = Copy(op.PrefixSortKeys);
            if (ssnOp != null)
            { 
                VarVec newKeys = Copy(ssnOp.Keys);
                // Copy the SortOp's SortKeys 
                List newPostfixSortKeys = Copy(ssnOp.PostfixSortKeys); 
                newOp = m_destCmd.CreateSingleStreamNestOp(newKeys, newPrefixSortKeys, newPostfixSortKeys, newOutputs, newCollectionInfoList, newDiscriminator);
            } 
            else
            {
                newOp = m_destCmd.CreateMultiStreamNestOp(newPrefixSortKeys, newOutputs, newCollectionInfoList);
            } 

            return m_destCmd.CreateNode(newOp, newChildren); 
        } 

        ///  
        /// Copies a singleStreamNestOp
        /// 
        /// 
        ///  
        /// 
        public override Node Visit(SingleStreamNestOp op, Node n) 
        { 
            return VisitNestOp(n);
        } 

        /// 
        /// Copies a multiStreamNestOp
        ///  
        /// 
        ///  
        ///  
        public override Node Visit(MultiStreamNestOp op, Node n)
        { 
            return VisitNestOp(n);
        }
        #endregion
 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Data.Metadata.Edm;
using System.Data.Query.PlanCompiler;
 
// Interesting cases: Unnest
// More generally, note that any subtree that is left-correlated will stay as such. 
// 

namespace System.Data.Query.InternalTrees 
{
    /// 
    /// Handles copying of operators
    ///  
    internal class OpCopier : BasicOpVisitorOfNode
    { 
        #region (pseudo) Public API 
        internal static Node Copy(Command cmd, Node n)
        { 
            VarMap varMap;
            return Copy(cmd, n, out varMap);
        }
 
        /// 
        /// Make a copy of the current node. Also return an ordered list of the new 
        /// Vars corresponding to the vars in "varList" 
        /// 
        /// current command 
        /// the node to clone
        /// list of Vars
        /// list of "new" Vars
        /// the cloned node 
        internal static Node Copy(Command cmd, Node node, VarList varList, out VarList newVarList)
        { 
            VarMap varMap; 
            Node newNode = Copy(cmd, node, out varMap);
            newVarList = Command.CreateVarList(); 
            foreach (Var v in varList)
            {
                Var newVar = varMap[v];
                newVarList.Add(newVar); 
            }
            return newNode; 
        } 

        internal static Node Copy(Command cmd, Node n, out VarMap varMap) 
        {
            OpCopier oc = new OpCopier(cmd);
            Node newNode = oc.CopyNode(n);
            varMap = oc.m_varMap; 
            return newNode;
        } 
 
        internal static List Copy(Command cmd, List sortKeys)
        { 
            OpCopier oc = new OpCopier(cmd);
            return oc.Copy(sortKeys);
        }
        #endregion 

        // WARNING 
        // Everything below this line should be local to this class 
        // WARNING
 
        #region Private State
        private Command m_srcCmd;
        protected Command m_destCmd;
        // Map of var to cloned Var 
        protected VarMap m_varMap;
        #endregion 
 
        #region Constructors (private)
        ///  
        /// Constructor. Allows for cloning of nodes within the same command
        /// 
        /// The command
        protected OpCopier(Command cmd) : this(cmd, cmd) {} 

        ///  
        /// Constructor. Allows for cloning of nodes across commands 
        /// 
        /// The Command to which Nodes to be cloned must belong 
        /// The Command to which cloned Nodes will belong
        private OpCopier(Command destCommand, Command sourceCommand)
        {
            m_srcCmd = sourceCommand; 
            m_destCmd = destCommand;
            m_varMap = new VarMap(); 
        } 
        #endregion
 
        #region Private State Management

        /// 
        /// Get the "cloned" var for a given Var. 
        /// If no cloned var exists, return the input Var itself
        ///  
        /// The Var for which the cloned Var should be retrieved 
        /// The cloned Var that corresponds to the specified Var if this OpCopier is cloning across two different Commands; otherwise it is safe to return the specified Var itself
        private Var GetMappedVar(Var v) 
        {
            Var mappedVar;

            // 
            // Return a mapping if there is one
            // 
            if (m_varMap.TryGetValue(v, out mappedVar)) 
            {
                return mappedVar; 
            }

            //
            // No mapping found. 
            // If we're cloning to a different command, this is an error
            // 
            if (m_destCmd != m_srcCmd) 
            {
                throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UnknownVar, 6); 
            }

            //
            // otherwise return the current Var itself 
            //
            return v; 
        } 

        ///  
        /// Set the "cloned" var for a given Var
        /// WARNING: If a mapping already exists, an exception is raised
        /// 
        /// The original Var 
        /// The cloned Var
        private void SetMappedVar(Var v, Var mappedVar) 
        { 
            m_varMap.Add(v, mappedVar);
        } 

        /// 
        /// Maps columns of an existing table to those of the cloned table
        ///  
        /// The original Table
        /// The cloned Table 
        private void MapTable(Table newTable, Table oldTable) 
        {
            // Map the corresponding columns of the table 
            // Now set up the column map
            for (int i = 0; i < oldTable.Columns.Count; i++)
            {
                SetMappedVar(oldTable.Columns[i], newTable.Columns[i]); 
            }
        } 
 
        /// 
        /// Produce the "mapped" Vars for each Var in the input sequence, while 
        /// preserving the original order
        /// 
        /// input var sequence
        /// output mapped vars 
        private IEnumerable MapVars(IEnumerable vars)
        { 
            foreach (Var v in vars) 
            {
                Var mappedVar = GetMappedVar(v); 
                yield return mappedVar;
            }
        }
 
        /// 
        /// Create a mapped varvec. A new varvec that "maps" all the Vars from 
        /// the original Varvec 
        /// 
        /// the varvec to clone 
        /// a mapped varvec
        private VarVec Copy(VarVec vars)
        {
            VarVec newVarVec = m_destCmd.CreateVarVec(MapVars(vars)); 
            return newVarVec;
        } 
 
        /// 
        /// Create a mapped copy of the input VarList - each var from the input varlist 
        /// is represented by its mapped var (and in exactly the same order) in the output
        /// varlist
        /// 
        /// varList to map 
        /// mapped varlist
        private VarList Copy(VarList varList) 
        { 
            VarList newVarList = Command.CreateVarList(MapVars(varList));
            return newVarList; 
        }

        /// 
        /// Copies a sortkey 
        /// 
        /// The SortKey to clone 
        /// A new SortKey that is a clone of sortKey 
        private SortKey Copy(SortKey sortKey)
        { 
            return Command.CreateSortKey(
                GetMappedVar(sortKey.Var),
                sortKey.AscendingSort,
                sortKey.Collation 
            );
        } 
 
        /// 
        /// Copies a list of Sortkeys 
        /// 
        /// The list of SortKeys
        /// A new list containing clones of the specified SortKeys
        private List Copy(List sortKeys) 
        {
            List newSortKeys = new List(); 
            foreach (SortKey k in sortKeys) 
            {
                newSortKeys.Add(Copy(k)); 
            }
            return newSortKeys;
        }
 
        #endregion
 
        #region Visitor Helpers 

        ///  
        /// Simple wrapper for all copy operations
        /// 
        /// The Node to copy
        /// A new Node that is a copy of the specified Node 
        protected Node CopyNode(Node n)
        { 
            return n.Op.Accept(this, n); 
        }
 
        /// 
        /// Copies all the Child Nodes of the specified Node
        /// 
        /// The Node for which the child Nodes should be copied 
        /// A new list containing copies of the specified Node's children
        private List ProcessChildren(Node n) 
        { 
            List children = new List();
            foreach (Node chi in n.Children) 
            {
                children.Add(CopyNode(chi));
            }
            return children; 
        }
 
        ///  
        /// Creates a new Node with the specified Op as its Op and the result of visiting the specified Node's children as its children
        ///  
        /// The Op that the new Node should reference
        /// The Node for which the children should be visited and the resulting cloned Nodes used as the children of the new Node returned by this method
        /// A new Node with the specified Op as its Op and the cloned child Nodes as its children
        private Node CopyDefault(Op op, Node original) 
        {
            return m_destCmd.CreateNode(op, ProcessChildren(original)); 
        } 
        #endregion
 
        #region IOpVisitor Members

        /// 
        /// Default Visitor pattern method for unrecognized Ops 
        /// 
        /// The unrecognized Op 
        /// The Node that references the Op 
        /// This method always throws NotSupportedException
        /// By design to indicate that the Op was not recognized and is therefore unsupported 
        public override Node Visit(Op op, Node n)
        {
            throw new NotSupportedException(System.Data.Entity.Strings.Iqt_General_UnsupportedOp(op.GetType().FullName));
        } 

        #region ScalarOps 
 
        /// 
        /// Copies a ConstantOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConstantOp op, Node n)
        { 
            ConstantBaseOp newOp = m_destCmd.CreateConstantOp(op.Type, op.Value); 
            return m_destCmd.CreateNode(newOp);
        } 

        /// 
        /// Copies a NullOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(NullOp op, Node n)
        { 
            return m_destCmd.CreateNode(m_destCmd.CreateNullOp(op.Type));
        }

        ///  
        /// Copies a ConstantPredicateOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConstantPredicateOp op, Node n)
        {
            return m_destCmd.CreateNode(m_destCmd.CreateConstantPredicateOp(op.Value));
        } 

        ///  
        /// Copies an InternalConstantOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(InternalConstantOp op, Node n)
        { 
            InternalConstantOp newOp = m_destCmd.CreateInternalConstantOp(op.Type, op.Value);
            return m_destCmd.CreateNode(newOp); 
        } 

        ///  
        /// Copies a NullSentinelOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NullSentinelOp op, Node n) 
        { 
            NullSentinelOp newOp = m_destCmd.CreateNullSentinelOp();
            return m_destCmd.CreateNode(newOp); 
        }

        /// 
        /// Copies a FunctionOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(FunctionOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateFunctionOp(op.Function), n);
        }
 
        /// 
        /// Copies a PropertyOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(PropertyOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreatePropertyOp(op.PropertyInfo), n); 
        }
 
        ///  
        /// Copies a RelPropertyOp
        ///  
        /// the RelPropertyOp to copy
        /// node tree corresponding to 'op'
        /// a copy of the node tree
        public override Node Visit(RelPropertyOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateRelPropertyOp(op.PropertyInfo), n); 
        } 

        ///  
        /// Copies a CaseOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CaseOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCaseOp(op.Type), n);
        } 

        /// 
        /// Copies a ComparisonOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ComparisonOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateComparisonOp(op.OpType), n);
        }

        ///  
        /// Copies a like-op
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(LikeOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateLikeOp(), n);
        } 

        ///  
        /// Clone an aggregateop 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(AggregateOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateAggregateOp(op.AggFunc, op.IsDistinctAggregate), n);
        } 
 
        /// 
        /// Copies a type constructor 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(NewInstanceOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateNewInstanceOp(op.Type), n); 
        }
 
        /// 
        /// Copies a NewEntityOp
        /// 
        /// the NewEntityOp to copy 
        /// node tree corresponding to the NewEntityOp
        /// a copy of the node tree 
        public override Node Visit(NewEntityOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateNewEntityOp(op.Type, op.RelationshipProperties, op.EntitySet), n); 
        }

        /// 
        /// Copies a discriminated type constructor 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(DiscriminatedNewEntityOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateDiscriminatedNewEntityOp(op.Type, op.DiscriminatorMap, op.EntitySet, op.RelationshipProperties), n);
        }
 
        /// 
        /// Copies a multiset constructor 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NewMultisetOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateNewMultisetOp(op.Type), n); 
        }
 
        ///  
        /// Copies a record constructor
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(NewRecordOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateNewRecordOp(op.Type), n); 
        } 

        ///  
        /// Copies a RefOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(RefOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateRefOp(op.EntitySet, op.Type), n);
        } 

        /// 
        /// Copies a VarRefOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(VarRefOp op, Node n)
        { 
            // Look up the newVar.
            // If no var is available in the map, that implies that the Var is defined
            // outside this subtree (and it is therefore safe to use it).
            Var newVar; 
            if (!m_varMap.TryGetValue(op.Var, out newVar))
                newVar = op.Var; 
            // no children for a VarRef 
            return m_destCmd.CreateNode(m_destCmd.CreateVarRefOp(newVar));
        } 

        /// 
        /// Copies a ConditionalOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ConditionalOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateConditionalOp(op.OpType), n);
        }

        ///  
        /// Copies an ArithmeticOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ArithmeticOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateArithmeticOp(op.OpType, op.Type), n);
        } 

        ///  
        /// Copies a TreatOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(TreatOp op, Node n)
        { 
            TreatOp newTreatOp = op.IsFakeTreat ? m_destCmd.CreateFakeTreatOp(op.Type) : m_destCmd.CreateTreatOp(op.Type);
            return CopyDefault(newTreatOp, n); 
        } 

        ///  
        /// Copies a CastOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CastOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCastOp(op.Type), n);
        } 

        /// 
        /// Copies a SoftCastOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(SoftCastOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateSoftCastOp(op.Type), n);
        }

        ///  
        /// Copies a DerefOp
        ///  
        /// the derefOp to copy 
        /// the subtree
        /// a copy of the subtree 
        public override Node Visit(DerefOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateDerefOp(op.Type), n);
        } 

        ///  
        /// Copies a NavigateOp 
        /// 
        /// the NavigateOp 
        /// the subtree
        /// a copy of the subtree
        public override Node Visit(NavigateOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateNavigateOp(op.Type, op.RelProperty), n);
        } 
 
        /// 
        /// Clone an IsOfOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(IsOfOp op, Node n)
        { 
            if (op.IsOfOnly) 
                return CopyDefault(m_destCmd.CreateIsOfOnlyOp(op.IsOfType), n);
            else 
                return CopyDefault(m_destCmd.CreateIsOfOp(op.IsOfType), n);
        }

        ///  
        /// Clone an ExistsOp
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ExistsOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateExistsOp(), n);
        } 

        ///  
        /// Clone an ElementOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ElementOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateElementOp(op.Type), n);
        } 
 
        /// 
        /// Copies a GetRefKeyOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GetRefKeyOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateGetRefKeyOp(op.Type), n); 
        }
 
        /// 
        /// Copies a GetEntityRefOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GetEntityRefOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateGetEntityRefOp(op.Type), n); 
        }

        /// 
        /// Copies a CollectOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CollectOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateCollectOp(op.Type), n);
        }
 
        #endregion
 
        #region RelOps 

        ///  
        /// Copies a ScanTableOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ScanTableOp op, Node n) 
        { 
            // First create a new ScanTableOp based on the metadata of the existing Op
            ScanTableOp newScan = m_destCmd.CreateScanTableOp(op.Table.TableMetadata); 
            // Map the corresponding tables/columns
            MapTable(newScan.Table, op.Table);

            // Create the new node 
            Debug.Assert(!n.HasChild0);
            return m_destCmd.CreateNode(newScan); 
        } 

        ///  
        /// Copies a ScanViewOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ScanViewOp op, Node n) 
        { 
            // First create a new ScanViewOp based on the metadata of the existing Op
            ScanViewOp newScan = m_destCmd.CreateScanViewOp(op.Table.TableMetadata); 
            // Map the corresponding tables/columns
            MapTable(newScan.Table, op.Table);

            // Create the new node 
            Debug.Assert(n.HasChild0);
            List children = ProcessChildren(n); 
            return m_destCmd.CreateNode(newScan, children); 
        }
 
        /// 
        /// Clone an UnnestOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(UnnestOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Get the mapped unnest-var
            Var mappedVar = GetMappedVar(op.Var); 

            // Create a new unnestOp 
            Table newTable = m_destCmd.CreateTableInstance(op.Table.TableMetadata); 
            UnnestOp newUnnest = m_destCmd.CreateUnnestOp(mappedVar, newTable);
 
            // Map the corresponding tables/columns
            MapTable(newUnnest.Table, op.Table);

            // create the unnest node 
            return m_destCmd.CreateNode(newUnnest, children);
        } 
 
        /// 
        /// Copies a ProjectOp 
        /// 
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(ProjectOp op, Node n)
        { 
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);
 
            // Copy the ProjectOp's VarSet
            VarVec newVarSet = Copy(op.Outputs);

            // Create a new ProjectOp based on the copied VarSet 
            ProjectOp newProject = m_destCmd.CreateProjectOp(newVarSet);
 
            // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newProject, children);
        } 

        /// 
        /// Copies a filterOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(FilterOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateFilterOp(), n);
        }

        ///  
        /// Copies a sort node
        ///  
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(SortOp op, Node n)
        {
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n); 

            // Copy the SortOp's SortKeys 
            List newSortKeys = Copy(op.Keys); 

            // Create a new SortOp that uses the copied SortKeys 
            SortOp newSortOp = m_destCmd.CreateSortOp(newSortKeys);

            // Return a new Node that references the copied SortOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newSortOp, children); 
        }
 
        ///  
        /// Copies a constrained sort node
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ConstrainedSortOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n); 

            // Copy the ConstrainedSortOp's SortKeys 
            List newSortKeys = Copy(op.Keys);

            // Create a new ConstrainedSortOp that uses the copied SortKeys and the original Op's WithTies value
            ConstrainedSortOp newSortOp = m_destCmd.CreateConstrainedSortOp(newSortKeys, op.WithTies); 

            // Return a new Node that references the copied SortOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newSortOp, children); 
        }
 
        /// 
        /// Copies a group-by node
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GroupByOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
            GroupByOp newGroupOp = m_destCmd.CreateGroupByOp(Copy(op.Keys), Copy(op.Outputs)); 

            // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newGroupOp, children); 
        }
 
        /// 
        /// Copies a group by into node
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(GroupByIntoOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
            GroupByIntoOp newGroupOp = m_destCmd.CreateGroupByIntoOp(Copy(op.Keys), Copy(op.Inputs),  Copy(op.Outputs)); 

            // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children 
            return m_destCmd.CreateNode(newGroupOp, children); 
        }
 
        /// 
        /// Copies a CrossJoinOp
        /// 
        /// The Op to Copy 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(CrossJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateCrossJoinOp(), n); 
        }

        /// 
        /// Copies an InnerJoinOp 
        /// 
        /// The Op to Copy 
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(InnerJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateInnerJoinOp(), n);
        }
 
        /// 
        /// Copies a LeftOuterJoinOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(LeftOuterJoinOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateLeftOuterJoinOp(), n); 
        }
 
        ///  
        /// Copies a FullOuterJoinOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(FullOuterJoinOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateFullOuterJoinOp(), n); 
        } 

        ///  
        /// Copies a crossApplyOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(CrossApplyOp op, Node n) 
        { 
            return CopyDefault(m_destCmd.CreateCrossApplyOp(), n);
        } 

        /// 
        /// Clone an OuterApplyOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(OuterApplyOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateOuterApplyOp(), n);
        }

        ///  
        /// Common copy path for all SetOps
        ///  
        /// The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp) 
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op 
        private Node CopySetOp(SetOp op, Node n)
        {
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n); 

            VarMap leftMap = new VarMap(); 
            VarMap rightMap = new VarMap(); 

 
            foreach (KeyValuePair kv in op.VarMap[0])
            {
                // Create a new output Var that is a copy of the original output Var
                Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type); 

                // Add a mapping for the new output var we've just created 
                SetMappedVar(kv.Key, outputVar); 

                // Add this output var's entries to the new VarMaps 
                leftMap.Add(outputVar, GetMappedVar(kv.Value));
                rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key]));
            }
 
            SetOp newSetOp = null;
            switch(op.OpType) 
            { 
                case OpType.UnionAll:
                    { 
                        Var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator;
                        if (null != branchDiscriminator)
                        {
                            branchDiscriminator = GetMappedVar(branchDiscriminator); 
                        }
                        newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator); 
                    } 
                    break;
 
                case OpType.Intersect:
                    {
                        newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap);
                    } 
                    break;
 
                case OpType.Except: 
                    {
                        newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap); 
                    }
                    break;

                default: 
                    {
                        Debug.Assert(false, "Unexpected SetOpType"); 
                    } 
                    break;
            } 

            return m_destCmd.CreateNode(newSetOp, children);
        }
 
        /// 
        /// Copies a UnionAllOp 
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(UnionAllOp op, Node n)
        {
            return CopySetOp(op, n); 
        }
 
        ///  
        /// Copies an IntersectOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(IntersectOp op, Node n) 
        {
            return CopySetOp(op, n); 
        } 

        ///  
        /// Copies an ExceptOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(ExceptOp op, Node n) 
        { 
            return CopySetOp(op, n);
        } 

        /// 
        /// Copies a DistinctOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op 
        public override Node Visit(DistinctOp op, Node n)
        { 
            // Visit the Node's children and map their Vars
            List children = ProcessChildren(n);

            // Copy the DistinctOp's Keys 
            VarVec newDistinctKeys = Copy(op.Keys);
 
            // Create a new DistinctOp that uses the copied keys 
            DistinctOp newDistinctOp = m_destCmd.CreateDistinctOp(newDistinctKeys);
 
            // Return a new Node that references the copied DistinctOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newDistinctOp, children);
        }
 
        public override Node Visit(SingleRowOp op, Node n)
        { 
            return CopyDefault(m_destCmd.CreateSingleRowOp(), n); 
        }
 
        public override Node Visit(SingleRowTableOp op, Node n)
        {
            return CopyDefault(m_destCmd.CreateSingleRowTableOp(), n);
        } 

        #endregion 
 
        #region AncillaryOps
        ///  
        /// Copies a VarDefOp
        /// 
        /// The Op to Copy
        /// The Node that references the Op 
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(VarDefOp op, Node n) 
        { 
            // First create a new Var
            List children = ProcessChildren(n); 
            Debug.Assert(op.Var.VarType == VarType.Computed, "Unexpected VarType");
            Var newVar = m_destCmd.CreateComputedVar(op.Var.Type);
            SetMappedVar(op.Var, newVar);
            return m_destCmd.CreateNode(m_destCmd.CreateVarDefOp(newVar), children); 
        }
 
        ///  
        /// Copies a VarDefListOp
        ///  
        /// The Op to Copy
        /// The Node that references the Op
        /// A copy of the original Node that references a copy of the original Op
        public override Node Visit(VarDefListOp op, Node n) 
        {
            return CopyDefault(m_destCmd.CreateVarDefListOp(), n); 
        } 
        #endregion
 
        #region RulePatternOps
        #endregion

        #region PhysicalOps 
        private ColumnMap Copy(ColumnMap columnMap)
        { 
            return ColumnMapCopier.Copy(columnMap, m_varMap); 
        }
 
        /// 
        /// Copies a PhysicalProjectOp
        /// 
        ///  
        /// 
        ///  
        public override Node Visit(PhysicalProjectOp op, Node n) 
        {
            // Visit the Node's children and map their Vars 
            List children = ProcessChildren(n);

            // Copy the ProjectOp's VarSet
            VarList newVarList = Copy(op.Outputs); 

            SimpleCollectionColumnMap newColumnMap = Copy(op.ColumnMap) as SimpleCollectionColumnMap; 
            Debug.Assert(newColumnMap != null, "Coping of a physical project's columnMap did not return a SimpleCollectionColumnMap" ); 
            // Create a new ProjectOp based on the copied VarSet
            PhysicalProjectOp newProject = m_destCmd.CreatePhysicalProjectOp(newVarList, newColumnMap); 

            // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children
            return m_destCmd.CreateNode(newProject, children);
        } 

        private Node VisitNestOp(Node n) 
        { 
            NestBaseOp op = n.Op as NestBaseOp;
            SingleStreamNestOp ssnOp = op as SingleStreamNestOp; 
            Debug.Assert(op != null);

            // Visit the Node's children and map their Vars
            List newChildren = ProcessChildren(n); 

            Var newDiscriminator = null; 
            if (ssnOp != null) 
            {
                newDiscriminator = GetMappedVar(ssnOp.Discriminator); 
            }
            List newCollectionInfoList = new List();
            foreach (CollectionInfo ci in op.CollectionInfo)
            { 
                ColumnMap newColumnMap = Copy(ci.ColumnMap);
 
                Var newCollectionVar = m_destCmd.CreateComputedVar(ci.CollectionVar.Type); 
                SetMappedVar(ci.CollectionVar, newCollectionVar);
 
                VarList newFlattendElementVars = Copy(ci.FlattenedElementVars);
                VarVec newKeys = Copy(ci.Keys);
                List newSortKeys = Copy(ci.SortKeys);
                CollectionInfo newCollectionInfo = Command.CreateCollectionInfo(newCollectionVar, newColumnMap, newFlattendElementVars, newKeys, newSortKeys, ci.DiscriminatorValue); 
                newCollectionInfoList.Add(newCollectionInfo);
            } 
 
            VarVec newOutputs = Copy(op.Outputs);
 
            NestBaseOp newOp = null;
            List newPrefixSortKeys = Copy(op.PrefixSortKeys);
            if (ssnOp != null)
            { 
                VarVec newKeys = Copy(ssnOp.Keys);
                // Copy the SortOp's SortKeys 
                List newPostfixSortKeys = Copy(ssnOp.PostfixSortKeys); 
                newOp = m_destCmd.CreateSingleStreamNestOp(newKeys, newPrefixSortKeys, newPostfixSortKeys, newOutputs, newCollectionInfoList, newDiscriminator);
            } 
            else
            {
                newOp = m_destCmd.CreateMultiStreamNestOp(newPrefixSortKeys, newOutputs, newCollectionInfoList);
            } 

            return m_destCmd.CreateNode(newOp, newChildren); 
        } 

        ///  
        /// Copies a singleStreamNestOp
        /// 
        /// 
        ///  
        /// 
        public override Node Visit(SingleStreamNestOp op, Node n) 
        { 
            return VisitNestOp(n);
        } 

        /// 
        /// Copies a multiStreamNestOp
        ///  
        /// 
        ///  
        ///  
        public override Node Visit(MultiStreamNestOp op, Node n)
        { 
            return VisitNestOp(n);
        }
        #endregion
 
        #endregion
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK