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