0dabf7fa15f8f53eb529cff7549c3f42acf2d992
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Query / InternalTrees / Command.cs
1 //---------------------------------------------------------------------
2 // <copyright file="Command.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner  Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System.Collections.Generic;
11 using System.Data.Common;
12 using System.Data.Metadata.Edm;
13 using System.Data.Query.PlanCompiler;
14 using System.Diagnostics;
15 using System.Linq;
16
17 namespace System.Data.Query.InternalTrees
18 {
19     /// <summary>
20     /// The Command object encapsulates all information relating to a single command.
21     /// It includes the expression tree in question, as well as the parameters to the
22     /// command.
23     /// Additionally, the Command class serves as a factory for building up different
24     /// nodes and Ops. Every node in the tree has a unique id, and this is enforced by
25     /// the node factory methods
26     /// </summary>
27     internal class Command
28     {
29         #region private state
30         private Dictionary<string, ParameterVar> m_parameterMap;
31         private List<Var> m_vars;
32         private List<Table> m_tables;
33         private Node m_root;
34         private MetadataWorkspace m_metadataWorkspace;
35         private TypeUsage m_boolType;
36         private TypeUsage m_intType;
37         private TypeUsage m_stringType;
38         private ConstantPredicateOp m_trueOp;
39         private ConstantPredicateOp m_falseOp;
40         private NodeInfoVisitor m_nodeInfoVisitor;
41         private PlanCompiler.KeyPullup m_keyPullupVisitor;
42         private int m_nextNodeId;
43         private int m_nextBranchDiscriminatorValue = 1000;
44
45         private bool m_disableVarVecEnumCaching;
46         private Stack<VarVec.VarVecEnumerator> m_freeVarVecEnumerators;
47         private Stack<VarVec> m_freeVarVecs;
48         
49
50         // set of referenced rel properties in this query
51         private HashSet<RelProperty> m_referencedRelProperties;
52         #endregion
53
54         #region constructors
55         /// <summary>
56         /// Creates a new command
57         /// </summary>
58         internal Command(MetadataWorkspace metadataWorkspace)
59         {
60             m_parameterMap = new Dictionary<string, ParameterVar>();
61             m_vars = new List<Var>();
62             m_tables = new List<Table>();
63             m_metadataWorkspace = metadataWorkspace;
64             if(!TryGetPrimitiveType(PrimitiveTypeKind.Boolean, out m_boolType))
65             {
66                 throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Cqt_General_NoProviderBooleanType);
67             }
68             if (!TryGetPrimitiveType(PrimitiveTypeKind.Int32, out m_intType))
69             {
70                 throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Cqt_General_NoProviderIntegerType);
71             }
72             if (!TryGetPrimitiveType(PrimitiveTypeKind.String, out m_stringType))
73             {
74                 throw EntityUtil.ProviderIncompatible(System.Data.Entity.Strings.Cqt_General_NoProviderStringType);
75             }
76             m_trueOp = new ConstantPredicateOp(m_boolType, true);
77             m_falseOp = new ConstantPredicateOp(m_boolType, false);
78             m_nodeInfoVisitor = new NodeInfoVisitor(this);
79             m_keyPullupVisitor = new PlanCompiler.KeyPullup(this);
80
81             // FreeLists
82             m_freeVarVecEnumerators = new Stack<VarVec.VarVecEnumerator>();
83             m_freeVarVecs = new Stack<VarVec>();
84
85             m_referencedRelProperties = new HashSet<RelProperty>();
86         }
87         #endregion
88
89         #region public methods
90         /// <summary>
91         /// Gets the metadata workspace associated with this command
92         /// </summary>
93         internal MetadataWorkspace MetadataWorkspace { get { return m_metadataWorkspace; } }
94                 
95         /// <summary>
96         /// Gets/sets the root node of the query
97         /// </summary>
98         internal Node Root { get { return m_root; } set { m_root = value; } }
99
100         internal void DisableVarVecEnumCaching() { m_disableVarVecEnumCaching = true; } 
101                 
102         /// <summary>
103         /// Returns the next value for a UnionAll BranchDiscriminator.
104         /// </summary>
105         internal int NextBranchDiscriminatorValue { get { return m_nextBranchDiscriminatorValue++; } }
106
107         /// <summary>
108         /// Returns the next value for a node id, without incrementing it. 
109         /// </summary>
110         internal int NextNodeId { get { return m_nextNodeId; } }
111
112         #region Metadata Helpers
113         /// <summary>
114         /// Helper routine to get the metadata representation for the bool type
115         /// </summary>
116         internal TypeUsage BooleanType
117         {
118             get { return m_boolType; }
119         }
120
121         /// <summary>
122         /// Helper routine to get the metadata representation of the int type
123         /// </summary>
124         internal TypeUsage IntegerType
125         {
126             get { return m_intType; }
127         }
128
129         /// <summary>
130         /// Helper routine to get the metadata representation of the string type
131         /// </summary>
132         internal TypeUsage StringType
133         {
134             get { return m_stringType; }
135         }
136
137         /// <summary>
138         /// Get the primitive type by primitive type kind
139         /// </summary>
140         /// <param name="modelType">EdmMetadata.PrimitiveTypeKind of the primitive type</param>
141         /// <param name="type">A TypeUsage that represents the specified primitive type</param>
142         /// <returns><c>True</c> if the specified primitive type could be retrieved; otherwise <c>false</c>.</returns>
143         private bool TryGetPrimitiveType(PrimitiveTypeKind modelType, out TypeUsage type)
144         {
145             type = null;
146
147             if (modelType == PrimitiveTypeKind.String)
148             {
149                 type = TypeUsage.CreateStringTypeUsage(m_metadataWorkspace.GetModelPrimitiveType(modelType), 
150                                                        false /*unicode*/, 
151                                                        false /*fixed*/);
152             }
153             else
154             {
155                 type = m_metadataWorkspace.GetCanonicalModelTypeUsage(modelType);
156             }
157
158             return (null != type);
159         }
160         #endregion
161
162         #region VarVec Creation
163         /// <summary>
164         /// VarVec constructor
165         /// </summary>
166         /// <returns>A new, empty, VarVec</returns>
167         internal VarVec CreateVarVec()
168         {
169             VarVec vec;
170             if (m_freeVarVecs.Count == 0)
171             {
172                 vec = new VarVec(this);
173             }
174             else
175             {
176                 vec = m_freeVarVecs.Pop();
177                 vec.Clear();
178             }
179             return vec;
180         }
181
182         /// <summary>
183         /// Create a VarVec with a single Var
184         /// </summary>
185         /// <param name="v"></param>
186         /// <returns></returns>
187         internal VarVec CreateVarVec(Var v)
188         {
189             VarVec varset = CreateVarVec();
190             varset.Set(v);
191             return varset;
192         }
193
194         /// <summary>
195         /// Create a VarVec with the set of specified vars
196         /// </summary>
197         /// <param name="v"></param>
198         /// <returns></returns>
199         internal VarVec CreateVarVec(IEnumerable<Var> v)
200         {
201             VarVec vec = CreateVarVec();
202             vec.InitFrom(v);
203             return vec;
204         }
205
206         /// <summary>
207         /// Create a new VarVec from the input VarVec
208         /// </summary>
209         /// <param name="v"></param>
210         /// <returns></returns>
211         internal VarVec CreateVarVec(VarVec v)
212         {
213             VarVec vec = CreateVarVec();
214             vec.InitFrom(v);
215             return vec;
216         }
217
218         /// <summary>
219         /// Release a VarVec to the freelist
220         /// </summary>
221         /// <param name="vec"></param>
222         internal void ReleaseVarVec(VarVec vec)
223         {
224             m_freeVarVecs.Push(vec);
225         }
226         #endregion
227
228         #region VarVecEnumerator
229         /// <summary>
230         /// Create a new enumerator for a VarVec; use a free one if its
231         /// available; otherwise, create a new one
232         /// </summary>
233         /// <param name="vec"></param>
234         /// <returns></returns>
235         internal VarVec.VarVecEnumerator GetVarVecEnumerator(VarVec vec)
236         {
237             VarVec.VarVecEnumerator enumerator;
238
239             if (m_disableVarVecEnumCaching ||
240                 m_freeVarVecEnumerators.Count == 0)
241             {
242                 enumerator = new VarVec.VarVecEnumerator(vec);
243             }
244             else
245             {
246                 enumerator = m_freeVarVecEnumerators.Pop();
247                 enumerator.Init(vec);
248             }
249             return enumerator;
250         }
251
252         /// <summary>
253         /// Release an enumerator; keep it in a local stack for future use
254         /// </summary>
255         /// <param name="enumerator"></param>
256         internal void ReleaseVarVecEnumerator(VarVec.VarVecEnumerator enumerator)
257         {
258             if (!m_disableVarVecEnumCaching)
259             {
260                 m_freeVarVecEnumerators.Push(enumerator);
261             }
262         }
263         #endregion
264
265         #region VarList
266         /// <summary>
267         /// Create an ordered list of Vars - initially empty
268         /// </summary>
269         /// <returns></returns>
270         internal static VarList CreateVarList()
271         {
272             return new VarList();
273         }
274
275         /// <summary>
276         /// Create an ordered list of Vars
277         /// </summary>
278         /// <param name="vars"></param>
279         /// <returns></returns>
280         internal static VarList CreateVarList(IEnumerable<Var> vars)
281         {
282             return new VarList(vars);
283         }
284         #endregion
285
286         #region VarMap
287         internal VarMap CreateVarMap()
288         {
289             return new VarMap();
290         }
291
292         #endregion
293
294         #region Table Helpers
295
296         private int NewTableId()
297         {
298             return m_tables.Count;
299         }
300
301
302         /// <summary>
303         /// Create a table whose element type is "elementType"
304         /// </summary>
305         /// <param name="elementType">type of each element (row) of the table</param>
306         /// <returns>a table definition object</returns>
307         internal static TableMD CreateTableDefinition(TypeUsage elementType)
308         {
309             return new TableMD(elementType, null);
310         }
311
312         /// <summary>
313         /// Creates a new table definition based on an extent. The element type
314         /// of the extent manifests as the single column of the table
315         /// </summary>
316         /// <param name="extent">the metadata extent</param>
317         /// <returns>A new TableMD instance based on the extent</returns>
318         internal static TableMD CreateTableDefinition(EntitySetBase extent)
319         {
320             return new TableMD(TypeUsage.Create(extent.ElementType), extent);
321         }
322
323         /// <summary>
324         /// Create a "flat" table definition object (ie) the table has one column 
325         /// for each property of the specified row type
326         /// </summary>
327         /// <param name="type">the shape of each row of the table</param>
328         /// <returns>the table definition</returns>
329         internal TableMD CreateFlatTableDefinition(RowType type)
330         {
331             return CreateFlatTableDefinition(type.Properties, new List<EdmMember>(), null);
332         }
333
334         /// <summary>
335         /// Create a "flat" table defintion. The table has one column for each property
336         /// specified, and the key columns of the table are those specified in the 
337         /// keyMembers parameter
338         /// </summary>
339         /// <param name="properties">list of columns for the table</param>
340         /// <param name="keyMembers">the key columns (if any)</param>
341         /// <param name="entitySet">(OPTIONAL) entityset corresponding to this table</param>
342         /// <returns></returns>
343         internal TableMD CreateFlatTableDefinition(IEnumerable<EdmProperty> properties, IEnumerable<EdmMember> keyMembers, EntitySetBase entitySet)
344         {
345             return new TableMD(properties, keyMembers, entitySet);
346         }
347
348         /// <summary>
349         /// Creates a new table instance
350         /// </summary>
351         /// <param name="tableMetadata">table metadata</param>
352         /// <returns>A new Table instance with columns as defined in the specified metadata</returns>
353         internal Table CreateTableInstance(TableMD tableMetadata)
354         {
355             Table t = new Table(this, tableMetadata, NewTableId());
356             m_tables.Add(t);
357             return t;
358         }
359
360         #endregion
361
362         #region Var Access
363
364         /// <summary>
365         /// All vars in the query
366         /// </summary>
367         internal IEnumerable<Var> Vars
368         {
369             get { return m_vars.Where(v => v.VarType != VarType.NotValid); }
370         }
371
372         /// <summary>
373         /// Access an existing variable in the query (by its id)
374         /// </summary>
375         /// <param name="id">The ID of the variable to retrieve</param>
376         /// <returns>The variable with the specified ID</returns>
377         internal Var GetVar(int id)
378         {
379             Debug.Assert(m_vars[id].VarType != VarType.NotValid, "The var has been replaced by a different var and is no longer valid.");
380
381             return m_vars[id];
382         }
383
384         /// <summary>
385         /// Gets the ParameterVar that corresponds to a given named parameter
386         /// </summary>
387         /// <param name="paramName">The name of the parameter for which to retrieve the ParameterVar</param>
388         /// <returns>The ParameterVar that corresponds to the specified parameter</returns>
389         internal ParameterVar GetParameter(string paramName)
390         {
391             return m_parameterMap[paramName];
392         }
393
394         #endregion
395
396         #region Var Creation
397
398         private int NewVarId()
399         {
400             return m_vars.Count;
401         }
402
403         /// <summary>
404         /// Creates a variable for a parameter in the query
405         /// </summary>
406         /// <param name="parameterName">The name of the parameter for which to create the var</param>
407         /// <param name="parameterType">The type of the parameter, and therefore the new var</param>
408         /// <returns>A new ParameterVar instance with the specified name and type</returns>
409         internal ParameterVar CreateParameterVar(string parameterName,
410             TypeUsage parameterType)
411         {
412             if (m_parameterMap.ContainsKey(parameterName))
413                 throw new Exception("duplicate parameter name: " + parameterName);
414             ParameterVar v = new ParameterVar(NewVarId(), parameterType, parameterName);
415             m_vars.Add(v);
416             m_parameterMap[parameterName] = v;
417             return v;
418         }
419
420         /// <summary>
421         /// Creates a variable for the given parameter variable and replaces it in parameter map.
422         /// </summary>
423         /// <param name="oldVar">Parameter variable that needs to replaced.</param>
424         /// <param name="generateReplacementType">Delegate that generates the replacement parameter's type.</param>
425         /// <returns>A new ParameterVar instance created of <paramref name="oldVar"/>.</returns>
426         /// <remarks>
427         /// This method should be used only to replace external enum or strong spatial parameters with a counterpart whose
428         /// type is the underlying type of the enum type, or the union type contating the strong spatial type of the <paramref name="oldVar"/>.
429         /// The operation invalidates the <paramref name="oldVar"/>. After the operation has completed 
430         /// the <paramref name="oldVar"/>) is invalidated internally and should no longer be used.
431         /// </remarks>Func<
432         private ParameterVar ReplaceParameterVar(ParameterVar oldVar, Func<TypeUsage, TypeUsage> generateReplacementType)
433         {
434             Debug.Assert(oldVar != null, "oldVar != null");
435             Debug.Assert(m_vars.Contains(oldVar));
436             ParameterVar v = new ParameterVar(NewVarId(), generateReplacementType(oldVar.Type), oldVar.ParameterName);
437             m_parameterMap[oldVar.ParameterName] = v;
438             m_vars.Add(v);
439             return v;
440         }
441
442         /// <summary>
443         /// Creates a variable for the given enum parameter variable and replaces it in parameter map.
444         /// </summary>
445         /// <param name="oldVar">Enum parameter variable that needs to replaced.</param>
446         /// <returns>A new ParameterVar instance created of <paramref name="oldVar"/>.</returns>
447         /// <remarks>
448         /// This method should be used only to replace external enum parameter with a counterpart whose
449         /// type is the underlying type of the enum type of the <paramref name="oldVar"/>.
450         /// The operation invalidates the <paramref name="oldVar"/>. After the operation has completed 
451         /// the <paramref name="oldVar"/>) is invalidated internally and should no longer be used.
452         /// </remarks>
453         internal ParameterVar ReplaceEnumParameterVar(ParameterVar oldVar)
454         {
455             return ReplaceParameterVar(oldVar, t => TypeHelpers.CreateEnumUnderlyingTypeUsage(t));
456         }
457
458         /// <summary>
459         /// Creates a variable for the given spatial parameter variable and replaces it in parameter map.
460         /// </summary>
461         /// <param name="oldVar">Spatial parameter variable that needs to replaced.</param>
462         /// <returns>A new ParameterVar instance created of <paramref name="oldVar"/>.</returns>
463         /// <remarks>
464         /// This method should be used only to replace external strong spatial parameter with a counterpart whose
465         /// type is the appropriate union type for <paramref name="oldVar"/>.
466         /// The operation invalidates the <paramref name="oldVar"/>. After the operation has completed 
467         /// the <paramref name="oldVar"/>) is invalidated internally and should no longer be used.
468         /// </remarks>
469         internal ParameterVar ReplaceStrongSpatialParameterVar(ParameterVar oldVar)
470         {
471             return ReplaceParameterVar(oldVar, t => TypeHelpers.CreateSpatialUnionTypeUsage(t));
472         }
473
474
475         /// <summary>
476         /// Creates a new var for a table column
477         /// </summary>
478         /// <param name="table">The table instance that produces the column</param>
479         /// <param name="columnMD">column metadata</param>
480         /// <returns>A new ColumnVar instance that references the specified column in the given table</returns>
481         internal ColumnVar CreateColumnVar(Table table, ColumnMD columnMD)
482         {
483             // create a new column var now
484             ColumnVar c = new ColumnVar(NewVarId(), table, columnMD);
485             table.Columns.Add(c);
486             m_vars.Add(c);
487             return c;
488         }
489
490         /// <summary>
491         /// Creates a computed var (ie) a variable that is computed by an expression
492         /// </summary>
493         /// <param name="type">The type of the result produced by the expression that defines the variable</param>
494         /// <returns>A new ComputedVar instance with the specified result type</returns>
495         internal ComputedVar CreateComputedVar(TypeUsage type)
496         {
497             ComputedVar v = new ComputedVar(NewVarId(), type);
498             m_vars.Add(v);
499             return v;
500         }
501
502         /// <summary>
503         /// Creates a SetOp Var of
504         /// </summary>
505         /// <param name="type">Datatype of the Var</param>
506         /// <returns>A new SetOp Var with the specified result type</returns>
507         internal SetOpVar CreateSetOpVar(TypeUsage type)
508         {
509             SetOpVar v = new SetOpVar(NewVarId(), type);
510             m_vars.Add(v);
511             return v;
512         }
513
514         #endregion
515
516         #region Node Creation
517         //
518         // The routines below help in node construction. All command tree nodes must go
519         // through these routines. These routines help to stamp each node with a unique
520         // id (the id is very helpful for debugging)
521         //
522
523         /// <summary>
524         /// Creates a Node with zero children
525         /// </summary>
526         /// <param name="op">The operator that the Node should reference</param>
527         /// <returns>A new Node with zero children that references the specified Op</returns>
528         internal Node CreateNode(Op op)
529         {
530             return this.CreateNode(op, new List<Node>());
531         }
532
533         /// <summary>
534         /// Creates a node with a single child Node
535         /// </summary>
536         /// <param name="op">The operator that the Node should reference</param>
537         /// <param name="arg1">The single child Node</param>
538         /// <returns>A new Node with the specified child Node, that references the specified Op</returns>
539         internal Node CreateNode(Op op, Node arg1)
540         {
541             List<Node> l = new List<Node>();
542             l.Add(arg1);
543             return this.CreateNode(op, l);
544         }
545
546         /// <summary>
547         /// Creates a node with two child Nodes
548         /// </summary>
549         /// <param name="op">The operator that the Node should reference</param>
550         /// <param name="arg1">The first child Node</param>
551         /// <param name="arg2">the second child Node</param>
552         /// <returns>A new Node with the specified child Nodes, that references the specified Op</returns>
553         internal Node CreateNode(Op op, Node arg1, Node arg2)
554         {
555             List<Node> l = new List<Node>();
556             l.Add(arg1); l.Add(arg2);
557             return this.CreateNode(op, l);
558         }
559
560         /// <summary>
561         /// Creates a node with 3 child Nodes
562         /// </summary>
563         /// <param name="op">The operator that the Node should reference</param>
564         /// <param name="arg1">The first child Node</param>
565         /// <param name="arg2">The second child Node</param>
566         /// <param name="arg3">The third child Node</param>
567         /// <returns>A new Node with the specified child Nodes, that references the specified Op</returns>
568         internal Node CreateNode(Op op, Node arg1, Node arg2, Node arg3)
569         {
570             List<Node> l = new List<Node>();
571             l.Add(arg1); l.Add(arg2); l.Add(arg3);
572             return this.CreateNode(op, l);
573         }
574
575         /// <summary>
576         /// Create a Node with the specified list of child Nodes
577         /// </summary>
578         /// <param name="op">The operator that the Node should reference</param>
579         /// <param name="args">The list of child Nodes</param>
580         /// <returns>A new Node with the specified child nodes, that references the specified Op</returns>
581         internal Node CreateNode(Op op, IList<Node> args)
582         {
583             return new Node(m_nextNodeId++, op, new List<Node>(args));
584         }
585
586         /// <summary>
587         /// Create a Node with the specified list of child Nodes
588         /// </summary>
589         /// <param name="op">The operator that the Node should reference</param>
590         /// <param name="args">The list of child Nodes</param>
591         /// <returns>A new Node with the specified child nodes, that references the specified Op</returns>
592         internal Node CreateNode(Op op, List<Node> args)
593         {
594             return new Node(m_nextNodeId++, op, args);
595         }
596
597         #endregion
598
599         #region ScalarOps
600
601         /// <summary>
602         /// Creates a new ConstantOp
603         /// </summary>
604         /// <param name="type">The type of the constant value</param>
605         /// <param name="value">The constant value (may be null)</param>
606         /// <returns>A new ConstantOp with the specified type and value</returns>
607         internal ConstantBaseOp CreateConstantOp(TypeUsage type, object value)
608         {
609             // create a NullOp if necessary
610             if (value == null)
611             {
612                 return new NullOp(type);
613             }
614             // Identify "safe" constants - the only safe ones are boolean (and we should
615             // probably include ints eventually)
616             else if (TypeSemantics.IsBooleanType(type))
617             {
618                 return new InternalConstantOp(type, value);
619             }
620             else
621             {
622                 return new ConstantOp(type, value);
623             }
624         }
625
626         /// <summary>
627         /// Create an "internal" constantOp - only for use by the plan compiler to 
628         /// represent internally generated constants.
629         /// User constants in the query should never get into this function
630         /// </summary>
631         /// <param name="type">datatype of the constant</param>
632         /// <param name="value">constant value</param>
633         /// <returns>a new "internal" constant op that represents the constant</returns>
634         internal InternalConstantOp CreateInternalConstantOp(TypeUsage type, object value)
635         {
636             return new InternalConstantOp(type, value);
637         }
638
639         /// <summary>
640         /// An internal constant that serves as a null sentinel, i.e. it is only ever used
641         /// to be checked whether it is null
642         /// </summary>
643         /// <returns></returns>
644         internal NullSentinelOp CreateNullSentinelOp()
645         {
646             return new NullSentinelOp(this.IntegerType, 1);
647         }
648
649         /// <summary>
650         /// An "internal" null constant
651         /// </summary>
652         /// <param name="type">datatype of the null constant</param>
653         /// <returns>a new "internal" null constant op</returns>
654         internal NullOp CreateNullOp(TypeUsage type)
655         {
656             return new NullOp(type);
657         }
658
659         /// <summary>
660         /// Create a constant predicateOp
661         /// </summary>
662         /// <param name="value">value of the constant predicate</param>
663         /// <returns></returns>
664         internal ConstantPredicateOp CreateConstantPredicateOp(bool value)
665         {
666             return value ? m_trueOp : m_falseOp;
667         }
668
669         /// <summary>
670         /// Create a constant predicate with value=true
671         /// </summary>
672         /// <returns></returns>
673         internal ConstantPredicateOp CreateTrueOp()
674         {
675             return m_trueOp;
676         }
677         /// <summary>
678         /// Create a constant predicateOp with the value false
679         /// </summary>
680         /// <returns></returns>
681         internal ConstantPredicateOp CreateFalseOp()
682         {
683             return m_falseOp;
684         }
685
686         /// <summary>
687         /// Creates a new FunctionOp
688         /// </summary>
689         /// <param name="function">EdmFunction metadata that represents the function that is invoked by the Op</param>
690         /// <returns>A new FunctionOp that references the specified function metadata</returns>
691         internal FunctionOp CreateFunctionOp(EdmFunction function)
692         {
693             return new FunctionOp(function);
694         }
695
696         /// <summary>
697         /// Creates a new TreatOp
698         /// </summary>
699         /// <param name="type">Type metadata that specifies the type that the child of the treat node should be treated as</param>
700         /// <returns>A new TreatOp that references the specified type metadata</returns>
701         internal TreatOp CreateTreatOp(TypeUsage type)
702         {
703             return new TreatOp(type, false);
704         }
705
706         /// <summary>
707         /// Create a "dummy" treatOp (i.e.) we can actually ignore the treatOp.
708         /// </summary>
709         /// <param name="type"></param>
710         /// <returns></returns>
711         internal TreatOp CreateFakeTreatOp(TypeUsage type)
712         {
713             return new TreatOp(type, true);
714         }
715
716         /// <summary>
717         /// Creates a new IsOfOp, which tests if the argument is of the specified type or a promotable type
718         /// </summary>
719         /// <param name="isOfType">Type metadata that specifies the type with which the type of the argument should be compared</param>
720         /// <returns>A new IsOfOp that references the specified type metadata</returns>
721         internal IsOfOp CreateIsOfOp(TypeUsage isOfType)
722         {
723             return new IsOfOp(isOfType, false/*only*/, m_boolType);
724         }
725         /// <summary>
726         /// Creates a new IsOfOp, which tests if the argument is of the specified type (and only the specified type)
727         /// </summary>
728         /// <param name="isOfType">Type metadata that specifies the type with which the type of the argument should be compared</param>
729         /// <returns>A new IsOfOp that references the specified type metadata</returns>
730         internal IsOfOp CreateIsOfOnlyOp(TypeUsage isOfType)
731         {
732             return new IsOfOp(isOfType, true /* "only" */, m_boolType);
733         }
734
735         /// <summary>
736         /// Creates a new CastOp
737         /// </summary>
738         /// <param name="type">Type metadata that represents the type to which the argument should be cast</param>
739         /// <returns>A new CastOp that references the specified type metadata</returns>
740         internal CastOp CreateCastOp(TypeUsage type)
741         {
742             return new CastOp(type);
743         }
744
745         /// <summary>
746         /// Creates a new SoftCastOp and casts the input to the desired type.
747         /// 
748         /// The caller is expected to determine if the cast is necessary or not
749         /// </summary>
750         /// <param name="type">Type metadata that represents the type to which the argument should be cast</param>
751         /// <returns>A new CastOp that references the specified type metadata</returns>
752         internal SoftCastOp CreateSoftCastOp(TypeUsage type)
753         {
754             return new SoftCastOp(type);
755         }
756
757         /// <summary>
758         /// Creates a new ComparisonOp of the specified type
759         /// </summary>
760         /// <param name="opType">An OpType that specifies one of the valid comparison OpTypes: EQ, GT, GE, NE, LT, LE</param>
761         /// <returns>A new ComparisonOp of the specified comparison OpType</returns>
762         internal ComparisonOp CreateComparisonOp(OpType opType)
763         {
764             return new ComparisonOp(opType, this.BooleanType);
765         }
766
767         /// <summary>
768         /// Creates a new LikeOp
769         /// </summary>
770         /// <returns>The new LikeOp</returns>
771         internal LikeOp CreateLikeOp()
772         {
773             return new LikeOp(this.BooleanType);
774         }
775
776         /// <summary>
777         /// Creates a new ConditionalOp of the specified type
778         /// </summary>
779         /// <param name="opType">An OpType that specifies one of the valid condition operations: And, Or, Not, IsNull</param>
780         /// <returns>A new ConditionalOp with the specified conditional OpType</returns>
781         internal ConditionalOp CreateConditionalOp(OpType opType)
782         {
783             return new ConditionalOp(opType, this.BooleanType);
784         }
785
786         /// <summary>
787         /// Creates a new CaseOp
788         /// </summary>
789         /// <param name="type">The result type of the CaseOp</param>
790         /// <returns>A new CaseOp with the specified result type</returns>
791         internal CaseOp CreateCaseOp(TypeUsage type)
792         {
793             return new CaseOp(type);
794         }
795
796         /// <summary>
797         /// Creates a new AggregateOp
798         /// </summary>
799         /// <param name="aggFunc">EdmFunction metadata that specifies the aggregate function</param>
800         /// <param name="distinctAgg">Indicates whether or not the aggregate is a distinct aggregate</param>
801         /// <returns>A new AggregateOp with the specified function metadata and distinct property</returns>
802         internal AggregateOp CreateAggregateOp(EdmFunction aggFunc, bool distinctAgg)
803         {
804             return new AggregateOp(aggFunc, distinctAgg);
805         }
806
807         /// <summary>
808         /// Creates a named type constructor
809         /// </summary>
810         /// <param name="type">Type metadata that specifies the type of the instance to construct</param>
811         /// <returns>A new NewInstanceOp with the specified result type</returns>
812         internal NewInstanceOp CreateNewInstanceOp(TypeUsage type)
813         {
814             return new NewInstanceOp(type);
815         }
816
817         /// <summary>
818         /// Build out a new NewEntityOp constructing the entity <paramref name="type"/> scoped to the <paramref name="entitySet"/>.
819         /// </summary>
820         internal NewEntityOp CreateScopedNewEntityOp(TypeUsage type, List<RelProperty> relProperties, EntitySet entitySet)
821         {
822             return new NewEntityOp(type, relProperties, true, entitySet);
823         }
824
825         /// <summary>
826         /// Build out a new NewEntityOp constructing the uscoped entity <paramref name="type"/>.
827         /// </summary>
828         internal NewEntityOp CreateNewEntityOp(TypeUsage type, List<RelProperty> relProperties)
829         {
830             return new NewEntityOp(type, relProperties, false, null);
831         }
832
833         /// <summary>
834         /// Create a discriminated named type constructor
835         /// </summary>
836         /// <param name="type">Type metadata that specifies the type of the instance to construct</param>
837         /// <param name="discriminatorMap">Mapping information including discriminator values</param>
838         /// <param name="entitySet">the entityset that this instance belongs to</param>
839         /// <param name="relProperties">list of rel properties that have corresponding values</param>
840         /// <returns>A new DiscriminatedNewInstanceOp with the specified result type and discrimination behavior</returns>
841         internal DiscriminatedNewEntityOp CreateDiscriminatedNewEntityOp(TypeUsage type, ExplicitDiscriminatorMap discriminatorMap,
842             EntitySet entitySet, List<RelProperty> relProperties)
843         {
844             return new DiscriminatedNewEntityOp(type, discriminatorMap, entitySet, relProperties);
845         }
846
847         /// <summary>
848         /// Creates a multiset constructor
849         /// </summary>
850         /// <param name="type">Type metadata that specifies the type of the multiset to construct</param>
851         /// <returns>A new NewMultiSetOp with the specified result type</returns>
852         internal NewMultisetOp CreateNewMultisetOp(TypeUsage type)
853         {
854             return new NewMultisetOp(type);
855         }
856
857         /// <summary>
858         /// Creates a record constructor
859         /// </summary>
860         /// <param name="type">Type metadata that specifies that record type to construct</param>
861         /// <returns>A new NewRecordOp with the specified result type</returns>
862         internal NewRecordOp CreateNewRecordOp(TypeUsage type)
863         {
864             return new NewRecordOp(type);
865         }
866
867         /// <summary>
868         /// Creates a record constructor
869         /// </summary>
870         /// <param name="type">Type metadata that specifies that record type to construct</param>
871         /// <returns>A new NewRecordOp with the specified result type</returns>
872         internal NewRecordOp CreateNewRecordOp(RowType type)
873         {
874             return new NewRecordOp(TypeUsage.Create(type));
875         }
876
877         /// <summary>
878         /// A variant of the above method to create a NewRecordOp. An additional
879         /// argument - fields - is supplied, and the semantics is that only these fields
880         /// have any values specified as part of the Node. All other fields are
881         /// considered to be null.
882         /// </summary>
883         /// <param name="type"></param>
884         /// <param name="fields"></param>
885         /// <returns></returns>
886         internal NewRecordOp CreateNewRecordOp(TypeUsage type,
887             List<EdmProperty> fields)
888         {
889             return new NewRecordOp(type, fields);
890         }
891
892         /// <summary>
893         /// Creates a new VarRefOp
894         /// </summary>
895         /// <param name="v">The variable to reference</param>
896         /// <returns>A new VarRefOp that references the specified variable</returns>
897         internal VarRefOp CreateVarRefOp(Var v)
898         {
899             return new VarRefOp(v);
900         }
901         /// <summary>
902         /// Creates a new ArithmeticOp of the specified type
903         /// </summary>
904         /// <param name="opType">An OpType that specifies one of the valid arithmetic operations: Plus, Minus, Multiply, Divide, Modulo, UnaryMinus</param>
905         /// <param name="type">Type metadata that specifies the result type of the arithmetic operation</param>
906         /// <returns>A new ArithmeticOp of the specified arithmetic OpType</returns>
907         internal ArithmeticOp CreateArithmeticOp(OpType opType, TypeUsage type)
908         {
909             return new ArithmeticOp(opType, type);
910         }
911
912         /// <summary>
913         /// Creates a new PropertyOp
914         /// </summary>
915         /// <param name="prop">EdmProperty metadata that specifies the property</param>
916         /// <returns>A new PropertyOp that references the specified property metadata</returns>
917         internal PropertyOp CreatePropertyOp(EdmMember prop)
918         {
919             //
920             // Track all rel-properties
921             //
922             NavigationProperty navProp = prop as NavigationProperty;
923             if (navProp != null)
924             {
925                 RelProperty relProperty = new RelProperty(navProp.RelationshipType, navProp.FromEndMember, navProp.ToEndMember);
926                 AddRelPropertyReference(relProperty);
927                 RelProperty inverseRelProperty = new RelProperty(navProp.RelationshipType, navProp.ToEndMember, navProp.FromEndMember);
928                 AddRelPropertyReference(inverseRelProperty);
929             }
930
931             // Actually create the propertyOp
932             return new PropertyOp(Helper.GetModelTypeUsage(prop), prop);
933         }
934
935         /// <summary>
936         /// Create a "relationship" propertyOp
937         /// </summary>
938         /// <param name="prop">the relationship property</param>
939         /// <returns>a RelPropertyOp</returns>
940         internal RelPropertyOp CreateRelPropertyOp(RelProperty prop)
941         {
942             AddRelPropertyReference(prop);
943             return new RelPropertyOp(prop.ToEnd.TypeUsage, prop);
944         }
945
946         /// <summary>
947         /// Creates a new RefOp
948         /// </summary>
949         /// <param name="entitySet">The EntitySet to which the ref refers</param>
950         /// <param name="type">The result type of the RefOp</param>
951         /// <returns>A new RefOp that references the specified EntitySet and has the specified result type</returns>
952         internal RefOp CreateRefOp(EntitySet entitySet, TypeUsage type)
953         {
954             return new RefOp(entitySet, type);
955         }
956
957         /// <summary>
958         /// Creates a new ExistsOp
959         /// </summary>
960         /// <returns>A new ExistsOp</returns>
961         internal ExistsOp CreateExistsOp()
962         {
963             return new ExistsOp(this.BooleanType);
964         }
965         /// <summary>
966         /// Creates a new ElementOp
967         /// </summary>
968         /// <param name="type">Type metadata that specifies the result (element) type</param>
969         /// <returns>A new ElementOp with the specified result type</returns>
970         internal ElementOp CreateElementOp(TypeUsage type)
971         {
972             return new ElementOp(type);
973         }
974
975         /// <summary>
976         /// Creates a new GetEntityRefOp: a ref-extractor (from an entity instance) Op
977         /// </summary>
978         /// <param name="type">Type metadata that specifies the result type</param>
979         /// <returns>A new GetEntityKeyOp with the specified result type</returns>
980         internal GetEntityRefOp CreateGetEntityRefOp(TypeUsage type)
981         {
982             return new GetEntityRefOp(type);
983         }
984         /// <summary>
985         /// Creates a new GetRefKeyOp: a key-extractor (from a ref instance) Op
986         /// </summary>
987         /// <param name="type">Type metadata that specifies the result type</param>
988         /// <returns>A new GetRefKeyOp with the specified result type</returns>
989         internal GetRefKeyOp CreateGetRefKeyOp(TypeUsage type)
990         {
991             return new GetRefKeyOp(type);
992         }
993
994         /// <summary>
995         /// Creates a new CollectOp
996         /// </summary>
997         /// <param name="type">Type metadata that specifies the result type of the Nest operation</param>
998         /// <returns>A new NestOp with the specified result type</returns>
999         internal CollectOp CreateCollectOp(TypeUsage type)
1000         {
1001             return new CollectOp(type);
1002         }
1003
1004         /// <summary>
1005         /// Create a DerefOp
1006         /// </summary>
1007         /// <param name="type">Entity type of the target entity</param>
1008         /// <returns>a DerefOp</returns>
1009         internal DerefOp CreateDerefOp(TypeUsage type)
1010         {
1011             return new DerefOp(type);
1012         }
1013
1014         /// <summary>
1015         /// Create a new NavigateOp node
1016         /// </summary>
1017         /// <param name="type">the output type of the navigateOp</param>
1018         /// <param name="relProperty">the relationship property</param>
1019         /// <returns>the navigateOp</returns>
1020         internal NavigateOp CreateNavigateOp(TypeUsage type, RelProperty relProperty)
1021         {
1022             // keep track of rel-properties
1023             AddRelPropertyReference(relProperty);
1024             return new NavigateOp(type, relProperty);
1025         }
1026
1027         #endregion
1028
1029         #region AncillaryOps
1030
1031         /// <summary>
1032         /// Creates a VarDefListOp
1033         /// </summary>
1034         /// <returns>A new VarDefListOp</returns>
1035         internal VarDefListOp CreateVarDefListOp()
1036         {
1037             return VarDefListOp.Instance;
1038         }
1039         /// <summary>
1040         /// Creates a VarDefOp (for a computed var)
1041         /// </summary>
1042         /// <param name="v">The computed var</param>
1043         /// <returns>A new VarDefOp that references the computed var</returns>
1044         internal VarDefOp CreateVarDefOp(Var v)
1045         {
1046             return new VarDefOp(v);
1047         }
1048
1049         /// <summary>
1050         /// Create a VarDefOp and the associated node for an expression.
1051         /// We create a computedVar first - of the same type as the expression, and
1052         /// then create a VarDefOp for the computed Var. Finally, we create a Node for
1053         /// the VarDefOp
1054         /// </summary>
1055         /// <param name="definingExpr"></param>
1056         /// <param name="computedVar">new Var produced</param>
1057         /// <returns></returns>
1058         internal Node CreateVarDefNode(Node definingExpr, out Var computedVar)
1059         {
1060             Debug.Assert(definingExpr.Op != null);
1061             ScalarOp scalarOp = definingExpr.Op as ScalarOp;
1062             Debug.Assert(scalarOp != null);
1063             computedVar = this.CreateComputedVar(scalarOp.Type);
1064             VarDefOp varDefOp = this.CreateVarDefOp(computedVar);
1065             Node varDefNode = this.CreateNode(varDefOp, definingExpr);
1066             return varDefNode;
1067         }
1068
1069         /// <summary>
1070         /// Creates a VarDefListOp with a single child - a VarDefOp created as in the function
1071         /// above.
1072         /// </summary>
1073         /// <param name="definingExpr"></param>
1074         /// <param name="computedVar">the computed Var produced</param>
1075         /// <returns></returns>
1076         internal Node CreateVarDefListNode(Node definingExpr, out Var computedVar)
1077         {
1078             Node varDefNode = this.CreateVarDefNode(definingExpr, out computedVar);
1079             VarDefListOp op = this.CreateVarDefListOp();
1080             Node varDefListNode = this.CreateNode(op, varDefNode);
1081             return varDefListNode;
1082         }
1083         #endregion
1084
1085         #region RelOps
1086
1087         /// <summary>
1088         /// Creates a new ScanTableOp
1089         /// </summary>
1090         /// <param name="tableMetadata">A Table metadata instance that specifies the table that should be scanned</param>
1091         /// <returns>A new ScanTableOp that references a new Table instance based on the specified table metadata</returns>
1092         internal ScanTableOp CreateScanTableOp(TableMD tableMetadata)
1093         {
1094             Table table = this.CreateTableInstance(tableMetadata);
1095             return CreateScanTableOp(table);
1096         }
1097         /// <summary>
1098         /// A variant of the above
1099         /// </summary>
1100         /// <param name="table">The table instance</param>
1101         /// <returns>a new ScanTableOp</returns>
1102         internal ScanTableOp CreateScanTableOp(Table table)
1103         {
1104             return new ScanTableOp(table);
1105         }
1106
1107         /// <summary>
1108         /// Creates an instance of a ScanViewOp
1109         /// </summary>
1110         /// <param name="table">the table instance</param>
1111         /// <returns>a new ScanViewOp</returns>
1112         internal ScanViewOp CreateScanViewOp(Table table)
1113         {
1114             return new ScanViewOp(table);
1115         }
1116         /// <summary>
1117         /// Creates an instance of a ScanViewOp
1118         /// </summary>
1119         /// <param name="tableMetadata">the table metadata</param>
1120         /// <returns>a new ScanViewOp</returns>
1121         internal ScanViewOp CreateScanViewOp(TableMD tableMetadata)
1122         {
1123             Table table = this.CreateTableInstance(tableMetadata);
1124             return this.CreateScanViewOp(table);
1125         }
1126         /// <summary>
1127         /// Creates a new UnnestOp, which creates a streaming result from a scalar (non-RelOp) value
1128         /// </summary>
1129         /// <param name="v">The Var that indicates the value to unnest</param>
1130         /// <returns>A new UnnestOp that targets the specified Var</returns>
1131         internal UnnestOp CreateUnnestOp(Var v)
1132         {
1133             Table t = this.CreateTableInstance(Command.CreateTableDefinition(TypeHelpers.GetEdmType<CollectionType>(v.Type).TypeUsage));
1134             return CreateUnnestOp(v, t);
1135         }
1136
1137         /// <summary>
1138         /// Creates a new UnnestOp - a variant of the above with the Table supplied
1139         /// </summary>
1140         /// <param name="v">the unnest Var</param>
1141         /// <param name="t">the table instance</param>
1142         /// <returns>a new UnnestOp</returns>
1143         internal UnnestOp CreateUnnestOp(Var v, Table t)
1144         {
1145             return new UnnestOp(v, t);
1146         }
1147
1148         /// <summary>
1149         /// Creates a new FilterOp
1150         /// </summary>
1151         /// <returns>A new FilterOp</returns>
1152         internal FilterOp CreateFilterOp()
1153         {
1154             return FilterOp.Instance;
1155         }
1156
1157         /// <summary>
1158         /// Creates a new ProjectOp
1159         /// </summary>
1160         /// <param name="vars">A VarSet that specifies the Vars produced by the projection</param>
1161         /// <returns>A new ProjectOp with the specified output VarSet</returns>
1162         internal ProjectOp CreateProjectOp(VarVec vars)
1163         {
1164             return new ProjectOp(vars);
1165         }
1166         /// <summary>
1167         /// A variant of the above where the ProjectOp produces exactly one var
1168         /// </summary>
1169         /// <param name="v"></param>
1170         /// <returns></returns>
1171         internal ProjectOp CreateProjectOp(Var v)
1172         {
1173             VarVec varSet = this.CreateVarVec();
1174             varSet.Set(v);
1175             return new ProjectOp(varSet);
1176         }
1177
1178         #region JoinOps
1179
1180         /// <summary>
1181         /// Creates a new InnerJoinOp
1182         /// </summary>
1183         /// <returns>A new InnerJoinOp</returns>
1184         internal InnerJoinOp CreateInnerJoinOp()
1185         {
1186             return InnerJoinOp.Instance;
1187         }
1188
1189         /// <summary>
1190         /// Creates a new LeftOuterJoinOp
1191         /// </summary>
1192         /// <returns>A new LeftOuterJoinOp</returns>
1193         internal LeftOuterJoinOp CreateLeftOuterJoinOp()
1194         {
1195             return LeftOuterJoinOp.Instance;
1196         }
1197
1198         /// <summary>
1199         /// Creates a new FullOuterJoinOp
1200         /// </summary>
1201         /// <returns>A new FullOuterJoinOp</returns>
1202         internal FullOuterJoinOp CreateFullOuterJoinOp()
1203         {
1204             return FullOuterJoinOp.Instance;
1205         }
1206
1207         /// <summary>
1208         /// Creates a new CrossJoinOp
1209         /// </summary>
1210         /// <returns>A new CrossJoinOp</returns>
1211         internal CrossJoinOp CreateCrossJoinOp()
1212         {
1213             return CrossJoinOp.Instance;
1214         }
1215
1216         #endregion
1217
1218         #region ApplyOps
1219
1220         /// <summary>
1221         /// Creates a new CrossApplyOp
1222         /// </summary>
1223         /// <returns>A new CrossApplyOp</returns>
1224         internal CrossApplyOp CreateCrossApplyOp()
1225         {
1226             return CrossApplyOp.Instance;
1227         }
1228         /// <summary>
1229         /// Creates a new OuterApplyOp
1230         /// </summary>
1231         /// <returns>A new OuterApplyOp</returns>
1232         internal OuterApplyOp CreateOuterApplyOp()
1233         {
1234             return OuterApplyOp.Instance;
1235         }
1236
1237         #endregion
1238
1239         #region SortKeys
1240
1241         /// <summary>
1242         /// Creates a new SortKey with the specified var, order and collation
1243         /// </summary>
1244         /// <param name="v">The variable to sort on</param>
1245         /// <param name="asc">The sort order (true for ascending, false for descending)</param>
1246         /// <param name="collation">The sort collation</param>
1247         /// <returns>A new SortKey with the specified var, order and collation</returns>
1248         internal static SortKey CreateSortKey(Var v, bool asc, string collation)
1249         {
1250             return new SortKey(v, asc, collation);
1251         }
1252         /// <summary>
1253         /// Creates a new SortKey with the specified var and order
1254         /// </summary>
1255         /// <param name="v">The variable to sort on</param>
1256         /// <param name="asc">The sort order (true for ascending, false for descending)</param>
1257         /// <returns>A new SortKey with the specified var and order</returns>
1258         internal static SortKey CreateSortKey(Var v, bool asc)
1259         {
1260             return new SortKey(v, asc, "");
1261         }
1262
1263         /// <summary>
1264         /// Creates a new SortKey with the specified var
1265         /// </summary>
1266         /// <param name="v">The variable to sort on</param>
1267         /// <returns>A new SortKey with the specified var</returns>
1268         internal static SortKey CreateSortKey(Var v)
1269         {
1270             return new SortKey(v, true, "");
1271         }
1272
1273         #endregion
1274
1275         /// <summary>
1276         /// Creates a new SortOp
1277         /// </summary>
1278         /// <param name="sortKeys">The list of SortKeys that define the sort var, order and collation for each sort key</param>
1279         /// <returns>A new SortOp with the specified sort keys</returns>
1280         internal SortOp CreateSortOp(List<SortKey> sortKeys)
1281         {
1282             return new SortOp(sortKeys);
1283         }
1284
1285         /// <summary>
1286         /// Creates a new ConstrainedSortOp
1287         /// </summary>
1288         /// <param name="sortKeys">The list of SortKeys that define the sort var, order and collation for each sort key</param>
1289         /// <returns>A new ConstrainedSortOp with the specified sort keys and a default WithTies value of false</returns>
1290         internal ConstrainedSortOp CreateConstrainedSortOp(List<SortKey> sortKeys)
1291         {
1292             return new ConstrainedSortOp(sortKeys, false);
1293         }
1294
1295         /// <summary>
1296         /// Creates a new ConstrainedSortOp
1297         /// </summary>
1298         /// <param name="sortKeys">The list of SortKeys that define the sort var, order and collation for each sort key</param>
1299         /// <param name="withTies">The value to use for the WithTies property of the new ConstrainedSortOp</param>
1300         /// <returns>A new ConstrainedSortOp with the specified sort keys and WithTies value</returns>
1301         internal ConstrainedSortOp CreateConstrainedSortOp(List<SortKey> sortKeys, bool withTies)
1302         {
1303             return new ConstrainedSortOp(sortKeys, withTies);
1304         }
1305
1306         /// <summary>
1307         /// Creates a new GroupByOp
1308         /// </summary>
1309         /// <param name="gbyKeys">A VarSet that specifies the Key variables produced by the GroupByOp</param>
1310         /// <param name="outputs">A VarSet that specifies all (Key and Aggregate) variables produced by the GroupByOp</param>
1311         /// <returns>A new GroupByOp with the specified key and output VarSets</returns>
1312         internal GroupByOp CreateGroupByOp(VarVec gbyKeys, VarVec outputs)
1313         {
1314             return new GroupByOp(gbyKeys, outputs);
1315         }
1316
1317         /// <summary>
1318         /// Creates a new GroupByIntoOp
1319         /// </summary>
1320         /// <param name="gbyKeys">A VarSet that specifies the Key variables produced by the GroupByOp</param>
1321         /// <param name="outputs">A VarSet that specifies the vars from the input that represent the real grouping input</param>
1322         /// <param name="inputs">A VarSet that specifies all (Key and Aggregate) variables produced by the GroupByOp</param>
1323         /// <returns>A new GroupByOp with the specified key and output VarSets</returns>
1324         internal GroupByIntoOp CreateGroupByIntoOp(VarVec gbyKeys, VarVec inputs, VarVec outputs)
1325         {
1326             return new GroupByIntoOp(gbyKeys, inputs, outputs);
1327         }
1328
1329         /// <summary>
1330         /// Creates a new DistinctOp
1331         /// <param name="keyVars">list of key vars</param>
1332         /// </summary>
1333         /// <returns>A new DistinctOp</returns>
1334         internal DistinctOp CreateDistinctOp(VarVec keyVars)
1335         {
1336             return new DistinctOp(keyVars);
1337         }
1338         /// <summary>
1339         /// An overload of the above - where the distinct has exactly one key
1340         /// </summary>
1341         /// <param name="keyVar"></param>
1342         /// <returns></returns>
1343         internal DistinctOp CreateDistinctOp(Var keyVar)
1344         {
1345             return new DistinctOp(this.CreateVarVec(keyVar));
1346         }
1347         
1348         /// <summary>
1349         /// Creates a new UnionAllOp
1350         /// </summary>
1351         /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
1352         /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
1353         /// <returns>A UnionAllOp that references the specified left and right Vars</returns>
1354         internal UnionAllOp CreateUnionAllOp(VarMap leftMap, VarMap rightMap)
1355         {
1356             return CreateUnionAllOp(leftMap, rightMap, null);
1357         }
1358
1359         /// <summary>
1360         /// Creates a new UnionAllOp, with a branch descriminator.
1361         /// </summary>
1362         /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
1363         /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
1364         /// <param name="branchDiscriminator">Var that contains the branch discrimination value (may be null until key pullup occurs)</param>
1365         /// <returns>A UnionAllOp that references the specified left and right Vars</returns>
1366         internal UnionAllOp CreateUnionAllOp(VarMap leftMap, VarMap rightMap, Var branchDiscriminator) 
1367         {
1368             Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
1369             VarVec vec = this.CreateVarVec();
1370             foreach (Var v in leftMap.Keys)
1371             {
1372                 vec.Set(v);
1373             }
1374             return new UnionAllOp(vec, leftMap, rightMap, branchDiscriminator);
1375         }
1376
1377         /// <summary>
1378         /// Creates a new IntersectOp
1379         /// </summary>
1380         /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
1381         /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
1382         /// <returns>An IntersectOp that references the specified left and right Vars</returns>
1383         internal IntersectOp CreateIntersectOp(VarMap leftMap, VarMap rightMap)
1384         {
1385             Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
1386             VarVec vec = this.CreateVarVec();
1387             foreach (Var v in leftMap.Keys)
1388             {
1389                 vec.Set(v);
1390             }
1391             return new IntersectOp(vec, leftMap, rightMap);
1392         }
1393         /// <summary>
1394         /// Creates a new ExceptOp
1395         /// </summary>
1396         /// <param name="leftMap">Mappings from the Output Vars to the Vars produced by the left argument</param>
1397         /// <param name="rightMap">Mappings from the Output Vars to the Vars produced by the right argument</param>
1398         /// <returns>An ExceptOp that references the specified left and right Vars</returns>
1399         internal ExceptOp CreateExceptOp(VarMap leftMap, VarMap rightMap)
1400         {
1401             Debug.Assert(leftMap.Count == rightMap.Count, "VarMap count mismatch");
1402             VarVec vec = this.CreateVarVec();
1403             foreach (Var v in leftMap.Keys)
1404             {
1405                 vec.Set(v);
1406             }
1407             return new ExceptOp(vec, leftMap, rightMap);
1408         }
1409
1410         /// <summary>
1411         /// Create a single-row-op (the relop analog of Element)
1412         /// </summary>
1413         /// <returns></returns>
1414         internal SingleRowOp CreateSingleRowOp()
1415         {
1416             return SingleRowOp.Instance;
1417         }
1418
1419         /// <summary>
1420         /// Create a SingleRowTableOp - a table with exactly one row (and no columns)
1421         /// </summary>
1422         /// <returns></returns>
1423         internal SingleRowTableOp CreateSingleRowTableOp()
1424         {
1425             return SingleRowTableOp.Instance;
1426         }
1427
1428         #endregion
1429
1430         #region PhysicalOps
1431         /// <summary>
1432         /// Create a PhysicalProjectOp - with a columnMap describing the output
1433         /// </summary>
1434         /// <param name="outputVars">list of output vars</param>
1435         /// <param name="columnMap">columnmap describing the output element</param>
1436         /// <returns></returns>
1437         internal PhysicalProjectOp CreatePhysicalProjectOp(VarList outputVars, SimpleCollectionColumnMap columnMap)
1438         {
1439             return new PhysicalProjectOp(outputVars, columnMap);
1440         }
1441         /// <summary>
1442         /// Create a physicalProjectOp - with a single column output
1443         /// </summary>
1444         /// <param name="outputVar">the output element</param>
1445         /// <returns></returns>
1446         internal PhysicalProjectOp CreatePhysicalProjectOp(Var outputVar)
1447         {
1448             VarList varList = Command.CreateVarList();
1449             varList.Add(outputVar);
1450             VarRefColumnMap varRefColumnMap = new VarRefColumnMap(outputVar);
1451
1452             SimpleCollectionColumnMap collectionColumnMap = new SimpleCollectionColumnMap(
1453                 TypeUtils.CreateCollectionType(varRefColumnMap.Type),   // type
1454                 null,                                                   // name
1455                 varRefColumnMap,                                        // element map
1456                 new SimpleColumnMap[0],                                 // keys
1457                 new SimpleColumnMap[0]);                                // foreign keys
1458             return CreatePhysicalProjectOp(varList, collectionColumnMap);
1459         }
1460
1461         /// <summary>
1462         /// Another overload - with an additional discriminatorValue.
1463         /// Should this be a subtype instead?
1464         /// </summary>
1465         /// <param name="collectionVar">the collectionVar</param>
1466         /// <param name="columnMap">column map for the collection element</param>
1467         /// <param name="flattenedElementVars">elementVars with any nested collections pulled up</param>
1468         /// <param name="keys">keys specific to this collection</param>
1469         /// <param name="sortKeys">sort keys specific to this collecion</param>
1470         /// <param name="discriminatorValue">discriminator value for this collection (under the current nestOp)</param>
1471         /// <returns>a new CollectionInfo instance</returns>
1472         internal static CollectionInfo CreateCollectionInfo(Var collectionVar, ColumnMap columnMap, VarList flattenedElementVars, VarVec keys, List<InternalTrees.SortKey> sortKeys, object discriminatorValue)
1473         {
1474             return new CollectionInfo(collectionVar, columnMap, flattenedElementVars, keys, sortKeys, discriminatorValue);
1475         }
1476
1477         /// <summary>
1478         /// Create a singleStreamNestOp
1479         /// </summary>
1480         /// <param name="keys">keys for the nest operation</param>
1481         /// <param name="prefixSortKeys">list of prefix sort keys</param>
1482         /// <param name="postfixSortKeys">list of postfix sort keys</param>
1483         /// <param name="outputVars">List of outputVars</param>
1484         /// <param name="collectionInfoList">CollectionInfo for each collection </param>
1485         /// <param name="discriminatorVar">Var describing the discriminator</param>
1486         /// <returns></returns>
1487         internal SingleStreamNestOp CreateSingleStreamNestOp(VarVec keys,
1488             List<SortKey> prefixSortKeys, List<SortKey> postfixSortKeys,
1489             VarVec outputVars,
1490             List<CollectionInfo> collectionInfoList, Var discriminatorVar)
1491         {
1492             return new SingleStreamNestOp(keys, prefixSortKeys, postfixSortKeys, outputVars, collectionInfoList, discriminatorVar);
1493         }
1494
1495         /// <summary>
1496         /// Create a MultiStreamNestOp
1497         /// </summary>
1498         /// <param name="prefixSortKeys">list of prefix sort keys</param>
1499         /// <param name="outputVars">List of outputVars</param>
1500         /// <param name="collectionInfoList">CollectionInfo for each collection element</param>
1501         /// <returns></returns>
1502         internal MultiStreamNestOp CreateMultiStreamNestOp(List<SortKey> prefixSortKeys, VarVec outputVars,
1503             List<CollectionInfo> collectionInfoList)
1504         {
1505             return new MultiStreamNestOp(prefixSortKeys, outputVars, collectionInfoList);
1506         }
1507         #endregion
1508
1509         #region NodeInfo
1510         /// <summary>
1511         /// Get auxilliary information for a Node
1512         /// </summary>
1513         /// <param name="n">the node</param>
1514         /// <returns>node info for this node</returns>
1515         internal NodeInfo GetNodeInfo(Node n)
1516         {
1517             return n.GetNodeInfo(this);
1518         }
1519
1520         /// <summary>
1521         /// Get extended node information for a RelOpNode
1522         /// </summary>
1523         /// <param name="n">the node</param>
1524         /// <returns>extended node info for this node</returns>
1525         internal ExtendedNodeInfo GetExtendedNodeInfo(Node n)
1526         {
1527             return n.GetExtendedNodeInfo(this);
1528         }
1529         /// <summary>
1530         /// Recompute the nodeinfo for a node, but only if has already been computed
1531         /// </summary>
1532         /// <param name="n">Node in question</param>
1533         internal void RecomputeNodeInfo(Node n)
1534         {
1535             m_nodeInfoVisitor.RecomputeNodeInfo(n);
1536         }
1537         #endregion
1538
1539         #region KeyInfo
1540         /// <summary>
1541         /// Pulls up keys if necessary and gets the key information for a Node
1542         /// </summary>
1543         /// <param name="n">node</param>
1544         /// <returns>key information</returns>
1545         internal KeyVec PullupKeys(Node n)
1546         {
1547             return m_keyPullupVisitor.GetKeys(n);
1548         }
1549         #endregion
1550
1551         #region Type Comparisons
1552         //
1553         // The functions described in this region are used through out the 
1554         // PlanCompiler to reason about type equality. Make sure that you 
1555         // use these and these alone
1556         //
1557
1558         /// <summary>
1559         /// Check to see if two types are considered "equal" for the purposes
1560         /// of the plan compiler. 
1561         /// Two types are considered to be equal if their "identities" are equal.
1562         /// </summary>
1563         /// <param name="x"></param>
1564         /// <param name="y"></param>
1565         /// <returns>true, if the types are "equal"</returns>
1566         internal static bool EqualTypes(TypeUsage x, TypeUsage y)
1567         {
1568             return PlanCompiler.TypeUsageEqualityComparer.Instance.Equals(x, y);
1569         }
1570         /// <summary>
1571         /// Check to see if two types are considered "equal" for the purposes
1572         /// of the plan compiler
1573         /// </summary>
1574         /// <param name="x"></param>
1575         /// <param name="y"></param>
1576         /// <returns>true, if the types are "equal"</returns>
1577         internal static bool EqualTypes(EdmType x, EdmType y)
1578         {
1579             return PlanCompiler.TypeUsageEqualityComparer.Equals(x, y);
1580         }
1581         #endregion
1582
1583         #region Builder Methods
1584         /// <summary>
1585         /// Builds out a UNION-ALL ladder from a sequence of node,var pairs.
1586         /// Assumption: Each node produces exactly one Var
1587         /// 
1588         /// If the input sequence has zero elements, we return null
1589         /// If the input sequence has one element, we return that single element
1590         /// Otherwise, we build out a UnionAll ladder from each of the inputs. If the input sequence was {A,B,C,D},
1591         /// we build up a union-all ladder that looks like 
1592         ///     (((A UA B) UA C) UA D)
1593         /// </summary>
1594         /// <param name="inputNodes">list of input nodes - one for each branch</param>
1595         /// <param name="inputVars">list of input vars - N for each branch</param>
1596         /// <param name="resultNode">the resulting union-all subtree</param>
1597         /// <param name="resultVar">the output vars from the union-all subtree</param>
1598         internal void BuildUnionAllLadder(
1599             IList<Node> inputNodes, IList<Var> inputVars,
1600             out Node resultNode, out IList<Var> resultVars)
1601         {
1602             if (inputNodes.Count == 0)
1603             {
1604                 resultNode = null;
1605                 resultVars = null;
1606                 return;
1607             }
1608
1609             int varPerNode = inputVars.Count / inputNodes.Count;
1610             Debug.Assert((inputVars.Count % inputNodes.Count == 0) && (varPerNode >= 1), "Inconsistent nodes/vars count:" + inputNodes.Count + "," + inputVars.Count);
1611
1612             if (inputNodes.Count == 1)
1613             {
1614                 resultNode = inputNodes[0];
1615                 resultVars = inputVars;
1616                 return;
1617             }
1618
1619             List<Var> unionAllVars = new List<Var>();
1620
1621             Node unionAllNode = inputNodes[0];
1622             for (int j = 0; j < varPerNode; j++)
1623             {
1624                 unionAllVars.Add(inputVars[j]);
1625             }
1626
1627             for (int i = 1; i < inputNodes.Count; i++)
1628             {
1629                 VarMap leftVarMap = this.CreateVarMap();
1630                 VarMap rightVarMap = this.CreateVarMap();
1631                 List<Var> setOpVars = new List<Var>();
1632                 for (int j = 0; j < varPerNode; j++)
1633                 {
1634                     SetOpVar newVar = this.CreateSetOpVar(unionAllVars[j].Type);
1635                     setOpVars.Add(newVar);
1636                     leftVarMap.Add(newVar, unionAllVars[j]);
1637                     rightVarMap.Add(newVar, inputVars[i * varPerNode + j]);
1638                 }
1639                 Op unionAllOp = this.CreateUnionAllOp(leftVarMap, rightVarMap);
1640                 unionAllNode = this.CreateNode(unionAllOp, unionAllNode, inputNodes[i]);
1641                 unionAllVars = setOpVars;
1642             }
1643
1644             resultNode = unionAllNode;
1645             resultVars = unionAllVars;
1646         }
1647
1648         /// <summary>
1649         /// A simplified version of the method above - each branch can produce only one var
1650         /// </summary>
1651         /// <param name="inputNodes"></param>
1652         /// <param name="inputVars"></param>
1653         /// <param name="resultNode"></param>
1654         /// <param name="resultVar"></param>
1655         internal void BuildUnionAllLadder(IList<Node> inputNodes, IList<Var> inputVars,
1656             out Node resultNode, out Var resultVar)
1657         {
1658             Debug.Assert(inputNodes.Count == inputVars.Count, "Count mismatch:" + inputNodes.Count + "," + inputVars.Count);
1659             IList<Var> varList;
1660             BuildUnionAllLadder(inputNodes, inputVars, out resultNode, out varList);
1661             if (varList != null && varList.Count > 0)
1662             {
1663                 resultVar = varList[0];
1664             }
1665             else
1666             {
1667                 resultVar = null;
1668             }
1669         }
1670
1671         /// <summary>
1672         /// Build a projectOp tree over the input. 
1673         /// This function builds a projectOp tree over the input. The Outputs (vars) of the project are the 
1674         /// list of vars from the input (inputVars), plus one computed Var for each of the computed expressions
1675         /// (computedExpressions)
1676         /// </summary>
1677         /// <param name="inputNode">the input relop to the project</param>
1678         /// <param name="inputVars">List of vars from the input that need to be projected</param>
1679         /// <param name="computedExpressions">list (possibly empty) of any computed expressions</param>
1680         /// <returns></returns>
1681         internal Node BuildProject(Node inputNode, IEnumerable<Var> inputVars,
1682             IEnumerable<Node> computedExpressions)
1683         {
1684             Debug.Assert(inputNode.Op.IsRelOp, "Expected a RelOp. Found " + inputNode.Op.OpType);
1685
1686             VarDefListOp varDefListOp = this.CreateVarDefListOp();
1687             Node varDefListNode = this.CreateNode(varDefListOp);
1688             VarVec projectVars = this.CreateVarVec(inputVars);
1689             foreach (Node expr in computedExpressions)
1690             {
1691                 Var v = this.CreateComputedVar(expr.Op.Type);
1692                 projectVars.Set(v);
1693                 VarDefOp varDefOp = this.CreateVarDefOp(v);
1694                 Node varDefNode = this.CreateNode(varDefOp, expr);
1695                 varDefListNode.Children.Add(varDefNode);
1696             }
1697             Node projectNode = this.CreateNode(
1698                 this.CreateProjectOp(projectVars),
1699                 inputNode,
1700                 varDefListNode);
1701             return projectNode;
1702         }
1703
1704         /// <summary>
1705         /// A "simpler" builder method for ProjectOp. The assumption is that the only output is the
1706         /// (var corresponding to) the computedExpression. None of the Vars of the "input" are projected out
1707         /// 
1708         /// The single output Var is returned in the "outputVar" parameter
1709         /// </summary>
1710         /// <param name="input">the input relop</param>
1711         /// <param name="computedExpression">the computed expression</param>
1712         /// <param name="projectVar">(output) the computed var corresponding to the computed expression</param>
1713         /// <returns>the new project subtree node</returns>
1714         internal Node BuildProject(Node input, Node computedExpression, out Var projectVar)
1715         {
1716             Node projectNode = BuildProject(input, new Var[] { }, new Node[] { computedExpression });
1717             projectVar = ((ProjectOp)projectNode.Op).Outputs.First;
1718             return projectNode;
1719         }
1720
1721         /// <summary>
1722         /// Build the equivalent of an OfTypeExpression over the input (ie) produce the set of values from the
1723         /// input that are of the desired type (exactly of the desired type, if the "includeSubtypes" parameter is false).
1724         /// 
1725         /// Further more, "update" the result element type to be the desired type.
1726         /// 
1727         /// We accomplish this by first building a FilterOp with an IsOf (or an IsOfOnly) predicate for the desired 
1728         /// type. We then build out a ProjectOp over the FilterOp, where we introduce a "Fake" TreatOp over the input
1729         /// element to cast it to the right type. The "Fake" TreatOp is only there for "compile-time" typing reasons,
1730         /// and will be ignored in the rest of the plan compiler
1731         /// </summary>
1732         /// <param name="inputNode">the input collection</param>
1733         /// <param name="inputVar">the single Var produced by the input collection</param>
1734         /// <param name="desiredType">the desired element type </param>
1735         /// <param name="includeSubtypes">do we include subtypes of the desired element type</param>
1736         /// <param name="resultNode">the result subtree</param>
1737         /// <param name="resultVar">the single Var produced by the result subtree</param>
1738         internal void BuildOfTypeTree(Node inputNode, Var inputVar, TypeUsage desiredType, bool includeSubtypes,
1739             out Node resultNode, out Var resultVar)
1740         {
1741             Op isOfOp = includeSubtypes ? this.CreateIsOfOp(desiredType) : this.CreateIsOfOnlyOp(desiredType);
1742             Node predicate = this.CreateNode(isOfOp, this.CreateNode(this.CreateVarRefOp(inputVar)));
1743             Node filterNode = this.CreateNode(this.CreateFilterOp(), inputNode, predicate);
1744
1745             resultNode = BuildFakeTreatProject(filterNode, inputVar, desiredType, out resultVar);
1746         }
1747
1748         /// Builds out a ProjectOp over the input that introduces a "Fake" TreatOp over the input Var to cast it to the desired type
1749         /// The "Fake" TreatOp is only there for "compile-time" typing reasons, and will be ignored in the rest of the plan compiler.
1750         /// </summary>
1751         /// <param name="inputNode">the input collection</param>
1752         /// <param name="inputVar">the single Var produced by the input collection</param>
1753         /// <param name="desiredType">the desired element type </param>
1754         /// <param name="resultVar">the single Var produced by the result subtree</param>
1755         /// <returns>the result subtree</returns>
1756         internal Node BuildFakeTreatProject(Node inputNode, Var inputVar, TypeUsage desiredType, out Var resultVar)
1757         {
1758             Node treatNode = this.CreateNode(this.CreateFakeTreatOp(desiredType), 
1759                 this.CreateNode(this.CreateVarRefOp(inputVar)));
1760             Node resultNode = this.BuildProject(inputNode, treatNode, out resultVar);
1761             return resultNode;
1762         }
1763
1764         /// <summary>
1765         /// Build a comparisonOp over the input arguments. Build SoftCasts over the inputs, if we need
1766         /// to.
1767         /// </summary>
1768         /// <param name="opType">the comparison optype</param>
1769         /// <param name="arg0">Arg 0</param>
1770         /// <param name="arg1">Arg 1</param>
1771         /// <returns>the resulting comparison tree</returns>
1772         internal Node BuildComparison(OpType opType, Node arg0, Node arg1)
1773         {
1774             if (!Command.EqualTypes(arg0.Op.Type, arg1.Op.Type))
1775             {
1776                 TypeUsage commonType = TypeHelpers.GetCommonTypeUsage(arg0.Op.Type, arg1.Op.Type);
1777                 Debug.Assert(commonType != null, "No common type for " + arg0.Op.Type + " and " + arg1.Op.Type);
1778                 if (!EqualTypes(commonType, arg0.Op.Type))
1779                 {
1780                     arg0 = this.CreateNode(this.CreateSoftCastOp(commonType), arg0);
1781                 }
1782                 if (!EqualTypes(commonType, arg1.Op.Type))
1783                 {
1784                     arg1 = this.CreateNode(this.CreateSoftCastOp(commonType), arg1);
1785                 }
1786             }
1787             Node newNode = this.CreateNode(this.CreateComparisonOp(opType), arg0, arg1);
1788             return newNode;
1789         }
1790
1791         /// <summary>
1792         /// Build up a CollectOp over a relop tree
1793         /// </summary>
1794         /// <param name="relOpNode">the relop tree</param>
1795         /// <param name="relOpVar">the single output var from the relop tree</param>
1796         /// <returns></returns>
1797         internal Node BuildCollect(Node relOpNode, Var relOpVar)
1798         {
1799             Node physicalProjectNode = this.CreateNode(this.CreatePhysicalProjectOp(relOpVar), relOpNode);
1800             TypeUsage collectOpType = TypeHelpers.CreateCollectionTypeUsage(relOpVar.Type);
1801             Node collectNode = this.CreateNode(this.CreateCollectOp(collectOpType), physicalProjectNode);
1802             return collectNode;
1803         }
1804         #endregion
1805
1806         #region Rel Properties
1807         /// <summary>
1808         /// Mark this rel-property as "referenced" in the current query, if the target
1809         /// end has multiplicity of one (or zero_or_one)
1810         /// </summary>
1811         /// <param name="relProperty">the rel-property</param>
1812         private void AddRelPropertyReference(RelProperty relProperty)
1813         {
1814             if (relProperty.ToEnd.RelationshipMultiplicity != RelationshipMultiplicity.Many &&
1815                 !m_referencedRelProperties.Contains(relProperty))
1816             {
1817                 m_referencedRelProperties.Add(relProperty);
1818             }
1819         }
1820
1821         /// <summary>
1822         /// The set of referenced rel properties in the current query
1823         /// </summary>
1824         internal HashSet<RelProperty> ReferencedRelProperties
1825         {
1826             get { return m_referencedRelProperties; }
1827         }
1828
1829         /// <summary>
1830         /// Is this rel-property referenced in the query so far
1831         /// </summary>
1832         /// <param name="relProperty">the rel-property</param>
1833         /// <returns>true, if the rel property was referenced in the query</returns>
1834         internal bool IsRelPropertyReferenced(RelProperty relProperty)
1835         {
1836             bool ret = m_referencedRelProperties.Contains(relProperty);
1837             return ret;
1838         }
1839         #endregion
1840
1841         #endregion
1842     }
1843
1844 }