Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Mapping / ViewGeneration / CqlGeneration / SlotInfo.cs
1 //---------------------------------------------------------------------
2 // <copyright file="SlotInfo.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.Data.Common.CommandTrees;
11 using System.Data.Common.CommandTrees.ExpressionBuilder;
12 using System.Data.Common.Utils;
13 using System.Data.Mapping.ViewGeneration.Structures;
14 using System.Text;
15 using System.Diagnostics;
16
17 namespace System.Data.Mapping.ViewGeneration.CqlGeneration
18 {
19     /// <summary>
20     /// A class that keeps track of slot information in a <see cref="CqlBlock"/>.
21     /// </summary>
22     internal sealed class SlotInfo : InternalBase
23     {
24         #region Constructor
25         /// <summary>
26         /// Creates a <see cref="SlotInfo"/> for a <see cref="CqlBlock"/> X with information about whether this slot is needed by X's parent
27         /// (<paramref name="isRequiredByParent"/>), whether X projects it (<paramref name="isProjected"/>) along with the slot value (<paramref name="slotValue"/>) and 
28         /// the output member path (<paramref name="outputMember"/> (for regular/non-boolean slots) for the slot.
29         /// </summary>
30         internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember)
31             : this(isRequiredByParent, isProjected, slotValue, outputMember, false /* enforceNotNull */)
32         { }
33
34         /// <summary>
35         /// Creates a <see cref="SlotInfo"/> for a <see cref="CqlBlock"/> X with information about whether this slot is needed by X's parent
36         /// (<paramref name="isRequiredByParent"/>), whether X projects it (<paramref name="isProjected"/>) along with the slot value (<paramref name="slotValue"/>) and 
37         /// the output member path (<paramref name="outputMember"/> (for regular/non-boolean slots) for the slot.
38         /// </summary>
39         /// <param name="enforceNotNull">We need to ensure that _from variables are never null since view generation uses 2-valued boolean logic.
40         /// If <paramref name="enforceNotNull"/>=true, the generated Cql adds a condition (AND <paramref name="slotValue"/> NOT NULL).
41         /// This flag is used only for boolean slots.</param>
42         internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember, bool enforceNotNull)
43         {
44             m_isRequiredByParent = isRequiredByParent;
45             m_isProjected = isProjected;
46             m_slotValue = slotValue;
47             m_outputMember = outputMember;
48             m_enforceNotNull = enforceNotNull;
49             Debug.Assert(false == m_isRequiredByParent || m_slotValue != null, "Required slots cannot be null");
50             Debug.Assert(m_slotValue is QualifiedSlot ||
51                          (m_slotValue == null && m_outputMember == null) || // unused boolean slot
52                          (m_slotValue is BooleanProjectedSlot) == (m_outputMember == null),
53                          "If slot is boolean slot, there is no member path for it and vice-versa");
54         }
55         #endregion
56
57         #region Fields
58         /// <summary>
59         /// If slot is required by the parent. Can be reset to false in <see cref="ResetIsRequiredByParent"/> method.
60         /// </summary>
61         private bool m_isRequiredByParent;
62         /// <summary>
63         /// If the node is capable of projecting this slot.
64         /// </summary>
65         private readonly bool m_isProjected;
66         /// <summary>
67         /// The slot represented by this <see cref="SlotInfo"/>.
68         /// </summary>
69         private readonly ProjectedSlot m_slotValue;
70         /// <summary>
71         /// The output member path of this slot.
72         /// </summary>
73         private readonly MemberPath m_outputMember;
74         /// <summary>
75         /// Whether to add AND NOT NULL to Cql.
76         /// </summary>
77         private readonly bool m_enforceNotNull;
78         #endregion
79
80         #region Properties
81         /// <summary>
82         /// Returns true iff this slot is required by the <see cref="CqlBlock"/>'s parent.
83         /// Can be reset to false by calling <see cref="ResetIsRequiredByParent"/> method.
84         /// </summary>
85         internal bool IsRequiredByParent
86         {
87             get { return m_isRequiredByParent; }
88         }
89
90         /// <summary>
91         /// Returns true iff this slot is projected by this <see cref="CqlBlock"/>.
92         /// </summary>
93         internal bool IsProjected
94         {
95             get { return m_isProjected; }
96         }
97
98         /// <summary>
99         /// Returns the output memberpath of this slot
100         /// </summary>
101         internal MemberPath OutputMember
102         {
103             get { return m_outputMember; }
104         }
105
106         /// <summary>
107         /// Returns the slot value corresponfing to this object.
108         /// </summary>
109         internal ProjectedSlot SlotValue
110         {
111             get { return m_slotValue; }
112         }
113
114         /// <summary>
115         /// Returns the Cql alias for this slot, e.g., "CPerson1_Pid", "_from0", etc
116         /// </summary>
117         internal string CqlFieldAlias
118         {
119             get
120             {
121                 return m_slotValue != null ? m_slotValue.GetCqlFieldAlias(m_outputMember) : null;
122             }
123         }
124
125         /// <summary>
126         /// Returns true if Cql generated for the slot needs to have an extra AND IS NOT NULL condition.
127         /// </summary>
128         internal bool IsEnforcedNotNull
129         {
130             get { return m_enforceNotNull; }
131         }
132         #endregion
133
134         #region Methods
135         /// <summary>
136         /// Sets the <see cref="IsRequiredByParent"/> to false.
137         /// Note we don't have a setter because we don't want people to set this field to true after the object has been created.
138         /// </summary>
139         internal void ResetIsRequiredByParent()
140         {
141             m_isRequiredByParent = false;
142         }
143
144         /// <summary>
145         /// Generates eSQL representation of the slot. For different slots, the result is different, e.g., "_from0", "CPerson1.pid", "TREAT(....)".
146         /// </summary>
147         internal StringBuilder AsEsql(StringBuilder builder, string blockAlias, int indentLevel)
148         {
149             if (m_enforceNotNull)
150             {
151                 builder.Append('(');
152                 m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel);
153                 builder.Append(" AND ");
154                 m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel);
155                 builder.Append(" IS NOT NULL)");
156             }
157             else
158             {
159                 m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel);
160             }
161             return builder;
162         }
163
164         /// <summary>
165         /// Generates CQT representation of the slot.
166         /// </summary>
167         internal DbExpression AsCqt(DbExpression row)
168         {
169             DbExpression cqt = m_slotValue.AsCqt(row, m_outputMember);
170             if (m_enforceNotNull)
171             {
172                 cqt = cqt.And(cqt.IsNull().Not());
173             }
174             return cqt;
175         }
176
177         internal override void ToCompactString(StringBuilder builder)
178         {
179             if (m_slotValue != null)
180             {
181                 builder.Append(CqlFieldAlias);
182             }
183         }
184         #endregion
185     }
186 }