Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Query / InternalTrees / Nodes.cs
1 //---------------------------------------------------------------------
2 // <copyright file="Nodes.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;
11 using System.Collections.Generic;
12 using System.Data.Metadata.Edm;
13 using System.Globalization;
14 using System.Diagnostics;
15
16 namespace System.Data.Query.InternalTrees
17 {
18     /// <summary>
19     /// A Node describes a node in a query tree. Each node has an operator, and
20     /// a list of zero or more children of that operator.
21     /// </summary>
22     internal class Node
23     {
24         #region private state
25         private int m_id;
26         private List<Node> m_children;
27         private Op m_op;
28         private NodeInfo m_nodeInfo;
29         #endregion
30
31         #region constructors
32         /// <summary>
33         /// Basic constructor. 
34         /// 
35         /// NEVER call this routine directly - you should always use the Command.CreateNode
36         /// factory methods.
37         /// </summary>
38         /// <param name="nodeId">id for the node</param>
39         /// <param name="op">The operator</param>
40         /// <param name="children">List of child nodes</param>
41         internal Node(int nodeId, Op op, List<Node> children)
42         {
43             m_id = nodeId;
44             m_op = op;
45             m_children = children;
46         }
47
48         /// <summary>
49         /// This routine is only used for building up rule patterns. 
50         /// NEVER use this routine for building up nodes in a user command tree.
51         /// </summary>
52         /// <param name="op"></param>
53         /// <param name="children"></param>
54         internal Node(Op op, params Node[] children)
55             : this(-1, op, new List<Node>(children))
56         {
57         }
58         #endregion
59
60         #region public properties and methods
61
62 #if DEBUG
63         internal int Id { get { return m_id; } }
64 #endif
65
66         /// <summary>
67         /// Get the list of children
68         /// </summary>
69         internal List<Node> Children { get { return m_children; } }
70
71         /// <summary>
72         /// Gets or sets the node's operator
73         /// </summary>
74         internal Op Op { get { return m_op; } set { m_op = value; } }
75
76         /// <summary>
77         /// Simpler (?) getter/setter routines
78         /// </summary>
79         internal Node Child0 { get { return m_children[0]; } set { m_children[0] = value; } }
80         /// <summary>
81         /// Do I have a zeroth child?
82         /// </summary>
83         internal bool HasChild0 { get { return m_children.Count > 0; } }
84
85         /// <summary>
86         /// Get/set first child
87         /// </summary>
88         internal Node Child1 { get { return m_children[1]; } set { m_children[1] = value; } }
89         /// <summary>
90         /// Do I have a child1?
91         /// </summary>
92         internal bool HasChild1 { get { return m_children.Count > 1; } }
93
94         /// <summary>
95         /// get/set second child
96         /// </summary>
97         internal Node Child2 { get { return m_children[2]; } set { m_children[2] = value; } }
98         /// <summary>
99         /// get/set second child
100         /// </summary>
101         internal Node Child3 { get { return m_children[3]; } /* commented out because of fxcop - there are no upstream callers -- set { m_children[3] = value; }*/ }
102         /// <summary>
103         /// Do I have a child2 (third child really)
104         /// </summary>
105         internal bool HasChild2 { get { return m_children.Count > 2; } }
106         /// <summary>
107         /// Do I have a child3 (fourth child really)
108         /// </summary>
109         internal bool HasChild3 { get { return m_children.Count > 3; } }
110
111         #region equivalence functions
112         /// <summary>
113         /// Is this subtree equivalent to another subtree
114         /// </summary>
115         /// <param name="other"></param>
116         /// <returns></returns>
117         internal bool IsEquivalent(Node other)
118         {
119             if (this.Children.Count != other.Children.Count)
120             {
121                 return false;
122             }
123             bool? opEquivalent = this.Op.IsEquivalent(other.Op);
124             if (opEquivalent != true)
125             {
126                 return false;
127             }
128             for (int i = 0; i < this.Children.Count; i++)
129             {
130                 if (!this.Children[i].IsEquivalent(other.Children[i]))
131                 {
132                     return false;
133                 }
134             }
135             return true;
136         }
137         #endregion
138
139         #region NodeInfo methods and properties
140         /// <summary>
141         /// Has the node info been initialized, i.e. previously computed
142         /// </summary>
143         internal bool IsNodeInfoInitialized { get { return (m_nodeInfo != null);  } }
144
145         /// <summary>
146         /// Get the nodeInfo for a node. Initializes it, if it has not yet been initialized
147         /// </summary>
148         /// <param name="command">Current command object</param>
149         /// <returns>NodeInfo for this node</returns>
150         internal NodeInfo GetNodeInfo(Command command)
151         {
152             if (m_nodeInfo == null)
153             {
154                 InitializeNodeInfo(command);
155             }
156             return m_nodeInfo;
157         }
158         /// <summary>
159         /// Gets the "extended" nodeinfo for a node; if it has not yet been initialized, then it will be
160         /// </summary>
161         /// <param name="command">current command object</param>
162         /// <returns>extended nodeinfo for this node</returns>
163         internal ExtendedNodeInfo GetExtendedNodeInfo(Command command)
164         {
165             if (m_nodeInfo == null)
166             {
167                 InitializeNodeInfo(command);
168             }
169             ExtendedNodeInfo extendedNodeInfo = m_nodeInfo as ExtendedNodeInfo;
170             Debug.Assert(extendedNodeInfo != null);
171             return extendedNodeInfo;
172         }
173
174         private void InitializeNodeInfo(Command command)
175         {
176             if (this.Op.IsRelOp || this.Op.IsPhysicalOp)
177             {
178                 m_nodeInfo = new ExtendedNodeInfo(command);
179             }
180             else
181             {
182                 m_nodeInfo = new NodeInfo(command);
183             }
184             command.RecomputeNodeInfo(this);
185         }
186         #endregion
187
188         #endregion
189     }
190 }