Пример #1
0
        internal override ProviderType MostPreciseTypeInFamily(ProviderType type)
        {
            SqlType sqlType = (SqlType)type;

            switch (sqlType.SqlDbType)
            {
            case SqlDbType.TinyInt:
            case SqlDbType.SmallInt:
            case SqlDbType.Int:
                return(From(typeof(int)));

            case SqlDbType.SmallMoney:
            case SqlDbType.Money:
                return(SqlTypeSystem.Create(SqlDbType.Money));

            case SqlDbType.Real:
            case SqlDbType.Float:
                return(From(typeof(double)));

            case SqlDbType.Date:
            case SqlDbType.Time:
            case SqlDbType.SmallDateTime:
            case SqlDbType.DateTime:
            case SqlDbType.DateTime2:
                return(From(typeof(DateTime)));

            case SqlDbType.DateTimeOffset:
                return(From(typeof(DateTimeOffset)));

            default:
                return(type);
            }
        }
Пример #2
0
 internal override Type GetClosestRuntimeType()
 {
     if (this.RuntimeOnlyType != null)
     {
         return(this.RuntimeOnlyType);
     }
     return(SqlTypeSystem.GetClosestRuntimeType(this.sqlDbType));
 }
Пример #3
0
        internal override ProviderType From(Type type, int?size)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                type = type.GetGenericArguments()[0];
            }

            // Retain mappings for DateTime and TimeSpan; add one for the new DateTimeOffset type.
            //
            if (System.Type.GetTypeCode(type) == TypeCode.Object &&
                type == typeof(DateTimeOffset))
            {
                return(SqlTypeSystem.Create(SqlDbType.DateTimeOffset));
            }

            return(base.From(type, size));
        }
Пример #4
0
        internal override ProviderType GetBestLargeType(ProviderType type)
        {
            SqlType sqlType = (SqlType)type;

            switch (sqlType.SqlDbType)
            {
            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
                return(SqlTypeSystem.Create(SqlDbType.NText));

            case SqlDbType.Char:
            case SqlDbType.VarChar:
                return(SqlTypeSystem.Create(SqlDbType.Text));

            case SqlDbType.Binary:
            case SqlDbType.VarBinary:
                return(SqlTypeSystem.Create(SqlDbType.Image));
            }
            return(type);
        }
Пример #5
0
        internal override ProviderType GetBestLargeType(ProviderType type)
        {
            SqlType sqlType = (SqlType)type;

            switch (sqlType.SqlDbType)
            {
            case SqlDbType.NText:
            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
                return(SqlTypeSystem.Create(SqlDbType.NVarChar, ProviderConstants.LargeTypeSizeIndicator));

            case SqlDbType.Text:
            case SqlDbType.Char:
            case SqlDbType.VarChar:
                return(SqlTypeSystem.Create(SqlDbType.VarChar, ProviderConstants.LargeTypeSizeIndicator));

            case SqlDbType.Image:
            case SqlDbType.Binary:
            case SqlDbType.VarBinary:
                return(SqlTypeSystem.Create(SqlDbType.VarBinary, ProviderConstants.LargeTypeSizeIndicator));
            }
            return(type);
        }
Пример #6
0
        /// <summary>
        /// For types with size, determine the closest matching type for the information
        /// specified, promoting to the appropriate large type as needed.  If no size is
        /// specified, we use the max.
        /// </summary>
        protected ProviderType GetBestType(SqlDbType targetType, int?size)
        {
            // determine max size for the specified db type
            int maxSize = 0;

            switch (targetType)
            {
            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
                maxSize = 4000;
                break;

            case SqlDbType.Char:
            case SqlDbType.VarChar:
            case SqlDbType.Binary:
            case SqlDbType.VarBinary:
                maxSize = 8000;
                break;
            }
            ;

            if (size.HasValue)
            {
                if (size.Value <= maxSize)
                {
                    return(SqlTypeSystem.Create(targetType, size.Value));
                }
                else
                {
                    return(GetBestLargeType(SqlTypeSystem.Create(targetType)));
                }
            }

            // if the type provider supports MAX types, return one, otherwise use
            // the maximum size determined above
            return(SqlTypeSystem.Create(targetType, SupportsMaxSize ? ProviderConstants.LargeTypeSizeIndicator : maxSize));
        }
Пример #7
0
        internal override ProviderType ChangeTypeFamilyTo(ProviderType type, ProviderType toType)
        {
            // if this is already the same family, do nothing
            if (type.IsSameTypeFamily(toType))
            {
                return(type);
            }

            // otherwise as a default return toType
            // but look for special cases we have to convert carefully
            if (type.IsApplicationType || toType.IsApplicationType)
            {
                return(toType);
            }
            SqlType sqlToType   = (SqlType)toType;
            SqlType sqlThisType = (SqlType)type;

            if (sqlToType.Category == TypeCategory.Numeric && sqlThisType.Category == TypeCategory.Char)
            {
                switch (sqlThisType.SqlDbType)
                {
                case SqlDbType.NChar:
                    return(SqlTypeSystem.Create(SqlDbType.Int));

                case SqlDbType.Char:
                    return(SqlTypeSystem.Create(SqlDbType.SmallInt));

                default:
                    return(toType);
                }
            }
            else
            {
                return(toType);
            }
        }
Пример #8
0
        internal override ProviderType From(Type type, int?size)
        {
            if (type.IsGenericType)
            {
                if (type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    type = type.GetGenericArguments()[0];
                }
                if (type.GetGenericTypeDefinition() == typeof(DbId <,>))
                {
                    type = type.GenericTypeArguments[1];// return From(typeof(int), size);
                }
            }
            TypeCode tc = System.Type.GetTypeCode(type);

            switch (tc)
            {
            case TypeCode.Boolean:
                return(SqlTypeSystem.Create(SqlDbType.Bit));

            case TypeCode.Byte:
                return(SqlTypeSystem.Create(SqlDbType.TinyInt));

            case TypeCode.SByte:
            case TypeCode.Int16:
                return(SqlTypeSystem.Create(SqlDbType.SmallInt));

            case TypeCode.Int32:
            case TypeCode.UInt16:
                return(SqlTypeSystem.Create(SqlDbType.Int));

            case TypeCode.Int64:
            case TypeCode.UInt32:
                return(SqlTypeSystem.Create(SqlDbType.BigInt));

            case TypeCode.UInt64:
                return(SqlTypeSystem.Create(SqlDbType.Decimal, 20, 0));

            case TypeCode.Decimal:
                return(SqlTypeSystem.Create(SqlDbType.Decimal, 29, size ?? 4));

            case TypeCode.Double:
                return(SqlTypeSystem.Create(SqlDbType.Float));

            case TypeCode.Single:
                return(SqlTypeSystem.Create(SqlDbType.Real));

            case TypeCode.Char:
                return(SqlTypeSystem.Create(SqlDbType.NChar, 1));

            case TypeCode.String:
                return(GetBestType(SqlDbType.NVarChar, size));

            case TypeCode.DateTime:
                return(SqlTypeSystem.Create(SqlDbType.DateTime));

            case TypeCode.Object:
            {
                if (type == typeof(Guid))
                {
                    return(SqlTypeSystem.Create(SqlDbType.UniqueIdentifier));
                }
                if (type == typeof(byte[]) || type == typeof(Binary))
                {
                    return(GetBestType(SqlDbType.VarBinary, size));
                }
                if (type == typeof(char[]))
                {
                    return(GetBestType(SqlDbType.NVarChar, size));
                }
                if (type == typeof(TimeSpan))
                {
                    return(SqlTypeSystem.Create(SqlDbType.BigInt));
                }
                if (type == typeof(System.Xml.Linq.XDocument) ||
                    type == typeof(System.Xml.Linq.XElement))
                {
                    return(ProviderConstants.XmlType);
                }
                // else UDT?
                return(new SqlType(type));
            }

            default:
                throw Error.UnexpectedTypeCode(tc);
            }
        }
Пример #9
0
        internal override ProviderType GetBestType(ProviderType typeA, ProviderType typeB)
        {
            // first determine the type precedence
            SqlType bestType = (SqlType)(typeA.ComparePrecedenceTo(typeB) > 0 ? typeA : typeB);

            // if one of the types is a not a server type, return
            // that type
            if (typeA.IsApplicationType || typeA.IsRuntimeOnlyType)
            {
                return(typeA);
            }
            if (typeB.IsApplicationType || typeB.IsRuntimeOnlyType)
            {
                return(typeB);
            }

            SqlType sqlTypeA = (SqlType)typeA;
            SqlType sqlTypeB = (SqlType)typeB;

            if (sqlTypeA.HasPrecisionAndScale && sqlTypeB.HasPrecisionAndScale && bestType.SqlDbType == SqlDbType.Decimal)
            {
                int p0 = sqlTypeA.Precision;
                int s0 = sqlTypeA.Scale;
                int p1 = sqlTypeB.Precision;
                int s1 = sqlTypeB.Scale;
                // precision and scale may be zero if this is an unsized type.
                if (p0 == 0 && s0 == 0 && p1 == 0 && s1 == 0)
                {
                    return(SqlTypeSystem.Create(bestType.SqlDbType));
                }
                else if (p0 == 0 && s0 == 0)
                {
                    return(SqlTypeSystem.Create(bestType.SqlDbType, p1, s1));
                }
                else if (p1 == 0 && s1 == 0)
                {
                    return(SqlTypeSystem.Create(bestType.SqlDbType, p0, s0));
                }
                // determine best scale/precision
                int bestLeft  = Math.Max(p0 - s0, p1 - s1);
                int bestRight = Math.Max(s0, s1);
                int precision = Math.Min(bestLeft + bestRight, 38);
                return(SqlTypeSystem.Create(bestType.SqlDbType, precision, /*scale*/ bestRight));
            }
            else
            {
                // determine the best size
                int?bestSize = null;

                if (sqlTypeA.Size.HasValue && sqlTypeB.Size.HasValue)
                {
                    bestSize = (sqlTypeB.Size > sqlTypeA.Size) ? sqlTypeB.Size : sqlTypeA.Size;
                }

                if (sqlTypeB.Size.HasValue && sqlTypeB.Size.Value == ProviderConstants.LargeTypeSizeIndicator ||
                    sqlTypeA.Size.HasValue && sqlTypeA.Size.Value == ProviderConstants.LargeTypeSizeIndicator)
                {
                    // the large type size trumps all
                    bestSize = ProviderConstants.LargeTypeSizeIndicator;
                }

                bestType = new SqlType(bestType.SqlDbType, bestSize);
            }

            return(bestType);
        }
Пример #10
0
        internal override ProviderType ReturnTypeOfFunction(SqlFunctionCall functionCall)
        {
            var argumentTypes = this.GetArgumentTypes(functionCall);

            SqlType arg0 = (SqlType)argumentTypes[0];
            SqlType arg1 = argumentTypes.Length > 1 ? (SqlType)argumentTypes[1] : (SqlType)null;

            switch (functionCall.Name)
            {
            case "LEN":
            case "DATALENGTH":
                switch (arg0.SqlDbType)
                {
                case SqlDbType.NVarChar:
                case SqlDbType.VarChar:
                case SqlDbType.VarBinary:
                    if (arg0.IsLargeType)
                    {
                        return(SqlTypeSystem.Create(SqlDbType.BigInt));
                    }
                    else
                    {
                        return(SqlTypeSystem.Create(SqlDbType.Int));
                    }

                default:
                    return(SqlTypeSystem.Create(SqlDbType.Int));
                }

            case "ABS":
            case "SIGN":
            case "ROUND":
            case "CEILING":
            case "FLOOR":
            case "POWER":
                switch (arg0.SqlDbType)
                {
                case SqlDbType.TinyInt:
                case SqlDbType.Int:
                case SqlDbType.SmallInt:
                    return(SqlTypeSystem.Create(SqlDbType.Int));

                case SqlDbType.Float:
                case SqlDbType.Real:
                    return(SqlTypeSystem.Create(SqlDbType.Float));

                default:
                    return(arg0);
                }

            case "PATINDEX":
            case "CHARINDEX":
                if (arg1.IsLargeType)
                {
                    return(SqlTypeSystem.Create(SqlDbType.BigInt));
                }
                return(SqlTypeSystem.Create(SqlDbType.Int));

            case "SUBSTRING":
                if (functionCall.Arguments[2].NodeType == SqlNodeType.Value)
                {
                    SqlValue val = (SqlValue)functionCall.Arguments[2];

                    if (val.Value is int)
                    {
                        switch (arg0.SqlDbType)
                        {
                        case SqlDbType.NVarChar:
                        case SqlDbType.NChar:
                        case SqlDbType.VarChar:
                        case SqlDbType.Char:
                            return(SqlTypeSystem.Create(arg0.SqlDbType, (int)val.Value));

                        default:
                            return(null);
                        }
                    }
                }
                switch (arg0.SqlDbType)
                {
                case SqlDbType.NVarChar:
                case SqlDbType.NChar:
                    return(SqlTypeSystem.Create(SqlDbType.NVarChar));

                case SqlDbType.VarChar:
                case SqlDbType.Char:
                    return(SqlTypeSystem.Create(SqlDbType.VarChar));

                default:
                    return(null);
                }

            case "STUFF":
                // if the stuff call is an insertion  and is strictly additive
                // (no deletion of characters) the return type is the same as
                // a concatenation
                if (functionCall.Arguments.Count == 4)
                {
                    SqlValue delLength = functionCall.Arguments[2] as SqlValue;
                    if (delLength != null && (int)delLength.Value == 0)
                    {
                        return(PredictTypeForBinary(SqlNodeType.Concat,
                                                    functionCall.Arguments[0].SqlType, functionCall.Arguments[3].SqlType));
                    }
                }
                return(null);

            case "LOWER":
            case "UPPER":
            case "RTRIM":
            case "LTRIM":
            case "INSERT":
            case "REPLACE":
            case "LEFT":
            case "RIGHT":
            case "REVERSE":
                return(arg0);

            default:
                return(null);
            }
        }
Пример #11
0
        internal override ProviderType Parse(string stype)
        {
            // parse type...
            string typeName = null;
            string param1   = null;
            string param2   = null;
            int    paren    = stype.IndexOf('(');
            int    space    = stype.IndexOf(' ');
            int    end      = (paren != -1 && space != -1) ? Math.Min(space, paren)
                                : (paren != -1) ? paren
                                        : (space != -1) ? space
                                                : -1;

            if (end == -1)
            {
                typeName = stype;
                end      = stype.Length;
            }
            else
            {
                typeName = stype.Substring(0, end);
            }
            int start = end;

            if (start < stype.Length && stype[start] == '(')
            {
                start++;
                end = stype.IndexOf(',', start);
                if (end > 0)
                {
                    param1 = stype.Substring(start, end - start);
                    start  = end + 1;
                    end    = stype.IndexOf(')', start);
                    param2 = stype.Substring(start, end - start);
                }
                else
                {
                    end    = stype.IndexOf(')', start);
                    param1 = stype.Substring(start, end - start);
                }
                start = end++;
            }

            #region Special case type mappings
            if (String.Compare(typeName, "rowversion", StringComparison.OrdinalIgnoreCase) == 0)
            {
                typeName = "Timestamp";
            }

            if (String.Compare(typeName, "numeric", StringComparison.OrdinalIgnoreCase) == 0)
            {
                typeName = "Decimal";
            }

            if (String.Compare(typeName, "sql_variant", StringComparison.OrdinalIgnoreCase) == 0)
            {
                typeName = "Variant";
            }

            if (String.Compare(typeName, "filestream", StringComparison.OrdinalIgnoreCase) == 0)
            {
                typeName = "Binary";
            }
            #endregion

            // since we're going to parse the enum value below, we verify
            // here that it is defined.  For example, types like table, cursor
            // are not valid.
            if (!Enum.GetNames(typeof(SqlDbType)).Select(n => n.ToUpperInvariant()).Contains(typeName.ToUpperInvariant()))
            {
                throw Error.InvalidProviderType(typeName);
            }

            int       p1     = 0;
            int       p2     = 0;
            SqlDbType dbType = (SqlDbType)Enum.Parse(typeof(SqlDbType), typeName, true);
            if (param1 != null)
            {
                if (String.Compare(param1.Trim(), "max", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    p1 = ProviderConstants.LargeTypeSizeIndicator;
                }
                else
                {
                    p1 = Int32.Parse(param1, Globalization.CultureInfo.InvariantCulture);
                    if (p1 == Int32.MaxValue)
                    {
                        p1 = ProviderConstants.LargeTypeSizeIndicator;
                    }
                }
            }

            if (param2 != null)
            {
                if (String.Compare(param2.Trim(), "max", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    p2 = ProviderConstants.LargeTypeSizeIndicator;
                }
                else
                {
                    p2 = Int32.Parse(param2, Globalization.CultureInfo.InvariantCulture);
                    if (p2 == Int32.MaxValue)
                    {
                        p2 = ProviderConstants.LargeTypeSizeIndicator;
                    }
                }
            }

            switch (dbType)
            {
            case SqlDbType.Binary:
            case SqlDbType.Char:
            case SqlDbType.NChar:
            case SqlDbType.NVarChar:
            case SqlDbType.VarBinary:
            case SqlDbType.VarChar:
                return(SqlTypeSystem.Create(dbType, p1));

            case SqlDbType.Decimal:
            case SqlDbType.Real:
            case SqlDbType.Float:
                return(SqlTypeSystem.Create(dbType, p1, p2));

            case SqlDbType.Timestamp:
            default:
                return(SqlTypeSystem.Create(dbType));
            }
        }