1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 
5 namespace System.Data.Linq.SqlClient {
6 
7     /// <summary>
8     /// Abstracts the provider side type system. Encapsulates:
9     /// - Mapping from runtime types to provider types.
10     /// - Parsing type strings in the provider's language.
11     /// - Handling application defined (opaque) types.
12     /// - Type coercion precedence rules.
13     /// - Type family organization.
14     /// </summary>
15     internal abstract class TypeSystemProvider {
16 
PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType)17         internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
18 
PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType)19         internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
20 
21         /// <summary>
22         /// Return the provider type corresponding to the given clr type.
23         /// </summary>
From(Type runtimeType)24         internal abstract ProviderType From(Type runtimeType);
25 
26         /// <summary>
27         /// Return the provider type corresponding to the given object instance.
28         /// </summary>
From(object o)29         internal abstract ProviderType From(object o);
30 
31         /// <summary>
32         /// Return the provider type corresponding to the given clr type and size.
33         /// </summary>
From(Type type, int? size)34         internal abstract ProviderType From(Type type, int? size);
35 
36         /// <summary>
37         /// Return a type by parsing a string. The format of the string is
38         /// provider specific.
39         /// </summary>
Parse(string text)40         internal abstract ProviderType Parse(string text);
41 
42         /// <summary>
43         /// Return a type understood only by the application.
44         /// Each call with the same index will return the same ProviderType.
45         /// </summary>
GetApplicationType(int index)46         internal abstract ProviderType GetApplicationType(int index);
47 
48         /// <summary>
49         /// Returns the most precise type in the family of the type given.
50         /// A family is a group types that serve similar functions. For example,
51         /// in SQL SmallInt and Int are part of one family.
52         /// </summary>
MostPreciseTypeInFamily(ProviderType type)53         internal abstract ProviderType MostPreciseTypeInFamily(ProviderType type);
54 
55         /// <summary>
56         /// For LOB data types that have large type equivalents, this function returns the equivalent large
57         /// data type.  If the type is not an LOB or cannot be converted, the function returns the current type.
58         /// For example SqlServer defines the 'Image' LOB type, whose large type equivalent is VarBinary(MAX).
59         /// </summary>
GetBestLargeType(ProviderType type)60         internal abstract ProviderType GetBestLargeType(ProviderType type);
61 
62         /// <summary>
63         /// Returns a type that can be used to hold values for both the current
64         /// type and the specified type without data loss.
65         /// </summary>
GetBestType(ProviderType typeA, ProviderType typeB)66         internal abstract ProviderType GetBestType(ProviderType typeA, ProviderType typeB);
67 
ReturnTypeOfFunction(SqlFunctionCall functionCall)68         internal abstract ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall);
69 
70         /// <summary>
71         /// Get a type that can hold the same information but belongs to a different type family.
72         /// For example, to represent a SQL NChar as an integer type, we need to use the type int.
73         /// (SQL smallint would not be able to contain characters with unicode >32768)
74         /// </summary>
75         /// <param name="toType">Type of the target type family</param>
76         /// <returns>Smallest type of target type family that can hold equivalent information</returns>
ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily)77         internal abstract ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily);
78 
InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value)79         internal abstract void InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value);
80     }
81 
82     /// <summary>
83     /// Flags control the format of string returned by ToQueryString().
84     /// </summary>
85     [Flags]
86     internal enum QueryFormatOptions {
87         None = 0,
88         SuppressSize = 1
89     }
90 
91     /// <summary>
92     /// An abstract type exposed by the TypeSystemProvider.
93     /// </summary>
94     internal abstract class ProviderType {
95 
96         /// <summary>
97         /// True if this type is a Unicode type (eg, ntext, etc).
98         /// </summary>
99         internal abstract bool IsUnicodeType { get; }
100 
101         /// <summary>
102         /// For a unicode type, return it's non-unicode equivalent.
103         /// </summary>
GetNonUnicodeEquivalent()104         internal abstract ProviderType GetNonUnicodeEquivalent();
105 
106         /// <summary>
107         /// True if this type has only a CLR representation and no provider representation.
108         /// </summary>
109         internal abstract bool IsRuntimeOnlyType { get; }
110 
111         /// <summary>
112         /// True if this type is an application defined type.
113         /// </summary>
114         internal abstract bool IsApplicationType { get; }
115 
116         /// <summary>
117         /// Determine whether this is the given application type.
118         /// </summary>
IsApplicationTypeOf(int index)119         internal abstract bool IsApplicationTypeOf(int index);
120 
121         /// <summary>
122         /// Returns the CLR type which most closely corresponds to this provider type.
123         /// </summary>
GetClosestRuntimeType()124         internal abstract Type GetClosestRuntimeType();
125 
126         /// <summary>
127         /// Compare implicit type coercion precedence.
128         /// -1 means there is an implicit conversion from this->type.
129         /// 0 means there is a two way implicit conversion from this->type
130         /// 1 means there is an implicit conversion from type->this.
131         /// </summary>
ComparePrecedenceTo(ProviderType type)132         internal abstract int ComparePrecedenceTo(ProviderType type);
133 
134         /// <summary>
135         /// Determines whether two types are in the same type family.
136         /// A family is a group types that serve similar functions. For example,
137         /// in SQL SmallInt and Int are part of one family.
138         /// </summary>
IsSameTypeFamily(ProviderType type)139         internal abstract bool IsSameTypeFamily(ProviderType type);
140 
141         /// <summary>
142         /// Used to indicate if the type supports comparison in provider.
143         /// </summary>
144         /// <returns>Returns true if type supports comparison in provider.</returns>
145         internal abstract bool SupportsComparison { get; }
146 
147         /// <summary>
148         /// Used to indicate if the types supports Length function (LEN in T-SQL).
149         /// </summary>
150         /// <returns>Returns true if type supports use of length function on the type.</returns>
151         internal abstract bool SupportsLength { get; }
152 
153         /// <summary>
154         /// Returns true if the given values will be equal to eachother for this type.
155         /// </summary>
AreValuesEqual(object o1, object o2)156         internal abstract bool AreValuesEqual(object o1, object o2);
157 
158         /// <summary>
159         /// Determines whether this type is a LOB (large object) type, or an equivalent type.
160         /// For example, on SqlServer, Image and VarChar(MAX) among others are considered large types.
161         /// </summary>
162         /// <returns></returns>
163         internal abstract bool IsLargeType { get; }
164 
165         /// <summary>
166         /// Convert this type into a string that can be used in a query.
167         /// </summary>
ToQueryString()168         internal abstract string ToQueryString();
169 
170         /// <summary>
171         /// Convert this type into a string that can be used in a query.
172         /// </summary>
ToQueryString(QueryFormatOptions formatOptions)173         internal abstract string ToQueryString(QueryFormatOptions formatOptions);
174 
175         /// <summary>
176         /// Whether this type is fixed size or not.
177         /// </summary>
178         internal abstract bool IsFixedSize { get; }
179 
180         /// <summary>
181         /// The type has a size or is large.
182         /// </summary>
183         internal abstract bool HasSizeOrIsLarge { get; }
184 
185         /// <summary>
186         /// The size of this type.
187         /// </summary>
188         internal abstract int? Size { get; }
189 
190         /// <summary>
191         /// True if the type can be ordered.
192         /// </summary>
193         internal abstract bool IsOrderable { get; }
194 
195         /// <summary>
196         /// True if the type can be grouped.
197         /// </summary>
198         internal abstract bool IsGroupable { get; }
199 
200         /// <summary>
201         /// True if the type can appear in a column
202         /// </summary>
203         internal abstract bool CanBeColumn { get; }
204 
205         /// <summary>
206         /// True if the type can appear as a parameter
207         /// </summary>
208         internal abstract bool CanBeParameter { get; }
209 
210         /// <summary>
211         /// True if the type is a single character type.
212         /// </summary>
213         internal abstract bool IsChar { get; }
214 
215         /// <summary>
216         /// True if the type is a multi-character type.
217         /// </summary>
218         internal abstract bool IsString { get; }
219 
220         /// <summary>
221         /// True if the type is a number.
222         /// </summary>
223         internal abstract bool IsNumeric { get; }
224 
225         /// <summary>
226         /// Returns true if the type uses precision and scale.  For example, returns true
227         /// for SqlDBTypes Decimal, Float and Real.
228         /// </summary>
229         internal abstract bool HasPrecisionAndScale { get; }
230 
231         /// <summary>
232         /// Determines if it is safe to suppress size specifications for
233         /// the operand of a cast/convert.  For example, when casting to string,
234         /// all these types have length less than the default sized used by SqlServer,
235         /// so the length specification can be omitted without fear of truncation.
236         /// </summary>
237         internal abstract bool CanSuppressSizeForConversionToString{ get; }
238 
operator ==(ProviderType typeA, ProviderType typeB)239         public static bool operator ==(ProviderType typeA, ProviderType typeB) {
240             if ((object)typeA == (object)typeB)
241                 return true;
242             if ((object)typeA != null)
243                 return typeA.Equals(typeB);
244             return false;
245         }
246 
operator !=(ProviderType typeA, ProviderType typeB)247         public static bool operator != (ProviderType typeA, ProviderType typeB) {
248             if ((object)typeA == (object)typeB)
249                 return false;
250             if ((object)typeA != null)
251                 return !typeA.Equals(typeB);
252             return true;
253         }
254 
Equals(object obj)255         public override bool Equals(object obj) {
256             return base.Equals(obj);
257         }
258 
GetHashCode()259         public override int GetHashCode() {
260             return base.GetHashCode();
261         }
262     }
263 }
264