1 //---------------------------------------------------------------------
2 // <copyright file="Constant.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 namespace System
.Data
.Mapping
.ViewGeneration
.Structures
12 using System
.Collections
.Generic
;
13 using System
.Data
.Common
.CommandTrees
;
14 using System
.Data
.Common
.CommandTrees
.ExpressionBuilder
;
15 using System
.Data
.Common
.Utils
;
16 using System
.Data
.Mapping
.ViewGeneration
.CqlGeneration
;
17 using System
.Data
.Metadata
.Edm
;
18 using System
.Diagnostics
;
22 /// This class denotes a constant that can be stored in multiconstants or projected in fields.
24 internal abstract class Constant
: InternalBase
27 internal static readonly IEqualityComparer
<Constant
> EqualityComparer
= new CellConstantComparer();
28 internal static readonly Constant Null
= NullConstant
.Instance
;
29 internal static readonly Constant NotNull
= new NegatedConstant( new Constant
[] { NullConstant.Instance }
);
30 internal static readonly Constant Undefined
= UndefinedConstant
.Instance
;
32 /// Represents scalar constants within a finite set that are not specified explicitly in the domain.
33 /// Currently only used as a Sentinel node to prevent expression optimization
35 internal static readonly Constant AllOtherConstants
= AllOtherConstantsConstant
.Instance
;
39 internal abstract bool IsNull();
41 internal abstract bool IsNotNull();
43 internal abstract bool IsUndefined();
46 /// Returns true if this constant contains not null.
47 /// Implemented in <see cref="NegatedConstant"/> class, all other implementations return false.
49 internal abstract bool HasNotNull();
52 /// Generates eSQL for the constant expression.
54 /// <param name="outputMember">The member to which this constant is directed</param>
55 internal abstract StringBuilder
AsEsql(StringBuilder builder
, MemberPath outputMember
, string blockAlias
);
58 /// Generates CQT for the constant expression.
60 /// <param name="row">The input row.</param>
61 /// <param name="outputMember">The member to which this constant is directed</param>
62 internal abstract DbExpression
AsCqt(DbExpression row
, MemberPath outputMember
);
64 public override bool Equals(object obj
)
66 Constant cellConst
= obj
as Constant
;
67 if (cellConst
== null)
73 return IsEqualTo(cellConst
);
77 public override int GetHashCode()
79 return base.GetHashCode();
82 protected abstract bool IsEqualTo(Constant right
);
84 internal abstract string ToUserString();
86 [System
.Diagnostics
.CodeAnalysis
.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
87 internal static void ConstantsToUserString(StringBuilder builder
, Set
<Constant
> constants
)
90 foreach (Constant constant
in constants
)
94 builder
.Append(System
.Data
.Entity
.Strings
.ViewGen_CommaBlank
);
97 string constrStr
= constant
.ToUserString();
98 builder
.Append(constrStr
);
103 #region Comparer class
104 private class CellConstantComparer
: IEqualityComparer
<Constant
>
106 public bool Equals(Constant left
, Constant right
)
108 // Quick check with references
109 if (object.ReferenceEquals(left
, right
))
111 // Gets the Null and Undefined case as well
114 // One of them is non-null at least. So if the other one is
115 // null, we cannot be equal
116 if (left
== null || right
== null)
120 // Both are non-null at this point
121 return left
.IsEqualTo(right
);
124 public int GetHashCode(Constant key
)
126 EntityUtil
.CheckArgumentNull(key
, "key");
127 return key
.GetHashCode();
132 #region Special constant classes (NullConstant, UndefinedConstant, AllOtherConstants)
133 private sealed class NullConstant
: Constant
135 internal static readonly Constant Instance
= new NullConstant();
137 private NullConstant() { }
140 internal override bool IsNull()
145 internal override bool IsNotNull()
150 internal override bool IsUndefined()
155 internal override bool HasNotNull()
160 internal override StringBuilder
AsEsql(StringBuilder builder
, MemberPath outputMember
, string blockAlias
)
162 Debug
.Assert(outputMember
.LeafEdmMember
!= null, "Constant can't correspond to an empty member path.");
163 EdmType constType
= Helper
.GetModelTypeUsage(outputMember
.LeafEdmMember
).EdmType
;
165 builder
.Append("CAST(NULL AS ");
166 CqlWriter
.AppendEscapedTypeName(builder
, constType
);
171 internal override DbExpression
AsCqt(DbExpression row
, MemberPath outputMember
)
173 Debug
.Assert(outputMember
.LeafEdmMember
!= null, "Constant can't correspond to an empty path.");
174 EdmType constType
= Helper
.GetModelTypeUsage(outputMember
.LeafEdmMember
).EdmType
;
176 return TypeUsage
.Create(constType
).Null();
179 public override int GetHashCode()
184 protected override bool IsEqualTo(Constant right
)
186 Debug
.Assert(Object
.ReferenceEquals(this, Instance
), "this must be == Instance for NullConstant");
187 return Object
.ReferenceEquals(this, right
);
190 internal override string ToUserString()
192 return System
.Data
.Entity
.Strings
.ViewGen_Null
;
195 internal override void ToCompactString(StringBuilder builder
)
197 builder
.Append("NULL");
201 private sealed class UndefinedConstant
: Constant
203 internal static readonly Constant Instance
= new UndefinedConstant();
205 private UndefinedConstant() { }
208 internal override bool IsNull()
213 internal override bool IsNotNull()
218 internal override bool IsUndefined()
223 internal override bool HasNotNull()
229 /// Not supported in this class.
231 internal override StringBuilder
AsEsql(StringBuilder builder
, MemberPath outputMember
, string blockAlias
)
233 Debug
.Fail("Should not be called.");
234 return null; // To keep the compiler happy
238 /// Not supported in this class.
240 internal override DbExpression
AsCqt(DbExpression row
, MemberPath outputMember
)
242 Debug
.Fail("Should not be called.");
243 return null; // To keep the compiler happy
246 public override int GetHashCode()
251 protected override bool IsEqualTo(Constant right
)
253 Debug
.Assert(Object
.ReferenceEquals(this, Instance
), "this must be == Instance for NullConstant");
254 return Object
.ReferenceEquals(this, right
);
258 /// Not supported in this class.
260 internal override string ToUserString()
262 Debug
.Fail("We should not emit a message about Undefined constants to the user.");
266 internal override void ToCompactString(StringBuilder builder
)
272 private sealed class AllOtherConstantsConstant
: Constant
274 internal static readonly Constant Instance
= new AllOtherConstantsConstant();
276 private AllOtherConstantsConstant() { }
279 internal override bool IsNull()
284 internal override bool IsNotNull()
289 internal override bool IsUndefined()
294 internal override bool HasNotNull()
300 /// Not supported in this class.
302 internal override StringBuilder
AsEsql(StringBuilder builder
, MemberPath outputMember
, string blockAlias
)
304 Debug
.Fail("Should not be called.");
305 return null; // To keep the compiler happy
309 /// Not supported in this class.
311 internal override DbExpression
AsCqt(DbExpression row
, MemberPath outputMember
)
313 Debug
.Fail("Should not be called.");
314 return null; // To keep the compiler happy
317 public override int GetHashCode()
322 protected override bool IsEqualTo(Constant right
)
324 Debug
.Assert(Object
.ReferenceEquals(this, Instance
), "this must be == Instance for NullConstant");
325 return Object
.ReferenceEquals(this, right
);
329 /// Not supported in this class.
331 internal override string ToUserString()
333 Debug
.Fail("We should not emit a message about Undefined constants to the user.");
337 internal override void ToCompactString(StringBuilder builder
)
339 builder
.Append("AllOtherConstants");