File: SqlClient\Common\TypeSystemProvider.cs
Project: ndp\fx\src\DLinq\Dlinq\System.Data.Linq.csproj (System.Data.Linq)
using System;
using System.Collections.Generic;
using System.Text;
 
namespace System.Data.Linq.SqlClient {
 
    /// <summary>
    /// Abstracts the provider side type system. Encapsulates:
    /// - Mapping from runtime types to provider types.
    /// - Parsing type strings in the provider's language.
    /// - Handling application defined (opaque) types.
    /// - Type coercion precedence rules.
    /// - Type family organization.
    /// </summary>
    internal abstract class TypeSystemProvider {
 
        internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
 
        internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
 
        /// <summary>
        /// Return the provider type corresponding to the given clr type.
        /// </summary>
        internal abstract ProviderType From(Type runtimeType);
 
        /// <summary>
        /// Return the provider type corresponding to the given object instance.
        /// </summary>
        internal abstract ProviderType From(object o);
 
        /// <summary>
        /// Return the provider type corresponding to the given clr type and size.
        /// </summary>
        internal abstract ProviderType From(Type type, int? size);
 
        /// <summary>
        /// Return a type by parsing a string. The format of the string is
        /// provider specific.
        /// </summary>
        internal abstract ProviderType Parse(string text);
 
        /// <summary>
        /// Return a type understood only by the application.
        /// Each call with the same index will return the same ProviderType.
        /// </summary>
        internal abstract ProviderType GetApplicationType(int index);
 
        /// <summary>
        /// Returns the most precise type in the family of the type given.
        /// A family is a group types that serve similar functions. For example,
        /// in SQL SmallInt and Int are part of one family.
        /// </summary>
        internal abstract ProviderType MostPreciseTypeInFamily(ProviderType type);
 
        /// <summary>
        /// For LOB data types that have large type equivalents, this function returns the equivalent large
        /// data type.  If the type is not an LOB or cannot be converted, the function returns the current type.
        /// For example SqlServer defines the 'Image' LOB type, whose large type equivalent is VarBinary(MAX).
        /// </summary>
        internal abstract ProviderType GetBestLargeType(ProviderType type);
 
        /// <summary>
        /// Returns a type that can be used to hold values for both the current
        /// type and the specified type without data loss.
        /// </summary>
        internal abstract ProviderType GetBestType(ProviderType typeA, ProviderType typeB);
 
        internal abstract ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall);
 
        /// <summary>
        /// Get a type that can hold the same information but belongs to a different type family.
        /// For example, to represent a SQL NChar as an integer type, we need to use the type int.
        /// (SQL smallint would not be able to contain characters with unicode >32768)
        /// </summary>
        /// <param name="toType">Type of the target type family</param>
        /// <returns>Smallest type of target type family that can hold equivalent information</returns>
        internal abstract ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType typeWithFamily);
 
        internal abstract void InitializeParameter(ProviderType type, System.Data.Common.DbParameter parameter, object value);
    }
 
    /// <summary>
    /// Flags control the format of string returned by ToQueryString().
    /// </summary>
    [Flags]
    internal enum QueryFormatOptions {
        None = 0,
        SuppressSize = 1
    }
 
    /// <summary>
    /// An abstract type exposed by the TypeSystemProvider.
    /// </summary>
    internal abstract class ProviderType {
 
        /// <summary>
        /// True if this type is a Unicode type (eg, ntext, etc).
        /// </summary>
        internal abstract bool IsUnicodeType { get; }
 
        /// <summary>
        /// For a unicode type, return it's non-unicode equivalent.
        /// </summary>
        internal abstract ProviderType GetNonUnicodeEquivalent();
 
        /// <summary>
        /// True if this type has only a CLR representation and no provider representation.
        /// </summary>
        internal abstract bool IsRuntimeOnlyType { get; }
 
        /// <summary>
        /// True if this type is an application defined type.
        /// </summary>
        internal abstract bool IsApplicationType { get; }
 
        /// <summary>
        /// Determine whether this is the given application type.
        /// </summary>
        internal abstract bool IsApplicationTypeOf(int index);
 
        /// <summary>
        /// Returns the CLR type which most closely corresponds to this provider type.
        /// </summary>
        internal abstract Type GetClosestRuntimeType();
 
        /// <summary>
        /// Compare implicit type coercion precedence.
        /// -1 means there is an implicit conversion from this->type.
        /// 0 means there is a two way implicit conversion from this->type
        /// 1 means there is an implicit conversion from type->this.
        /// </summary>
        internal abstract int ComparePrecedenceTo(ProviderType type);
 
        /// <summary>
        /// Determines whether two types are in the same type family.
        /// A family is a group types that serve similar functions. For example,
        /// in SQL SmallInt and Int are part of one family.
        /// </summary>
        internal abstract bool IsSameTypeFamily(ProviderType type);
 
        /// <summary>
        /// Used to indicate if the type supports comparison in provider.
        /// </summary>
        /// <returns>Returns true if type supports comparison in provider.</returns>
        internal abstract bool SupportsComparison { get; }
 
        /// <summary>
        /// Used to indicate if the types supports Length function (LEN in T-SQL).  
        /// </summary>
        /// <returns>Returns true if type supports use of length function on the type.</returns>
        internal abstract bool SupportsLength { get; }
 
        /// <summary>
        /// Returns true if the given values will be equal to eachother for this type.
        /// </summary>
        internal abstract bool AreValuesEqual(object o1, object o2);
 
        /// <summary>
        /// Determines whether this type is a LOB (large object) type, or an equivalent type.
        /// For example, on SqlServer, Image and VarChar(MAX) among others are considered large types.
        /// </summary>
        /// <returns></returns>
        internal abstract bool IsLargeType { get; }
 
        /// <summary>
        /// Convert this type into a string that can be used in a query.
        /// </summary>
        internal abstract string ToQueryString();
 
        /// <summary>
        /// Convert this type into a string that can be used in a query.
        /// </summary>
        internal abstract string ToQueryString(QueryFormatOptions formatOptions);
 
        /// <summary>
        /// Whether this type is fixed size or not.
        /// </summary>
        internal abstract bool IsFixedSize { get; }
 
        /// <summary>
        /// The type has a size or is large.
        /// </summary>
        internal abstract bool HasSizeOrIsLarge { get; }
 
        /// <summary>
        /// The size of this type.
        /// </summary>
        internal abstract int? Size { get; }
 
        /// <summary>
        /// True if the type can be ordered.
        /// </summary>
        internal abstract bool IsOrderable { get; }
 
        /// <summary>
        /// True if the type can be grouped.
        /// </summary>
        internal abstract bool IsGroupable { get; }
 
        /// <summary>
        /// True if the type can appear in a column
        /// </summary>
        internal abstract bool CanBeColumn { get; }
 
        /// <summary>
        /// True if the type can appear as a parameter
        /// </summary>
        internal abstract bool CanBeParameter { get; }
 
        /// <summary>
        /// True if the type is a single character type.
        /// </summary>
        internal abstract bool IsChar { get; }
 
        /// <summary>
        /// True if the type is a multi-character type.
        /// </summary>
        internal abstract bool IsString { get; }
 
        /// <summary>
        /// True if the type is a number.
        /// </summary>
        internal abstract bool IsNumeric { get; }
 
        /// <summary>
        /// Returns true if the type uses precision and scale.  For example, returns true
        /// for SqlDBTypes Decimal, Float and Real.
        /// </summary>
        internal abstract bool HasPrecisionAndScale { get; }
 
        /// <summary>
        /// Determines if it is safe to suppress size specifications for
        /// the operand of a cast/convert.  For example, when casting to string,
        /// all these types have length less than the default sized used by SqlServer,
        /// so the length specification can be omitted without fear of truncation.
        /// </summary>
        internal abstract bool CanSuppressSizeForConversionToString{ get; }
 
        public static bool operator ==(ProviderType typeA, ProviderType typeB) {
            if ((object)typeA == (object)typeB)
                return true;
            if ((object)typeA != null)
                return typeA.Equals(typeB);
            return false;
        }
 
        public static bool operator != (ProviderType typeA, ProviderType typeB) {
            if ((object)typeA == (object)typeB)
                return false;
            if ((object)typeA != null)
                return !typeA.Equals(typeB);
            return true;
        }
 
        public override bool Equals(object obj) {
            return base.Equals(obj);
        }
 
        public override int GetHashCode() {
            return base.GetHashCode();
        }
    }
}