Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Query / InternalTrees / OpCopier.cs
1 //---------------------------------------------------------------------
2 // <copyright file="OpCopier.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner  Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 // Interesting cases: Unnest
11 // More generally, note that any subtree that is left-correlated will stay as such.
12 //
13
14 namespace System.Data.Query.InternalTrees
15 {
16     using System;
17     using System.Collections.Generic;
18     using System.Diagnostics;
19
20     /// <summary>
21     /// Handles copying of operators
22     /// </summary>
23     internal class OpCopier : BasicOpVisitorOfNode
24     {
25         #region (pseudo) Public API
26         internal static Node Copy(Command cmd, Node n)
27         {
28             VarMap varMap;
29             return Copy(cmd, n, out varMap);
30         }
31
32         /// <summary>
33         /// Make a copy of the current node. Also return an ordered list of the new
34         /// Vars corresponding to the vars in "varList"
35         /// </summary>
36         /// <param name="cmd">current command</param>
37         /// <param name="node">the node to clone</param>
38         /// <param name="varList">list of Vars</param>
39         /// <param name="newVarList">list of "new" Vars</param>
40         /// <returns>the cloned node</returns>
41         internal static Node Copy(Command cmd, Node node, VarList varList, out VarList newVarList)
42         {
43             VarMap varMap;
44             Node newNode = Copy(cmd, node, out varMap);
45             newVarList = Command.CreateVarList();
46             foreach (Var v in varList)
47             {
48                 Var newVar = varMap[v];
49                 newVarList.Add(newVar);
50             }
51             return newNode;
52         }
53
54         internal static Node Copy(Command cmd, Node n, out VarMap varMap)
55         {
56             OpCopier oc = new OpCopier(cmd);
57             Node newNode = oc.CopyNode(n);
58             varMap = oc.m_varMap;
59             return newNode;
60         }
61
62         internal static List<SortKey> Copy(Command cmd, List<SortKey> sortKeys)
63         {
64             OpCopier oc = new OpCopier(cmd);
65             return oc.Copy(sortKeys);
66         }
67         #endregion
68
69         // WARNING
70         // Everything below this line should be local to this class
71         // WARNING
72
73         #region Private State
74         private Command m_srcCmd;
75         protected Command m_destCmd;
76         // Map of var to cloned Var
77         protected VarMap m_varMap;
78         #endregion
79
80         #region Constructors (private)
81         /// <summary>
82         /// Constructor. Allows for cloning of nodes within the same command
83         /// </summary>
84         /// <param name="cmd">The command</param>
85         protected OpCopier(Command cmd) : this(cmd, cmd) {}
86
87         /// <summary>
88         /// Constructor. Allows for cloning of nodes across commands
89         /// </summary>
90         /// <param name="destCommand">The Command to which Nodes to be cloned must belong</param>
91         /// <param name="sourceCommand">The Command to which cloned Nodes will belong</param>
92         private OpCopier(Command destCommand, Command sourceCommand)
93         {
94             m_srcCmd = sourceCommand;
95             m_destCmd = destCommand;
96             m_varMap = new VarMap();
97         }
98         #endregion
99
100         #region Private State Management
101
102         /// <summary>
103         /// Get the "cloned" var for a given Var.
104         /// If no cloned var exists, return the input Var itself
105         /// </summary>
106         /// <param name="v">The Var for which the cloned Var should be retrieved</param>
107         /// <returns>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</returns>
108         private Var GetMappedVar(Var v)
109         {
110             Var mappedVar;
111
112             //
113             // Return a mapping if there is one
114             //
115             if (m_varMap.TryGetValue(v, out mappedVar))
116             {
117                 return mappedVar;
118             }
119
120             //
121             // No mapping found.
122             // If we're cloning to a different command, this is an error
123             //
124             if (m_destCmd != m_srcCmd)
125             {
126                 throw EntityUtil.InternalError(EntityUtil.InternalErrorCode.UnknownVar, 6); 
127             }
128
129             //
130             // otherwise return the current Var itself
131             //
132             return v;
133         }
134
135         /// <summary>
136         /// Set the "cloned" var for a given Var
137         /// WARNING: If a mapping already exists, an exception is raised
138         /// </summary>
139         /// <param name="v">The original Var</param>
140         /// <param name="mappedVar">The cloned Var</param>
141         private void SetMappedVar(Var v, Var mappedVar)
142         {
143             m_varMap.Add(v, mappedVar);
144         }
145
146         /// <summary>
147         /// Maps columns of an existing table to those of the cloned table
148         /// </summary>
149         /// <param name="newTable">The original Table</param>
150         /// <param name="oldTable">The cloned Table</param>
151         private void MapTable(Table newTable, Table oldTable)
152         {
153             // Map the corresponding columns of the table
154             // Now set up the column map
155             for (int i = 0; i < oldTable.Columns.Count; i++)
156             {
157                 SetMappedVar(oldTable.Columns[i], newTable.Columns[i]);
158             }
159         }
160
161         /// <summary>
162         /// Produce the "mapped" Vars for each Var in the input sequence, while
163         /// preserving the original order
164         /// </summary>
165         /// <param name="vars">input var sequence</param>
166         /// <returns>output mapped vars</returns>
167         private IEnumerable<Var> MapVars(IEnumerable<Var> vars)
168         {
169             foreach (Var v in vars)
170             {
171                 Var mappedVar = GetMappedVar(v);
172                 yield return mappedVar;
173             }
174         }
175
176         /// <summary>
177         /// Create a mapped varvec. A new varvec that "maps" all the Vars from
178         /// the original Varvec
179         /// </summary>
180         /// <param name="vars">the varvec to clone</param>
181         /// <returns>a mapped varvec</returns>
182         private VarVec Copy(VarVec vars)
183         {
184             VarVec newVarVec = m_destCmd.CreateVarVec(MapVars(vars));
185             return newVarVec;
186         }
187
188         /// <summary>
189         /// Create a mapped copy of the input VarList - each var from the input varlist
190         /// is represented by its mapped var (and in exactly the same order) in the output
191         /// varlist
192         /// </summary>
193         /// <param name="varList">varList to map</param>
194         /// <returns>mapped varlist</returns>
195         private VarList Copy(VarList varList)
196         {
197             VarList newVarList = Command.CreateVarList(MapVars(varList));
198             return newVarList;
199         }
200
201         /// <summary>
202         /// Copies a sortkey
203         /// </summary>
204         /// <param name="sortKey">The SortKey to clone</param>
205         /// <returns>A new SortKey that is a clone of sortKey</returns>
206         private SortKey Copy(SortKey sortKey)
207         {
208             return Command.CreateSortKey(
209                 GetMappedVar(sortKey.Var),
210                 sortKey.AscendingSort,
211                 sortKey.Collation
212             );
213         }
214
215         /// <summary>
216         /// Copies a list of Sortkeys
217         /// </summary>
218         /// <param name="sortKeys">The list of SortKeys</param>
219         /// <returns>A new list containing clones of the specified SortKeys</returns>
220         private List<SortKey> Copy(List<SortKey> sortKeys)
221         {
222             List<SortKey> newSortKeys = new List<SortKey>();
223             foreach (SortKey k in sortKeys)
224             {
225                 newSortKeys.Add(Copy(k));
226             }
227             return newSortKeys;
228         }
229
230         #endregion
231
232         #region Visitor Helpers
233
234         /// <summary>
235         /// Simple wrapper for all copy operations
236         /// </summary>
237         /// <param name="n">The Node to copy</param>
238         /// <returns>A new Node that is a copy of the specified Node</returns>
239         protected Node CopyNode(Node n)
240         {
241             return n.Op.Accept<Node>(this, n);
242         }
243
244         /// <summary>
245         /// Copies all the Child Nodes of the specified Node
246         /// </summary>
247         /// <param name="n">The Node for which the child Nodes should be copied</param>
248         /// <returns>A new list containing copies of the specified Node's children</returns>
249         private List<Node> ProcessChildren(Node n)
250         {
251             List<Node> children = new List<Node>();
252             foreach (Node chi in n.Children)
253             {
254                 children.Add(CopyNode(chi));
255             }
256             return children;
257         }
258
259         /// <summary>
260         /// Creates a new Node with the specified Op as its Op and the result of visiting the specified Node's children as its children
261         /// </summary>
262         /// <param name="op">The Op that the new Node should reference</param>
263         /// <param name="original">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</param>
264         /// <returns>A new Node with the specified Op as its Op and the cloned child Nodes as its children</returns>
265         private Node CopyDefault(Op op, Node original)
266         {
267             return m_destCmd.CreateNode(op, ProcessChildren(original));
268         }
269         #endregion
270
271         #region IOpVisitor<Node> Members
272
273         /// <summary>
274         /// Default Visitor pattern method for unrecognized Ops
275         /// </summary>
276         /// <param name="op">The unrecognized Op</param>
277         /// <param name="n">The Node that references the Op</param>
278         /// <returns>This method always throws NotSupportedException</returns>
279         /// <exception cref="NotSupportedException">By design to indicate that the Op was not recognized and is therefore unsupported</exception>
280         public override Node Visit(Op op, Node n)
281         {
282             throw new NotSupportedException(System.Data.Entity.Strings.Iqt_General_UnsupportedOp(op.GetType().FullName));
283         }
284
285         #region ScalarOps
286
287         /// <summary>
288         /// Copies a ConstantOp
289         /// </summary>
290         /// <param name="op">The Op to Copy</param>
291         /// <param name="n">The Node that references the Op</param>
292         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
293         public override Node Visit(ConstantOp op, Node n)
294         {
295             ConstantBaseOp newOp = m_destCmd.CreateConstantOp(op.Type, op.Value);
296             return m_destCmd.CreateNode(newOp);
297         }
298
299         /// <summary>
300         /// Copies a NullOp
301         /// </summary>
302         /// <param name="op">The Op to Copy</param>
303         /// <param name="n">The Node that references the Op</param>
304         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
305         public override Node Visit(NullOp op, Node n)
306         {
307             return m_destCmd.CreateNode(m_destCmd.CreateNullOp(op.Type));
308         }
309
310         /// <summary>
311         /// Copies a ConstantPredicateOp
312         /// </summary>
313         /// <param name="op">The Op to Copy</param>
314         /// <param name="n">The Node that references the Op</param>
315         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
316         public override Node Visit(ConstantPredicateOp op, Node n)
317         {
318             return m_destCmd.CreateNode(m_destCmd.CreateConstantPredicateOp(op.Value));
319         }
320
321         /// <summary>
322         /// Copies an InternalConstantOp
323         /// </summary>
324         /// <param name="op">The Op to Copy</param>
325         /// <param name="n">The Node that references the Op</param>
326         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
327         public override Node Visit(InternalConstantOp op, Node n)
328         {
329             InternalConstantOp newOp = m_destCmd.CreateInternalConstantOp(op.Type, op.Value);
330             return m_destCmd.CreateNode(newOp);
331         }
332
333         /// <summary>
334         /// Copies a NullSentinelOp
335         /// </summary>
336         /// <param name="op">The Op to Copy</param>
337         /// <param name="n">The Node that references the Op</param>
338         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
339         public override Node Visit(NullSentinelOp op, Node n)
340         {
341             NullSentinelOp newOp = m_destCmd.CreateNullSentinelOp();
342             return m_destCmd.CreateNode(newOp);
343         }
344
345         /// <summary>
346         /// Copies a FunctionOp
347         /// </summary>
348         /// <param name="op">The Op to Copy</param>
349         /// <param name="n">The Node that references the Op</param>
350         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
351         public override Node Visit(FunctionOp op, Node n)
352         {
353             return CopyDefault(m_destCmd.CreateFunctionOp(op.Function), n);
354         }
355
356         /// <summary>
357         /// Copies a PropertyOp
358         /// </summary>
359         /// <param name="op">The Op to Copy</param>
360         /// <param name="n">The Node that references the Op</param>
361         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
362         public override Node Visit(PropertyOp op, Node n)
363         {
364             return CopyDefault(m_destCmd.CreatePropertyOp(op.PropertyInfo), n);
365         }
366
367         /// <summary>
368         /// Copies a RelPropertyOp
369         /// </summary>
370         /// <param name="op">the RelPropertyOp to copy</param>
371         /// <param name="n">node tree corresponding to 'op'</param>
372         /// <returns>a copy of the node tree</returns>
373         public override Node Visit(RelPropertyOp op, Node n)
374         {
375             return CopyDefault(m_destCmd.CreateRelPropertyOp(op.PropertyInfo), n);
376         }
377
378         /// <summary>
379         /// Copies a CaseOp
380         /// </summary>
381         /// <param name="op">The Op to Copy</param>
382         /// <param name="n">The Node that references the Op</param>
383         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
384         public override Node Visit(CaseOp op, Node n)
385         {
386             return CopyDefault(m_destCmd.CreateCaseOp(op.Type), n);
387         }
388
389         /// <summary>
390         /// Copies a ComparisonOp
391         /// </summary>
392         /// <param name="op">The Op to Copy</param>
393         /// <param name="n">The Node that references the Op</param>
394         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
395         public override Node Visit(ComparisonOp op, Node n)
396         {
397             return CopyDefault(m_destCmd.CreateComparisonOp(op.OpType), n);
398         }
399
400         /// <summary>
401         /// Copies a like-op
402         /// </summary>
403         /// <param name="op">The Op to Copy</param>
404         /// <param name="n">The Node that references the Op</param>
405         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
406         public override Node Visit(LikeOp op, Node n)
407         {
408             return CopyDefault(m_destCmd.CreateLikeOp(), n);
409         }
410
411         /// <summary>
412         /// Clone an aggregateop
413         /// </summary>
414         /// <param name="op">The Op to Copy</param>
415         /// <param name="n">The Node that references the Op</param>
416         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
417         public override Node Visit(AggregateOp op, Node n)
418         {
419             return CopyDefault(m_destCmd.CreateAggregateOp(op.AggFunc, op.IsDistinctAggregate), n);
420         }
421
422         /// <summary>
423         /// Copies a type constructor
424         /// </summary>
425         /// <param name="op">The Op to Copy</param>
426         /// <param name="n">The Node that references the Op</param>
427         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
428         public override Node Visit(NewInstanceOp op, Node n)
429         {
430             return CopyDefault(m_destCmd.CreateNewInstanceOp(op.Type), n);
431         }
432
433         /// <summary>
434         /// Copies a NewEntityOp
435         /// </summary>
436         /// <param name="op">the NewEntityOp to copy</param>
437         /// <param name="n">node tree corresponding to the NewEntityOp</param>
438         /// <returns>a copy of the node tree</returns>
439         public override Node Visit(NewEntityOp op, Node n)
440         {
441             NewEntityOp opCopy;
442             if (op.Scoped)
443             {
444                 opCopy = m_destCmd.CreateScopedNewEntityOp(op.Type, op.RelationshipProperties, op.EntitySet);
445             }
446             else
447             {
448                 Debug.Assert(op.EntitySet == null, "op.EntitySet must be null for the constructor that hasn't been scoped yet.");
449                 opCopy = m_destCmd.CreateNewEntityOp(op.Type, op.RelationshipProperties);
450             }
451             return CopyDefault(opCopy, n);
452         }
453
454         /// <summary>
455         /// Copies a discriminated type constructor
456         /// </summary>
457         /// <param name="op">The Op to Copy</param>
458         /// <param name="n">The Node that references the Op</param>
459         /// <returns>A copy of the original Node that references a copy of the original Op</returns>        
460         public override Node Visit(DiscriminatedNewEntityOp op, Node n)
461         {
462             return CopyDefault(m_destCmd.CreateDiscriminatedNewEntityOp(op.Type, op.DiscriminatorMap, op.EntitySet, op.RelationshipProperties), n);
463         }
464
465         /// <summary>
466         /// Copies a multiset constructor
467         /// </summary>
468         /// <param name="op">The Op to Copy</param>
469         /// <param name="n">The Node that references the Op</param>
470         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
471         public override Node Visit(NewMultisetOp op, Node n)
472         {
473             return CopyDefault(m_destCmd.CreateNewMultisetOp(op.Type), n);
474         }
475
476         /// <summary>
477         /// Copies a record constructor
478         /// </summary>
479         /// <param name="op">The Op to Copy</param>
480         /// <param name="n">The Node that references the Op</param>
481         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
482         public override Node Visit(NewRecordOp op, Node n)
483         {
484             return CopyDefault(m_destCmd.CreateNewRecordOp(op.Type), n);
485         }
486
487         /// <summary>
488         /// Copies a RefOp
489         /// </summary>
490         /// <param name="op">The Op to Copy</param>
491         /// <param name="n">The Node that references the Op</param>
492         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
493         public override Node Visit(RefOp op, Node n)
494         {
495             return CopyDefault(m_destCmd.CreateRefOp(op.EntitySet, op.Type), n);
496         }
497
498         /// <summary>
499         /// Copies a VarRefOp
500         /// </summary>
501         /// <param name="op">The Op to Copy</param>
502         /// <param name="n">The Node that references the Op</param>
503         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
504         public override Node Visit(VarRefOp op, Node n)
505         {
506             // Look up the newVar.
507             // If no var is available in the map, that implies that the Var is defined
508             // outside this subtree (and it is therefore safe to use it).
509             Var newVar;
510             if (!m_varMap.TryGetValue(op.Var, out newVar))
511                 newVar = op.Var;
512             // no children for a VarRef
513             return m_destCmd.CreateNode(m_destCmd.CreateVarRefOp(newVar));
514         }
515
516         /// <summary>
517         /// Copies a ConditionalOp
518         /// </summary>
519         /// <param name="op">The Op to Copy</param>
520         /// <param name="n">The Node that references the Op</param>
521         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
522         public override Node Visit(ConditionalOp op, Node n)
523         {
524             return CopyDefault(m_destCmd.CreateConditionalOp(op.OpType), n);
525         }
526
527         /// <summary>
528         /// Copies an ArithmeticOp
529         /// </summary>
530         /// <param name="op">The Op to Copy</param>
531         /// <param name="n">The Node that references the Op</param>
532         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
533         public override Node Visit(ArithmeticOp op, Node n)
534         {
535             return CopyDefault(m_destCmd.CreateArithmeticOp(op.OpType, op.Type), n);
536         }
537
538         /// <summary>
539         /// Copies a TreatOp
540         /// </summary>
541         /// <param name="op">The Op to Copy</param>
542         /// <param name="n">The Node that references the Op</param>
543         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
544         public override Node Visit(TreatOp op, Node n)
545         {
546             TreatOp newTreatOp = op.IsFakeTreat ? m_destCmd.CreateFakeTreatOp(op.Type) : m_destCmd.CreateTreatOp(op.Type);
547             return CopyDefault(newTreatOp, n);
548         }
549
550         /// <summary>
551         /// Copies a CastOp
552         /// </summary>
553         /// <param name="op">The Op to Copy</param>
554         /// <param name="n">The Node that references the Op</param>
555         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
556         public override Node Visit(CastOp op, Node n)
557         {
558             return CopyDefault(m_destCmd.CreateCastOp(op.Type), n);
559         }
560
561         /// <summary>
562         /// Copies a SoftCastOp
563         /// </summary>
564         /// <param name="op">The Op to Copy</param>
565         /// <param name="n">The Node that references the Op</param>
566         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
567         public override Node Visit(SoftCastOp op, Node n)
568         {
569             return CopyDefault(m_destCmd.CreateSoftCastOp(op.Type), n);
570         }
571
572         /// <summary>
573         /// Copies a DerefOp
574         /// </summary>
575         /// <param name="op">the derefOp to copy</param>
576         /// <param name="n">the subtree</param>
577         /// <returns>a copy of the subtree</returns>
578         public override Node Visit(DerefOp op, Node n)
579         {
580             return CopyDefault(m_destCmd.CreateDerefOp(op.Type), n);
581         }
582
583         /// <summary>
584         /// Copies a NavigateOp
585         /// </summary>
586         /// <param name="op">the NavigateOp</param>
587         /// <param name="n">the subtree</param>
588         /// <returns>a copy of the subtree</returns>
589         public override Node Visit(NavigateOp op, Node n)
590         {
591             return CopyDefault(m_destCmd.CreateNavigateOp(op.Type, op.RelProperty), n);
592         }
593
594         /// <summary>
595         /// Clone an IsOfOp
596         /// </summary>
597         /// <param name="op">The Op to Copy</param>
598         /// <param name="n">The Node that references the Op</param>
599         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
600         public override Node Visit(IsOfOp op, Node n)
601         {
602             if (op.IsOfOnly)
603                 return CopyDefault(m_destCmd.CreateIsOfOnlyOp(op.IsOfType), n);
604             else
605                 return CopyDefault(m_destCmd.CreateIsOfOp(op.IsOfType), n);
606         }
607
608         /// <summary>
609         /// Clone an ExistsOp
610         /// </summary>
611         /// <param name="op">The Op to Copy</param>
612         /// <param name="n">The Node that references the Op</param>
613         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
614         public override Node Visit(ExistsOp op, Node n)
615         {
616             return CopyDefault(m_destCmd.CreateExistsOp(), n);
617         }
618
619         /// <summary>
620         /// Clone an ElementOp
621         /// </summary>
622         /// <param name="op">The Op to Copy</param>
623         /// <param name="n">The Node that references the Op</param>
624         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
625         public override Node Visit(ElementOp op, Node n)
626         {
627             return CopyDefault(m_destCmd.CreateElementOp(op.Type), n);
628         }
629
630         /// <summary>
631         /// Copies a GetRefKeyOp
632         /// </summary>
633         /// <param name="op">The Op to Copy</param>
634         /// <param name="n">The Node that references the Op</param>
635         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
636         public override Node Visit(GetRefKeyOp op, Node n)
637         {
638             return CopyDefault(m_destCmd.CreateGetRefKeyOp(op.Type), n);
639         }
640
641         /// <summary>
642         /// Copies a GetEntityRefOp
643         /// </summary>
644         /// <param name="op">The Op to Copy</param>
645         /// <param name="n">The Node that references the Op</param>
646         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
647         public override Node Visit(GetEntityRefOp op, Node n)
648         {
649             return CopyDefault(m_destCmd.CreateGetEntityRefOp(op.Type), n);
650         }
651
652         /// <summary>
653         /// Copies a CollectOp
654         /// </summary>
655         /// <param name="op">The Op to Copy</param>
656         /// <param name="n">The Node that references the Op</param>
657         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
658         public override Node Visit(CollectOp op, Node n)
659         {
660             return CopyDefault(m_destCmd.CreateCollectOp(op.Type), n);
661         }
662
663         #endregion
664
665         #region RelOps
666
667         /// <summary>
668         /// Copies a ScanTableOp
669         /// </summary>
670         /// <param name="op">The Op to Copy</param>
671         /// <param name="n">The Node that references the Op</param>
672         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
673         public override Node Visit(ScanTableOp op, Node n)
674         {
675             // First create a new ScanTableOp based on the metadata of the existing Op
676             ScanTableOp newScan = m_destCmd.CreateScanTableOp(op.Table.TableMetadata);
677             // Map the corresponding tables/columns
678             MapTable(newScan.Table, op.Table);
679
680             // Create the new node
681             Debug.Assert(!n.HasChild0);
682             return m_destCmd.CreateNode(newScan);
683         }
684
685         /// <summary>
686         /// Copies a ScanViewOp
687         /// </summary>
688         /// <param name="op">The Op to Copy</param>
689         /// <param name="n">The Node that references the Op</param>
690         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
691         public override Node Visit(ScanViewOp op, Node n)
692         {
693             // First create a new ScanViewOp based on the metadata of the existing Op
694             ScanViewOp newScan = m_destCmd.CreateScanViewOp(op.Table.TableMetadata);
695             // Map the corresponding tables/columns
696             MapTable(newScan.Table, op.Table);
697
698             // Create the new node
699             Debug.Assert(n.HasChild0);
700             List<Node> children = ProcessChildren(n);
701             return m_destCmd.CreateNode(newScan, children);
702         }
703
704         /// <summary>
705         /// Clone an UnnestOp
706         /// </summary>
707         /// <param name="op">The Op to Copy</param>
708         /// <param name="n">The Node that references the Op</param>
709         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
710         public override Node Visit(UnnestOp op, Node n)
711         {
712             // Visit the Node's children and map their Vars
713             List<Node> children = ProcessChildren(n);
714
715             // Get the mapped unnest-var
716             Var mappedVar = GetMappedVar(op.Var);
717
718             // Create a new unnestOp
719             Table newTable = m_destCmd.CreateTableInstance(op.Table.TableMetadata);
720             UnnestOp newUnnest = m_destCmd.CreateUnnestOp(mappedVar, newTable);
721
722             // Map the corresponding tables/columns
723             MapTable(newUnnest.Table, op.Table);
724
725             // create the unnest node
726             return m_destCmd.CreateNode(newUnnest, children);
727         }
728
729         /// <summary>
730         /// Copies a ProjectOp
731         /// </summary>
732         /// <param name="op">The Op to Copy</param>
733         /// <param name="n">The Node that references the Op</param>
734         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
735         public override Node Visit(ProjectOp op, Node n)
736         {
737             // Visit the Node's children and map their Vars
738             List<Node> children = ProcessChildren(n);
739
740             // Copy the ProjectOp's VarSet
741             VarVec newVarSet = Copy(op.Outputs);
742
743             // Create a new ProjectOp based on the copied VarSet
744             ProjectOp newProject = m_destCmd.CreateProjectOp(newVarSet);
745
746             // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children
747             return m_destCmd.CreateNode(newProject, children);
748         }
749
750         /// <summary>
751         /// Copies a filterOp
752         /// </summary>
753         /// <param name="op">The Op to Copy</param>
754         /// <param name="n">The Node that references the Op</param>
755         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
756         public override Node Visit(FilterOp op, Node n)
757         {
758             return CopyDefault(m_destCmd.CreateFilterOp(), n);
759         }
760
761         /// <summary>
762         /// Copies a sort node
763         /// </summary>
764         /// <param name="op">The Op to Copy</param>
765         /// <param name="n">The Node that references the Op</param>
766         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
767         public override Node Visit(SortOp op, Node n)
768         {
769             // Visit the Node's children and map their Vars
770             List<Node> children = ProcessChildren(n);
771
772             // Copy the SortOp's SortKeys
773             List<SortKey> newSortKeys = Copy(op.Keys);
774
775             // Create a new SortOp that uses the copied SortKeys
776             SortOp newSortOp = m_destCmd.CreateSortOp(newSortKeys);
777
778             // Return a new Node that references the copied SortOp and has the copied child Nodes as its children
779             return m_destCmd.CreateNode(newSortOp, children);
780         }
781
782         /// <summary>
783         /// Copies a constrained sort node
784         /// </summary>
785         /// <param name="op">The Op to Copy</param>
786         /// <param name="n">The Node that references the Op</param>
787         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
788         public override Node Visit(ConstrainedSortOp op, Node n)
789         {
790             // Visit the Node's children and map their Vars
791             List<Node> children = ProcessChildren(n);
792
793             // Copy the ConstrainedSortOp's SortKeys
794             List<SortKey> newSortKeys = Copy(op.Keys);
795
796             // Create a new ConstrainedSortOp that uses the copied SortKeys and the original Op's WithTies value
797             ConstrainedSortOp newSortOp = m_destCmd.CreateConstrainedSortOp(newSortKeys, op.WithTies);
798
799             // Return a new Node that references the copied SortOp and has the copied child Nodes as its children
800             return m_destCmd.CreateNode(newSortOp, children);
801         }
802
803         /// <summary>
804         /// Copies a group-by node
805         /// </summary>
806         /// <param name="op">The Op to Copy</param>
807         /// <param name="n">The Node that references the Op</param>
808         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
809         public override Node Visit(GroupByOp op, Node n)
810         {
811             // Visit the Node's children and map their Vars
812             List<Node> children = ProcessChildren(n);
813
814             // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
815             GroupByOp newGroupOp = m_destCmd.CreateGroupByOp(Copy(op.Keys), Copy(op.Outputs));
816
817             // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children
818             return m_destCmd.CreateNode(newGroupOp, children);
819         }
820
821         /// <summary>
822         /// Copies a group by into node
823         /// </summary>
824         /// <param name="op">The Op to Copy</param>
825         /// <param name="n">The Node that references the Op</param>
826         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
827         public override Node Visit(GroupByIntoOp op, Node n)
828         {
829             // Visit the Node's children and map their Vars
830             List<Node> children = ProcessChildren(n);
831
832             // Create a new GroupByOp that uses copies of the Key and Output VarSets of the original GroupByOp
833             GroupByIntoOp newGroupOp = m_destCmd.CreateGroupByIntoOp(Copy(op.Keys), Copy(op.Inputs),  Copy(op.Outputs));
834
835             // Return a new Node that references the copied GroupByOp and has the copied child Nodes as its children
836             return m_destCmd.CreateNode(newGroupOp, children);
837         }
838
839         /// <summary>
840         /// Copies a CrossJoinOp
841         /// </summary>
842         /// <param name="op">The Op to Copy</param>
843         /// <param name="n">The Node that references the Op</param>
844         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
845         public override Node Visit(CrossJoinOp op, Node n)
846         {
847             return CopyDefault(m_destCmd.CreateCrossJoinOp(), n);
848         }
849
850         /// <summary>
851         /// Copies an InnerJoinOp
852         /// </summary>
853         /// <param name="op">The Op to Copy</param>
854         /// <param name="n">The Node that references the Op</param>
855         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
856         public override Node Visit(InnerJoinOp op, Node n)
857         {
858             return CopyDefault(m_destCmd.CreateInnerJoinOp(), n);
859         }
860
861         /// <summary>
862         /// Copies a LeftOuterJoinOp
863         /// </summary>
864         /// <param name="op">The Op to Copy</param>
865         /// <param name="n">The Node that references the Op</param>
866         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
867         public override Node Visit(LeftOuterJoinOp op, Node n)
868         {
869             return CopyDefault(m_destCmd.CreateLeftOuterJoinOp(), n);
870         }
871
872         /// <summary>
873         /// Copies a FullOuterJoinOp
874         /// </summary>
875         /// <param name="op">The Op to Copy</param>
876         /// <param name="n">The Node that references the Op</param>
877         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
878         public override Node Visit(FullOuterJoinOp op, Node n)
879         {
880             return CopyDefault(m_destCmd.CreateFullOuterJoinOp(), n);
881         }
882
883         /// <summary>
884         /// Copies a crossApplyOp
885         /// </summary>
886         /// <param name="op">The Op to Copy</param>
887         /// <param name="n">The Node that references the Op</param>
888         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
889         public override Node Visit(CrossApplyOp op, Node n)
890         {
891             return CopyDefault(m_destCmd.CreateCrossApplyOp(), n);
892         }
893
894         /// <summary>
895         /// Clone an OuterApplyOp
896         /// </summary>
897         /// <param name="op">The Op to Copy</param>
898         /// <param name="n">The Node that references the Op</param>
899         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
900         public override Node Visit(OuterApplyOp op, Node n)
901         {
902             return CopyDefault(m_destCmd.CreateOuterApplyOp(), n);
903         }
904
905         /// <summary>
906         /// Common copy path for all SetOps
907         /// </summary>
908         /// <param name="op">The SetOp to Copy (must be one of ExceptOp, IntersectOp, UnionAllOp)</param>
909         /// <param name="n">The Node that references the Op</param>
910         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
911         private Node CopySetOp(SetOp op, Node n)
912         {
913             // Visit the Node's children and map their Vars
914             List<Node> children = ProcessChildren(n);
915
916             VarMap leftMap = new VarMap();
917             VarMap rightMap = new VarMap();
918
919             
920             foreach (KeyValuePair<Var, Var> kv in op.VarMap[0])
921             {
922                 // Create a new output Var that is a copy of the original output Var
923                 Var outputVar = m_destCmd.CreateSetOpVar(kv.Key.Type);
924
925                 // Add a mapping for the new output var we've just created
926                 SetMappedVar(kv.Key, outputVar);
927
928                 // Add this output var's entries to the new VarMaps
929                 leftMap.Add(outputVar, GetMappedVar(kv.Value));
930                 rightMap.Add(outputVar, GetMappedVar((op.VarMap[1])[kv.Key]));
931             }
932
933             SetOp newSetOp = null;
934             switch(op.OpType)
935             {
936                 case OpType.UnionAll:
937                     {
938                         Var branchDiscriminator = ((UnionAllOp)op).BranchDiscriminator;
939                         if (null != branchDiscriminator) 
940                         {
941                             branchDiscriminator = GetMappedVar(branchDiscriminator);
942                         }
943                         newSetOp = m_destCmd.CreateUnionAllOp(leftMap, rightMap, branchDiscriminator);
944                     }
945                     break;
946
947                 case OpType.Intersect:
948                     {
949                         newSetOp = m_destCmd.CreateIntersectOp(leftMap, rightMap);
950                     }
951                     break;
952
953                 case OpType.Except:
954                     {
955                         newSetOp = m_destCmd.CreateExceptOp(leftMap, rightMap);
956                     }
957                     break;
958
959                 default:
960                     {
961                         Debug.Assert(false, "Unexpected SetOpType");
962                     }
963                     break;
964             }
965
966             return m_destCmd.CreateNode(newSetOp, children);
967         }
968
969         /// <summary>
970         /// Copies a UnionAllOp
971         /// </summary>
972         /// <param name="op">The Op to Copy</param>
973         /// <param name="n">The Node that references the Op</param>
974         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
975         public override Node Visit(UnionAllOp op, Node n)
976         {
977             return CopySetOp(op, n);
978         }
979
980         /// <summary>
981         /// Copies an IntersectOp
982         /// </summary>
983         /// <param name="op">The Op to Copy</param>
984         /// <param name="n">The Node that references the Op</param>
985         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
986         public override Node Visit(IntersectOp op, Node n)
987         {
988             return CopySetOp(op, n);
989         }
990
991         /// <summary>
992         /// Copies an ExceptOp
993         /// </summary>
994         /// <param name="op">The Op to Copy</param>
995         /// <param name="n">The Node that references the Op</param>
996         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
997         public override Node Visit(ExceptOp op, Node n)
998         {
999             return CopySetOp(op, n);
1000         }
1001
1002         /// <summary>
1003         /// Copies a DistinctOp
1004         /// </summary>
1005         /// <param name="op">The Op to Copy</param>
1006         /// <param name="n">The Node that references the Op</param>
1007         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
1008         public override Node Visit(DistinctOp op, Node n)
1009         {
1010             // Visit the Node's children and map their Vars
1011             List<Node> children = ProcessChildren(n);
1012
1013             // Copy the DistinctOp's Keys
1014             VarVec newDistinctKeys = Copy(op.Keys);
1015
1016             // Create a new DistinctOp that uses the copied keys
1017             DistinctOp newDistinctOp = m_destCmd.CreateDistinctOp(newDistinctKeys);
1018
1019             // Return a new Node that references the copied DistinctOp and has the copied child Nodes as its children
1020             return m_destCmd.CreateNode(newDistinctOp, children);
1021         }
1022
1023         public override Node Visit(SingleRowOp op, Node n)
1024         {
1025             return CopyDefault(m_destCmd.CreateSingleRowOp(), n);
1026         }
1027
1028         public override Node Visit(SingleRowTableOp op, Node n)
1029         {
1030             return CopyDefault(m_destCmd.CreateSingleRowTableOp(), n);
1031         }
1032
1033         #endregion
1034
1035         #region AncillaryOps
1036         /// <summary>
1037         /// Copies a VarDefOp
1038         /// </summary>
1039         /// <param name="op">The Op to Copy</param>
1040         /// <param name="n">The Node that references the Op</param>
1041         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
1042         public override Node Visit(VarDefOp op, Node n)
1043         {
1044             // First create a new Var
1045             List<Node> children = ProcessChildren(n);
1046             Debug.Assert(op.Var.VarType == VarType.Computed, "Unexpected VarType");
1047             Var newVar = m_destCmd.CreateComputedVar(op.Var.Type);
1048             SetMappedVar(op.Var, newVar);
1049             return m_destCmd.CreateNode(m_destCmd.CreateVarDefOp(newVar), children);
1050         }
1051
1052         /// <summary>
1053         /// Copies a VarDefListOp
1054         /// </summary>
1055         /// <param name="op">The Op to Copy</param>
1056         /// <param name="n">The Node that references the Op</param>
1057         /// <returns>A copy of the original Node that references a copy of the original Op</returns>
1058         public override Node Visit(VarDefListOp op, Node n)
1059         {
1060             return CopyDefault(m_destCmd.CreateVarDefListOp(), n);
1061         }
1062         #endregion
1063
1064         #region RulePatternOps
1065         #endregion
1066
1067         #region PhysicalOps
1068         private ColumnMap Copy(ColumnMap columnMap)
1069         {
1070             return ColumnMapCopier.Copy(columnMap, m_varMap);
1071         }
1072
1073         /// <summary>
1074         /// Copies a PhysicalProjectOp
1075         /// </summary>
1076         /// <param name="op"></param>
1077         /// <param name="n"></param>
1078         /// <returns></returns>
1079         public override Node Visit(PhysicalProjectOp op, Node n)
1080         {
1081             // Visit the Node's children and map their Vars
1082             List<Node> children = ProcessChildren(n);
1083
1084             // Copy the ProjectOp's VarSet
1085             VarList newVarList = Copy(op.Outputs);
1086
1087             SimpleCollectionColumnMap newColumnMap = Copy(op.ColumnMap) as SimpleCollectionColumnMap;
1088             Debug.Assert(newColumnMap != null, "Coping of a physical project's columnMap did not return a SimpleCollectionColumnMap" );
1089             // Create a new ProjectOp based on the copied VarSet
1090             PhysicalProjectOp newProject = m_destCmd.CreatePhysicalProjectOp(newVarList, newColumnMap);
1091
1092             // Return a new Node that references the copied ProjectOp and has the copied child Nodes as its children
1093             return m_destCmd.CreateNode(newProject, children);
1094         }
1095
1096         private Node VisitNestOp(Node n)
1097         {
1098             NestBaseOp op = n.Op as NestBaseOp;
1099             SingleStreamNestOp ssnOp = op as SingleStreamNestOp;
1100             Debug.Assert(op != null);
1101
1102             // Visit the Node's children and map their Vars
1103             List<Node> newChildren = ProcessChildren(n);
1104
1105             Var newDiscriminator = null;
1106             if (ssnOp != null)
1107             {
1108                 newDiscriminator = GetMappedVar(ssnOp.Discriminator);
1109             }
1110             List<CollectionInfo> newCollectionInfoList = new List<CollectionInfo>();
1111             foreach (CollectionInfo ci in op.CollectionInfo)
1112             {
1113                 ColumnMap newColumnMap = Copy(ci.ColumnMap);
1114
1115                 Var newCollectionVar = m_destCmd.CreateComputedVar(ci.CollectionVar.Type);
1116                 SetMappedVar(ci.CollectionVar, newCollectionVar);
1117
1118                 VarList newFlattendElementVars = Copy(ci.FlattenedElementVars);
1119                 VarVec newKeys = Copy(ci.Keys);
1120                 List<SortKey> newSortKeys = Copy(ci.SortKeys);
1121                 CollectionInfo newCollectionInfo = Command.CreateCollectionInfo(newCollectionVar, newColumnMap, newFlattendElementVars, newKeys, newSortKeys, ci.DiscriminatorValue);
1122                 newCollectionInfoList.Add(newCollectionInfo);
1123             }
1124
1125             VarVec newOutputs = Copy(op.Outputs);
1126
1127             NestBaseOp newOp = null;
1128             List<SortKey> newPrefixSortKeys = Copy(op.PrefixSortKeys);
1129             if (ssnOp != null)
1130             {
1131                 VarVec newKeys = Copy(ssnOp.Keys);
1132                 // Copy the SortOp's SortKeys
1133                 List<SortKey> newPostfixSortKeys = Copy(ssnOp.PostfixSortKeys);
1134                 newOp = m_destCmd.CreateSingleStreamNestOp(newKeys, newPrefixSortKeys, newPostfixSortKeys, newOutputs, newCollectionInfoList, newDiscriminator);
1135             }
1136             else
1137             {
1138                 newOp = m_destCmd.CreateMultiStreamNestOp(newPrefixSortKeys, newOutputs, newCollectionInfoList);
1139             }
1140
1141             return m_destCmd.CreateNode(newOp, newChildren);
1142         }
1143
1144         /// <summary>
1145         /// Copies a singleStreamNestOp
1146         /// </summary>
1147         /// <param name="op"></param>
1148         /// <param name="n"></param>
1149         /// <returns></returns>
1150         public override Node Visit(SingleStreamNestOp op, Node n)
1151         {
1152             return VisitNestOp(n);
1153         }
1154
1155         /// <summary>
1156         /// Copies a multiStreamNestOp
1157         /// </summary>
1158         /// <param name="op"></param>
1159         /// <param name="n"></param>
1160         /// <returns></returns>
1161         public override Node Visit(MultiStreamNestOp op, Node n)
1162         {
1163             return VisitNestOp(n);
1164         }
1165         #endregion
1166
1167         #endregion
1168     }
1169 }