e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
935 lines
48 KiB
C#
935 lines
48 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="SqlEnums.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
// <owner current="true" primary="true">[....]</owner>
|
|
// <owner current="true" primary="false">[....]</owner>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Data.SqlClient {
|
|
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data.Common;
|
|
using System.Data.OleDb;
|
|
using System.Data.SqlTypes;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.Xml;
|
|
using System.IO;
|
|
using System.Data.Sql;
|
|
|
|
using MSS=Microsoft.SqlServer.Server;
|
|
|
|
internal sealed class MetaType {
|
|
internal readonly Type ClassType; // com+ type
|
|
internal readonly Type SqlType;
|
|
|
|
internal readonly int FixedLength; // fixed length size in bytes (-1 for variable)
|
|
internal readonly bool IsFixed; // true if fixed length, note that sqlchar and sqlbinary are not considered fixed length
|
|
internal readonly bool IsLong; // true if long
|
|
internal readonly bool IsPlp; // Column is Partially Length Prefixed (MAX)
|
|
internal readonly byte Precision; // maxium precision for numeric types // $
|
|
internal readonly byte Scale;
|
|
internal readonly byte TDSType;
|
|
internal readonly byte NullableType;
|
|
|
|
internal readonly string TypeName; // string name of this type
|
|
internal readonly SqlDbType SqlDbType;
|
|
internal readonly DbType DbType;
|
|
|
|
// holds count of property bytes expected for a SQLVariant structure
|
|
internal readonly byte PropBytes;
|
|
|
|
|
|
// pre-computed fields
|
|
internal readonly bool IsAnsiType;
|
|
internal readonly bool IsBinType;
|
|
internal readonly bool IsCharType;
|
|
internal readonly bool IsNCharType;
|
|
internal readonly bool IsSizeInCharacters;
|
|
internal readonly bool IsNewKatmaiType;
|
|
internal readonly bool IsVarTime;
|
|
|
|
internal readonly bool Is70Supported;
|
|
internal readonly bool Is80Supported;
|
|
internal readonly bool Is90Supported;
|
|
internal readonly bool Is100Supported;
|
|
|
|
public MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool isLong, bool isPlp, byte tdsType, byte nullableTdsType, string typeName, Type classType, Type sqlType, SqlDbType sqldbType, DbType dbType, byte propBytes) {
|
|
this.Precision = precision;
|
|
this.Scale = scale;
|
|
this.FixedLength = fixedLength;
|
|
this.IsFixed = isFixed;
|
|
this.IsLong = isLong;
|
|
this.IsPlp = isPlp;
|
|
// can we get rid of this (?just have a mapping?)
|
|
this.TDSType = tdsType;
|
|
this.NullableType = nullableTdsType;
|
|
this.TypeName = typeName;
|
|
this.SqlDbType = sqldbType;
|
|
this.DbType = dbType;
|
|
|
|
this.ClassType = classType;
|
|
this.SqlType = sqlType;
|
|
this.PropBytes = propBytes;
|
|
|
|
IsAnsiType = _IsAnsiType(sqldbType);
|
|
IsBinType = _IsBinType(sqldbType);
|
|
IsCharType = _IsCharType(sqldbType);
|
|
IsNCharType = _IsNCharType(sqldbType);
|
|
IsSizeInCharacters = _IsSizeInCharacters(sqldbType);
|
|
IsNewKatmaiType = _IsNewKatmaiType(sqldbType);
|
|
IsVarTime = _IsVarTime(sqldbType);
|
|
|
|
Is70Supported = _Is70Supported(SqlDbType);
|
|
Is80Supported = _Is80Supported(SqlDbType);
|
|
Is90Supported = _Is90Supported(SqlDbType);
|
|
Is100Supported = _Is100Supported(SqlDbType);
|
|
}
|
|
|
|
// properties should be inlined so there should be no perf penalty for using these accessor functions
|
|
public int TypeId { // partial length prefixed (xml, nvarchar(max),...)
|
|
get { return 0;}
|
|
}
|
|
|
|
private static bool _IsAnsiType(SqlDbType type) {
|
|
return(type == SqlDbType.Char ||
|
|
type == SqlDbType.VarChar ||
|
|
type == SqlDbType.Text);
|
|
}
|
|
|
|
// is this type size expressed as count of characters or bytes?
|
|
private static bool _IsSizeInCharacters(SqlDbType type) {
|
|
return(type == SqlDbType.NChar ||
|
|
type == SqlDbType.NVarChar ||
|
|
type == SqlDbType.Xml ||
|
|
type == SqlDbType.NText);
|
|
}
|
|
|
|
private static bool _IsCharType(SqlDbType type) {
|
|
return(type == SqlDbType.NChar ||
|
|
type == SqlDbType.NVarChar ||
|
|
type == SqlDbType.NText ||
|
|
type == SqlDbType.Char ||
|
|
type == SqlDbType.VarChar ||
|
|
type == SqlDbType.Text ||
|
|
type == SqlDbType.Xml);
|
|
}
|
|
|
|
private static bool _IsNCharType(SqlDbType type) {
|
|
return(type == SqlDbType.NChar ||
|
|
type == SqlDbType.NVarChar ||
|
|
type == SqlDbType.NText ||
|
|
type == SqlDbType.Xml);
|
|
}
|
|
|
|
private static bool _IsBinType(SqlDbType type) {
|
|
return(type == SqlDbType.Image ||
|
|
type == SqlDbType.Binary ||
|
|
type == SqlDbType.VarBinary ||
|
|
type == SqlDbType.Timestamp ||
|
|
type == SqlDbType.Udt ||
|
|
(int) type == 24 /*SqlSmallVarBinary*/);
|
|
}
|
|
|
|
private static bool _Is70Supported(SqlDbType type) {
|
|
return((type != SqlDbType.BigInt) && ((int)type > 0) &&
|
|
((int)type <= (int) SqlDbType.VarChar));
|
|
}
|
|
|
|
private static bool _Is80Supported(SqlDbType type) {
|
|
return((int)type >= 0 &&
|
|
((int)type <= (int) SqlDbType.Variant));
|
|
}
|
|
|
|
private static bool _Is90Supported(SqlDbType type) {
|
|
return _Is80Supported(type) ||
|
|
SqlDbType.Xml == type ||
|
|
SqlDbType.Udt == type;
|
|
}
|
|
|
|
private static bool _Is100Supported(SqlDbType type) {
|
|
return _Is90Supported(type) ||
|
|
SqlDbType.Date == type ||
|
|
SqlDbType.Time == type ||
|
|
SqlDbType.DateTime2 == type ||
|
|
SqlDbType.DateTimeOffset == type;
|
|
}
|
|
|
|
private static bool _IsNewKatmaiType(SqlDbType type) {
|
|
return SqlDbType.Structured == type;
|
|
}
|
|
|
|
internal static bool _IsVarTime(SqlDbType type) {
|
|
return (type == SqlDbType.Time || type == SqlDbType.DateTime2 || type == SqlDbType.DateTimeOffset);
|
|
}
|
|
|
|
//
|
|
// map SqlDbType to MetaType class
|
|
//
|
|
internal static MetaType GetMetaTypeFromSqlDbType(SqlDbType target, bool isMultiValued) { // WebData 113289
|
|
switch(target) {
|
|
case SqlDbType.BigInt: return MetaBigInt;
|
|
case SqlDbType.Binary: return MetaBinary;
|
|
case SqlDbType.Bit: return MetaBit;
|
|
case SqlDbType.Char: return MetaChar;
|
|
case SqlDbType.DateTime: return MetaDateTime;
|
|
case SqlDbType.Decimal: return MetaDecimal;
|
|
case SqlDbType.Float: return MetaFloat;
|
|
case SqlDbType.Image: return MetaImage;
|
|
case SqlDbType.Int: return MetaInt;
|
|
case SqlDbType.Money: return MetaMoney;
|
|
case SqlDbType.NChar: return MetaNChar;
|
|
case SqlDbType.NText: return MetaNText;
|
|
case SqlDbType.NVarChar: return MetaNVarChar;
|
|
case SqlDbType.Real: return MetaReal;
|
|
case SqlDbType.UniqueIdentifier: return MetaUniqueId;
|
|
case SqlDbType.SmallDateTime: return MetaSmallDateTime;
|
|
case SqlDbType.SmallInt: return MetaSmallInt;
|
|
case SqlDbType.SmallMoney: return MetaSmallMoney;
|
|
case SqlDbType.Text: return MetaText;
|
|
case SqlDbType.Timestamp: return MetaTimestamp;
|
|
case SqlDbType.TinyInt: return MetaTinyInt;
|
|
case SqlDbType.VarBinary: return MetaVarBinary;
|
|
case SqlDbType.VarChar: return MetaVarChar;
|
|
case SqlDbType.Variant: return MetaVariant;
|
|
case (SqlDbType)TdsEnums.SmallVarBinary: return MetaSmallVarBinary;
|
|
case SqlDbType.Xml: return MetaXml;
|
|
case SqlDbType.Udt: return MetaUdt;
|
|
case SqlDbType.Structured:
|
|
if (isMultiValued) {
|
|
return MetaTable;
|
|
}
|
|
else {
|
|
return MetaSUDT;
|
|
}
|
|
case SqlDbType.Date: return MetaDate;
|
|
case SqlDbType.Time: return MetaTime;
|
|
case SqlDbType.DateTime2: return MetaDateTime2;
|
|
case SqlDbType.DateTimeOffset: return MetaDateTimeOffset;
|
|
default: throw SQL.InvalidSqlDbType(target);
|
|
}
|
|
}
|
|
|
|
//
|
|
// map DbType to MetaType class
|
|
//
|
|
internal static MetaType GetMetaTypeFromDbType(DbType target) {
|
|
// if we can't map it, we need to throw
|
|
switch (target) {
|
|
case DbType.AnsiString: return MetaVarChar;
|
|
case DbType.AnsiStringFixedLength: return MetaChar;
|
|
case DbType.Binary: return MetaVarBinary;
|
|
case DbType.Byte: return MetaTinyInt;
|
|
case DbType.Boolean: return MetaBit;
|
|
case DbType.Currency: return MetaMoney;
|
|
case DbType.Date:
|
|
case DbType.DateTime: return MetaDateTime;
|
|
case DbType.Decimal: return MetaDecimal;
|
|
case DbType.Double: return MetaFloat;
|
|
case DbType.Guid: return MetaUniqueId;
|
|
case DbType.Int16: return MetaSmallInt;
|
|
case DbType.Int32: return MetaInt;
|
|
case DbType.Int64: return MetaBigInt;
|
|
case DbType.Object: return MetaVariant;
|
|
case DbType.Single: return MetaReal;
|
|
case DbType.String: return MetaNVarChar;
|
|
case DbType.StringFixedLength: return MetaNChar;
|
|
case DbType.Time: return MetaDateTime;
|
|
case DbType.Xml: return MetaXml;
|
|
case DbType.DateTime2: return MetaDateTime2;
|
|
case DbType.DateTimeOffset: return MetaDateTimeOffset;
|
|
case DbType.SByte: // unsupported
|
|
case DbType.UInt16:
|
|
case DbType.UInt32:
|
|
case DbType.UInt64:
|
|
case DbType.VarNumeric:
|
|
default: throw ADP.DbTypeNotSupported(target, typeof(SqlDbType)); // no direct mapping, error out
|
|
}
|
|
}
|
|
|
|
internal static MetaType GetMaxMetaTypeFromMetaType(MetaType mt) {
|
|
// if we can't map it, we need to throw
|
|
switch (mt.SqlDbType) {
|
|
case SqlDbType.VarBinary:
|
|
case SqlDbType.Binary:
|
|
return MetaMaxVarBinary;
|
|
case SqlDbType.VarChar:
|
|
case SqlDbType.Char:
|
|
return MetaMaxVarChar;
|
|
case SqlDbType.NVarChar:
|
|
case SqlDbType.NChar:
|
|
return MetaMaxNVarChar;
|
|
case SqlDbType.Udt:
|
|
//
|
|
return MetaMaxUdt;
|
|
default:
|
|
return mt;
|
|
}
|
|
}
|
|
|
|
//
|
|
// map COM+ Type to MetaType class
|
|
//
|
|
static internal MetaType GetMetaTypeFromType(Type dataType) {
|
|
return GetMetaTypeFromValue(dataType, null, false, true);
|
|
}
|
|
static internal MetaType GetMetaTypeFromValue(object value, bool streamAllowed=true) {
|
|
return GetMetaTypeFromValue(value.GetType(), value, true, streamAllowed);
|
|
}
|
|
|
|
static private MetaType GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed) {
|
|
switch (Type.GetTypeCode(dataType)) {
|
|
case TypeCode.Empty: throw ADP.InvalidDataType(TypeCode.Empty);
|
|
case TypeCode.Object:
|
|
if (dataType == typeof(System.Byte[])) {
|
|
// mdac 90455 must not default to image if inferLen is false ...
|
|
//
|
|
if (!inferLen || ((byte[]) value).Length <= TdsEnums.TYPE_SIZE_LIMIT) {
|
|
return MetaVarBinary;
|
|
}
|
|
else {
|
|
return MetaImage;
|
|
}
|
|
}
|
|
else if (dataType == typeof(System.Guid)) {
|
|
return MetaUniqueId;
|
|
}
|
|
else if (dataType == typeof(System.Object)) {
|
|
return MetaVariant;
|
|
} // check sql types now
|
|
else if (dataType == typeof(SqlBinary))
|
|
return MetaVarBinary;
|
|
else if (dataType == typeof(SqlBoolean))
|
|
return MetaBit;
|
|
else if (dataType == typeof(SqlByte))
|
|
return MetaTinyInt;
|
|
else if (dataType == typeof(SqlBytes))
|
|
return MetaVarBinary;
|
|
else if (dataType == typeof(SqlChars))
|
|
return MetaNVarChar; // MDAC 87587
|
|
else if (dataType == typeof(SqlDateTime))
|
|
return MetaDateTime;
|
|
else if (dataType == typeof(SqlDouble))
|
|
return MetaFloat;
|
|
else if (dataType == typeof(SqlGuid))
|
|
return MetaUniqueId;
|
|
else if (dataType == typeof(SqlInt16))
|
|
return MetaSmallInt;
|
|
else if (dataType == typeof(SqlInt32))
|
|
return MetaInt;
|
|
else if (dataType == typeof(SqlInt64))
|
|
return MetaBigInt;
|
|
else if (dataType == typeof(SqlMoney))
|
|
return MetaMoney;
|
|
else if (dataType == typeof(SqlDecimal))
|
|
return MetaDecimal;
|
|
else if (dataType == typeof(SqlSingle))
|
|
return MetaReal;
|
|
else if (dataType == typeof(SqlXml))
|
|
return MetaXml;
|
|
else if (dataType == typeof(SqlString)) {
|
|
return ((inferLen && !((SqlString)value).IsNull) ? PromoteStringType(((SqlString)value).Value) : MetaNVarChar); // MDAC 87587
|
|
}
|
|
else if (dataType == typeof(IEnumerable<DbDataRecord>) || dataType == typeof(DataTable)) {
|
|
return MetaTable;
|
|
} else if (dataType == typeof(TimeSpan)) {
|
|
return MetaTime;
|
|
}
|
|
else if (dataType == typeof(DateTimeOffset)) {
|
|
return MetaDateTimeOffset;
|
|
}
|
|
else {
|
|
// UDT ?
|
|
SqlUdtInfo attribs = SqlUdtInfo.TryGetFromType(dataType);
|
|
if (attribs != null) {
|
|
return MetaUdt;
|
|
}
|
|
if (streamAllowed) {
|
|
// Derived from Stream ?
|
|
if (typeof(Stream).IsAssignableFrom(dataType)) {
|
|
return MetaVarBinary;
|
|
}
|
|
// Derived from TextReader ?
|
|
if (typeof(TextReader).IsAssignableFrom(dataType)) {
|
|
return MetaNVarChar;
|
|
}
|
|
// Derived from XmlReader ?
|
|
if (typeof(System.Xml.XmlReader).IsAssignableFrom(dataType)) {
|
|
return MetaXml;
|
|
}
|
|
}
|
|
}
|
|
throw ADP.UnknownDataType(dataType);
|
|
|
|
case TypeCode.DBNull: throw ADP.InvalidDataType(TypeCode.DBNull);
|
|
case TypeCode.Boolean: return MetaBit;
|
|
case TypeCode.Char: throw ADP.InvalidDataType(TypeCode.Char);
|
|
case TypeCode.SByte: throw ADP.InvalidDataType(TypeCode.SByte);
|
|
case TypeCode.Byte: return MetaTinyInt;
|
|
case TypeCode.Int16: return MetaSmallInt;
|
|
case TypeCode.UInt16: throw ADP.InvalidDataType(TypeCode.UInt16);
|
|
case TypeCode.Int32: return MetaInt;
|
|
case TypeCode.UInt32: throw ADP.InvalidDataType(TypeCode.UInt32);
|
|
case TypeCode.Int64: return MetaBigInt;
|
|
case TypeCode.UInt64: throw ADP.InvalidDataType(TypeCode.UInt64);
|
|
case TypeCode.Single: return MetaReal;
|
|
case TypeCode.Double: return MetaFloat;
|
|
case TypeCode.Decimal: return MetaDecimal;
|
|
case TypeCode.DateTime: return MetaDateTime;
|
|
case TypeCode.String: return (inferLen ? PromoteStringType((string)value) : MetaNVarChar);
|
|
default: throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType));
|
|
}
|
|
}
|
|
|
|
internal static object GetNullSqlValue(Type sqlType) {
|
|
if (sqlType == typeof(SqlSingle)) return SqlSingle.Null;
|
|
else if (sqlType == typeof(SqlString)) return SqlString.Null;
|
|
else if (sqlType == typeof(SqlDouble)) return SqlDouble.Null;
|
|
else if (sqlType == typeof(SqlBinary)) return SqlBinary.Null;
|
|
else if (sqlType == typeof(SqlGuid)) return SqlGuid.Null;
|
|
else if (sqlType == typeof(SqlBoolean)) return SqlBoolean.Null;
|
|
else if (sqlType == typeof(SqlByte)) return SqlByte.Null;
|
|
else if (sqlType == typeof(SqlInt16)) return SqlInt16.Null;
|
|
else if (sqlType == typeof(SqlInt32)) return SqlInt32.Null;
|
|
else if (sqlType == typeof(SqlInt64)) return SqlInt64.Null;
|
|
else if (sqlType == typeof(SqlDecimal)) return SqlDecimal.Null;
|
|
else if (sqlType == typeof(SqlDateTime)) return SqlDateTime.Null;
|
|
else if (sqlType == typeof(SqlMoney)) return SqlMoney.Null;
|
|
else if (sqlType == typeof(SqlXml)) return SqlXml.Null;
|
|
else if (sqlType == typeof(object)) return DBNull.Value;
|
|
else if (sqlType == typeof(IEnumerable<DbDataRecord>)) return DBNull.Value;
|
|
else if (sqlType == typeof(DataTable)) return DBNull.Value;
|
|
else if (sqlType == typeof(DateTime)) return DBNull.Value;
|
|
else if (sqlType == typeof(TimeSpan)) return DBNull.Value;
|
|
else if (sqlType == typeof(DateTimeOffset)) return DBNull.Value;
|
|
else {
|
|
Debug.Assert(false, "Unknown SqlType!");
|
|
return DBNull.Value;
|
|
}
|
|
}
|
|
|
|
internal static MetaType PromoteStringType(string s) {
|
|
int len = s.Length;
|
|
|
|
if ((len << 1) > TdsEnums.TYPE_SIZE_LIMIT) {
|
|
return MetaVarChar; // try as var char since we can send a 8K characters
|
|
}
|
|
return MetaNVarChar; // send 4k chars, but send as unicode
|
|
}
|
|
|
|
internal static object GetComValueFromSqlVariant(object sqlVal) {
|
|
object comVal = null;
|
|
|
|
if (ADP.IsNull(sqlVal))
|
|
return comVal;
|
|
|
|
if (sqlVal is SqlSingle)
|
|
comVal = ((SqlSingle)sqlVal).Value;
|
|
else if (sqlVal is SqlString)
|
|
comVal = ((SqlString)sqlVal).Value;
|
|
else if (sqlVal is SqlDouble)
|
|
comVal = ((SqlDouble)sqlVal).Value;
|
|
else if (sqlVal is SqlBinary)
|
|
comVal = ((SqlBinary)sqlVal).Value;
|
|
else if (sqlVal is SqlGuid)
|
|
comVal = ((SqlGuid)sqlVal).Value;
|
|
else if (sqlVal is SqlBoolean)
|
|
comVal = ((SqlBoolean)sqlVal).Value;
|
|
else if (sqlVal is SqlByte)
|
|
comVal = ((SqlByte)sqlVal).Value;
|
|
else if (sqlVal is SqlInt16)
|
|
comVal = ((SqlInt16)sqlVal).Value;
|
|
else if (sqlVal is SqlInt32)
|
|
comVal = ((SqlInt32)sqlVal).Value;
|
|
else if (sqlVal is SqlInt64)
|
|
comVal = ((SqlInt64)sqlVal).Value;
|
|
else if (sqlVal is SqlDecimal)
|
|
comVal = ((SqlDecimal)sqlVal).Value;
|
|
else if (sqlVal is SqlDateTime)
|
|
comVal = ((SqlDateTime)sqlVal).Value;
|
|
else if (sqlVal is SqlMoney)
|
|
comVal = ((SqlMoney)sqlVal).Value;
|
|
else if (sqlVal is SqlXml)
|
|
comVal = ((SqlXml)sqlVal).Value;
|
|
else
|
|
{
|
|
AssertIsUserDefinedTypeInstance(sqlVal, "unknown SqlType class stored in sqlVal");
|
|
}
|
|
|
|
|
|
return comVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assert that the supplied object is an instance of a SQL User-Defined Type (UDT).
|
|
/// </summary>
|
|
/// <param name="sqlValue">Object instance to be tested.</param>
|
|
/// <remarks>
|
|
/// This method is only compiled with debug builds, and it a helper method for the GetComValueFromSqlVariant method defined in this class.
|
|
///
|
|
/// The presence of the SqlUserDefinedTypeAttribute on the object's type
|
|
/// is used to determine if the object is a UDT instance (if present it is a UDT, else it is not).
|
|
/// </remarks>
|
|
/// <exception cref="NullReferenceException">
|
|
/// If sqlValue is null. Callers must ensure the object is non-null.
|
|
/// </exception>
|
|
[Conditional("DEBUG")]
|
|
private static void AssertIsUserDefinedTypeInstance(object sqlValue, string failedAssertMessage)
|
|
{
|
|
Type type = sqlValue.GetType();
|
|
Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[] attributes = (Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[])type.GetCustomAttributes(typeof(Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute), true);
|
|
|
|
Debug.Assert(attributes.Length > 0, failedAssertMessage);
|
|
}
|
|
|
|
// devnote: This method should not be used with SqlDbType.Date and SqlDbType.DateTime2.
|
|
// With these types the values should be used directly as CLR types instead of being converted to a SqlValue
|
|
internal static object GetSqlValueFromComVariant(object comVal) {
|
|
object sqlVal = null;
|
|
if ((null != comVal) && (DBNull.Value != comVal)) {
|
|
if (comVal is float)
|
|
sqlVal = new SqlSingle((float)comVal);
|
|
else if (comVal is string)
|
|
sqlVal = new SqlString((string)comVal);
|
|
else if (comVal is double)
|
|
sqlVal = new SqlDouble((double)comVal);
|
|
else if (comVal is System.Byte[])
|
|
sqlVal = new SqlBinary((byte[])comVal);
|
|
else if (comVal is System.Char)
|
|
sqlVal = new SqlString(((char)comVal).ToString());
|
|
else if (comVal is System.Char[])
|
|
sqlVal = new SqlChars((System.Char[])comVal);
|
|
else if (comVal is System.Guid)
|
|
sqlVal = new SqlGuid((Guid)comVal);
|
|
else if (comVal is bool)
|
|
sqlVal = new SqlBoolean((bool)comVal);
|
|
else if (comVal is byte)
|
|
sqlVal = new SqlByte((byte)comVal);
|
|
else if (comVal is Int16)
|
|
sqlVal = new SqlInt16((Int16)comVal);
|
|
else if (comVal is Int32)
|
|
sqlVal = new SqlInt32((Int32)comVal);
|
|
else if (comVal is Int64)
|
|
sqlVal = new SqlInt64((Int64)comVal);
|
|
else if (comVal is Decimal)
|
|
sqlVal = new SqlDecimal((Decimal)comVal);
|
|
else if (comVal is DateTime) {
|
|
// devnote: Do not use with SqlDbType.Date and SqlDbType.DateTime2. See comment at top of method.
|
|
sqlVal = new SqlDateTime((DateTime)comVal);
|
|
} else if (comVal is XmlReader)
|
|
sqlVal = new SqlXml((XmlReader)comVal);
|
|
else if (comVal is TimeSpan || comVal is DateTimeOffset)
|
|
sqlVal = comVal;
|
|
#if DEBUG
|
|
else
|
|
Debug.Assert(false, "unknown SqlType class stored in sqlVal");
|
|
#endif
|
|
}
|
|
return sqlVal;
|
|
}
|
|
|
|
internal static SqlDbType GetSqlDbTypeFromOleDbType(short dbType, string typeName) {
|
|
SqlDbType sqlType = SqlDbType.Variant;
|
|
switch ((OleDbType)dbType) {
|
|
case OleDbType.BigInt:
|
|
sqlType = SqlDbType.BigInt;
|
|
break;
|
|
case OleDbType.Boolean:
|
|
sqlType = SqlDbType.Bit;
|
|
break;
|
|
case OleDbType.Char:
|
|
case OleDbType.VarChar:
|
|
// these guys are ambiguous - server sends over DBTYPE_STR in both cases
|
|
sqlType = (typeName == MetaTypeName.CHAR) ? SqlDbType.Char : SqlDbType.VarChar;
|
|
break;
|
|
case OleDbType.Currency:
|
|
sqlType = (typeName == MetaTypeName.SMALLMONEY) ? SqlDbType.SmallMoney : SqlDbType.Money;
|
|
break;
|
|
case OleDbType.Date:
|
|
case OleDbType.DBTimeStamp:
|
|
case OleDbType.Filetime:
|
|
switch (typeName) {
|
|
case MetaTypeName.SMALLDATETIME:
|
|
sqlType = SqlDbType.SmallDateTime;
|
|
break;
|
|
case MetaTypeName.DATETIME2:
|
|
sqlType = SqlDbType.DateTime2;
|
|
break;
|
|
default:
|
|
sqlType = SqlDbType.DateTime;
|
|
break;
|
|
}
|
|
break;
|
|
case OleDbType.Decimal:
|
|
case OleDbType.Numeric:
|
|
sqlType = SqlDbType.Decimal;
|
|
break;
|
|
case OleDbType.Double:
|
|
sqlType = SqlDbType.Float;
|
|
break;
|
|
case OleDbType.Guid:
|
|
sqlType = SqlDbType.UniqueIdentifier;
|
|
break;
|
|
case OleDbType.Integer:
|
|
sqlType = SqlDbType.Int;
|
|
break;
|
|
case OleDbType.LongVarBinary:
|
|
sqlType = SqlDbType.Image;
|
|
break;
|
|
case OleDbType.LongVarChar:
|
|
sqlType = SqlDbType.Text;
|
|
break;
|
|
case OleDbType.LongVarWChar:
|
|
sqlType = SqlDbType.NText;
|
|
break;
|
|
case OleDbType.Single:
|
|
sqlType = SqlDbType.Real;
|
|
break;
|
|
case OleDbType.SmallInt:
|
|
case OleDbType.UnsignedSmallInt:
|
|
sqlType = SqlDbType.SmallInt;
|
|
break;
|
|
case OleDbType.TinyInt:
|
|
case OleDbType.UnsignedTinyInt:
|
|
sqlType = SqlDbType.TinyInt;
|
|
break;
|
|
case OleDbType.VarBinary:
|
|
case OleDbType.Binary:
|
|
sqlType = (typeName == MetaTypeName.BINARY) ? SqlDbType.Binary : SqlDbType.VarBinary;
|
|
break;
|
|
case OleDbType.Variant:
|
|
sqlType = SqlDbType.Variant;
|
|
break;
|
|
case OleDbType.VarWChar:
|
|
case OleDbType.WChar:
|
|
case OleDbType.BSTR:
|
|
// these guys are ambiguous - server sends over DBTYPE_WSTR in both cases
|
|
// BSTR is always assumed to be NVARCHAR
|
|
sqlType = (typeName == MetaTypeName.NCHAR) ? SqlDbType.NChar : SqlDbType.NVarChar;
|
|
break;
|
|
case OleDbType.DBDate: // Date
|
|
sqlType = SqlDbType.Date;
|
|
break;
|
|
case (OleDbType)132: // Udt
|
|
sqlType = SqlDbType.Udt;
|
|
break;
|
|
case (OleDbType)141: // Xml
|
|
sqlType = SqlDbType.Xml;
|
|
break;
|
|
case (OleDbType)145: // Time
|
|
sqlType = SqlDbType.Time;
|
|
break;
|
|
case (OleDbType)146: // DateTimeOffset
|
|
sqlType = SqlDbType.DateTimeOffset;
|
|
break;
|
|
//
|
|
default:
|
|
break; // no direct mapping, just use SqlDbType.Variant;
|
|
}
|
|
|
|
return sqlType;
|
|
}
|
|
|
|
internal static MetaType GetSqlDataType(int tdsType, UInt32 userType, int length) {
|
|
switch (tdsType) {
|
|
case TdsEnums.SQLMONEYN: return ((4 == length) ? MetaSmallMoney : MetaMoney);
|
|
case TdsEnums.SQLDATETIMN: return ((4 == length) ? MetaSmallDateTime : MetaDateTime);
|
|
case TdsEnums.SQLINTN: return ((4 <= length) ? ((4 == length) ? MetaInt : MetaBigInt) : ((2 == length) ? MetaSmallInt : MetaTinyInt));
|
|
case TdsEnums.SQLFLTN: return ((4 == length) ? MetaReal : MetaFloat);
|
|
case TdsEnums.SQLTEXT: return MetaText;
|
|
case TdsEnums.SQLVARBINARY: return MetaSmallVarBinary;
|
|
case TdsEnums.SQLBIGVARBINARY: return MetaVarBinary;
|
|
|
|
case TdsEnums.SQLVARCHAR: //goto TdsEnums.SQLBIGVARCHAR;
|
|
case TdsEnums.SQLBIGVARCHAR: return MetaVarChar;
|
|
|
|
case TdsEnums.SQLBINARY: //goto TdsEnums.SQLBIGBINARY;
|
|
case TdsEnums.SQLBIGBINARY: return ((TdsEnums.SQLTIMESTAMP == userType) ? MetaTimestamp : MetaBinary);
|
|
|
|
case TdsEnums.SQLIMAGE: return MetaImage;
|
|
|
|
case TdsEnums.SQLCHAR: //goto TdsEnums.SQLBIGCHAR;
|
|
case TdsEnums.SQLBIGCHAR: return MetaChar;
|
|
|
|
case TdsEnums.SQLINT1: return MetaTinyInt;
|
|
|
|
case TdsEnums.SQLBIT: //goto TdsEnums.SQLBITN;
|
|
case TdsEnums.SQLBITN: return MetaBit;
|
|
|
|
case TdsEnums.SQLINT2: return MetaSmallInt;
|
|
case TdsEnums.SQLINT4: return MetaInt;
|
|
case TdsEnums.SQLINT8: return MetaBigInt;
|
|
case TdsEnums.SQLMONEY: return MetaMoney;
|
|
case TdsEnums.SQLDATETIME: return MetaDateTime;
|
|
case TdsEnums.SQLFLT8: return MetaFloat;
|
|
case TdsEnums.SQLFLT4: return MetaReal;
|
|
case TdsEnums.SQLMONEY4: return MetaSmallMoney;
|
|
case TdsEnums.SQLDATETIM4: return MetaSmallDateTime;
|
|
|
|
case TdsEnums.SQLDECIMALN: //goto TdsEnums.SQLNUMERICN;
|
|
case TdsEnums.SQLNUMERICN: return MetaDecimal;
|
|
|
|
case TdsEnums.SQLUNIQUEID: return MetaUniqueId ;
|
|
case TdsEnums.SQLNCHAR: return MetaNChar;
|
|
case TdsEnums.SQLNVARCHAR: return MetaNVarChar;
|
|
case TdsEnums.SQLNTEXT: return MetaNText;
|
|
case TdsEnums.SQLVARIANT: return MetaVariant;
|
|
case TdsEnums.SQLUDT: return MetaUdt;
|
|
case TdsEnums.SQLXMLTYPE: return MetaXml;
|
|
case TdsEnums.SQLTABLE: return MetaTable;
|
|
case TdsEnums.SQLDATE: return MetaDate;
|
|
case TdsEnums.SQLTIME: return MetaTime;
|
|
case TdsEnums.SQLDATETIME2: return MetaDateTime2;
|
|
case TdsEnums.SQLDATETIMEOFFSET: return MetaDateTimeOffset;
|
|
|
|
case TdsEnums.SQLVOID:
|
|
default:
|
|
Debug.Assert(false, "Unknown type " + tdsType.ToString(CultureInfo.InvariantCulture));
|
|
throw SQL.InvalidSqlDbType((SqlDbType)tdsType);
|
|
}// case
|
|
}
|
|
|
|
internal static MetaType GetDefaultMetaType() {
|
|
return MetaNVarChar;
|
|
}
|
|
|
|
// Converts an XmlReader into String
|
|
internal static String GetStringFromXml(XmlReader xmlreader) {
|
|
SqlXml sxml = new SqlXml(xmlreader);
|
|
return sxml.Value;
|
|
}
|
|
|
|
private static readonly MetaType MetaBigInt = new MetaType
|
|
(19, 255, 8, true, false, false, TdsEnums.SQLINT8, TdsEnums.SQLINTN, MetaTypeName.BIGINT, typeof(System.Int64), typeof(SqlInt64), SqlDbType.BigInt, DbType.Int64, 0);
|
|
|
|
private static readonly MetaType MetaFloat = new MetaType
|
|
(15, 255, 8, true, false, false, TdsEnums.SQLFLT8, TdsEnums.SQLFLTN, MetaTypeName.FLOAT, typeof(System.Double), typeof(SqlDouble), SqlDbType.Float, DbType.Double, 0);
|
|
|
|
private static readonly MetaType MetaReal = new MetaType
|
|
(7, 255, 4, true, false, false, TdsEnums.SQLFLT4, TdsEnums.SQLFLTN, MetaTypeName.REAL, typeof(System.Single), typeof(SqlSingle), SqlDbType.Real, DbType.Single, 0);
|
|
|
|
// MetaBinary has two bytes of properties for binary and varbinary
|
|
// 2 byte maxlen
|
|
private static readonly MetaType MetaBinary = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.BINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Binary, DbType.Binary, 2);
|
|
|
|
// syntatic sugar for the user...timestamps are 8-byte fixed length binary columns
|
|
private static readonly MetaType MetaTimestamp = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.TIMESTAMP, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Timestamp, DbType.Binary, 2);
|
|
|
|
internal static readonly MetaType MetaVarBinary = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2);
|
|
|
|
internal static readonly MetaType MetaMaxVarBinary = new MetaType
|
|
(255, 255, -1, false, true, true, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2);
|
|
|
|
// HACK!!! We have an internal type for smallvarbinarys stored on TdsEnums. We
|
|
// store on TdsEnums instead of SqlDbType because we do not want to expose
|
|
// this type to the user!
|
|
private static readonly MetaType MetaSmallVarBinary = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLVARBINARY, TdsEnums.SQLBIGBINARY, ADP.StrEmpty, typeof(System.Byte[]), typeof(SqlBinary), TdsEnums.SmallVarBinary, DbType.Binary, 2);
|
|
|
|
internal static readonly MetaType MetaImage = new MetaType
|
|
(255, 255, -1, false, true, false, TdsEnums.SQLIMAGE, TdsEnums.SQLIMAGE, MetaTypeName.IMAGE, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Image, DbType.Binary, 0);
|
|
|
|
private static readonly MetaType MetaBit = new MetaType
|
|
(255, 255, 1, true, false, false, TdsEnums.SQLBIT, TdsEnums.SQLBITN, MetaTypeName.BIT, typeof(System.Boolean), typeof(SqlBoolean), SqlDbType.Bit, DbType.Boolean, 0);
|
|
|
|
private static readonly MetaType MetaTinyInt = new MetaType
|
|
(3, 255, 1, true, false, false, TdsEnums.SQLINT1, TdsEnums.SQLINTN, MetaTypeName.TINYINT, typeof(System.Byte), typeof(SqlByte), SqlDbType.TinyInt, DbType.Byte, 0);
|
|
|
|
private static readonly MetaType MetaSmallInt = new MetaType
|
|
(5, 255, 2, true, false, false, TdsEnums.SQLINT2, TdsEnums.SQLINTN, MetaTypeName.SMALLINT, typeof(System.Int16), typeof(SqlInt16), SqlDbType.SmallInt, DbType.Int16, 0);
|
|
|
|
private static readonly MetaType MetaInt = new MetaType
|
|
(10, 255, 4, true, false, false, TdsEnums.SQLINT4, TdsEnums.SQLINTN, MetaTypeName.INT, typeof(System.Int32), typeof(SqlInt32), SqlDbType.Int, DbType.Int32, 0);
|
|
|
|
// MetaVariant has seven bytes of properties for MetaChar and MetaVarChar
|
|
// 5 byte tds collation
|
|
// 2 byte maxlen
|
|
private static readonly MetaType MetaChar = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLBIGCHAR, TdsEnums.SQLBIGCHAR, MetaTypeName.CHAR, typeof(System.String), typeof(SqlString), SqlDbType.Char, DbType.AnsiStringFixedLength, 7);
|
|
|
|
private static readonly MetaType MetaVarChar = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7);
|
|
|
|
internal static readonly MetaType MetaMaxVarChar = new MetaType
|
|
(255, 255, -1, false, true, true, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7);
|
|
|
|
internal static readonly MetaType MetaText = new MetaType
|
|
(255, 255, -1, false, true, false, TdsEnums.SQLTEXT, TdsEnums.SQLTEXT, MetaTypeName.TEXT, typeof(System.String), typeof(SqlString), SqlDbType.Text, DbType.AnsiString, 0);
|
|
|
|
// MetaVariant has seven bytes of properties for MetaNChar and MetaNVarChar
|
|
// 5 byte tds collation
|
|
// 2 byte maxlen
|
|
private static readonly MetaType MetaNChar = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLNCHAR, TdsEnums.SQLNCHAR, MetaTypeName.NCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NChar, DbType.StringFixedLength, 7);
|
|
|
|
internal static readonly MetaType MetaNVarChar = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7);
|
|
|
|
internal static readonly MetaType MetaMaxNVarChar = new MetaType
|
|
(255, 255, -1, false, true, true, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7);
|
|
|
|
internal static readonly MetaType MetaNText = new MetaType
|
|
(255, 255, -1, false, true, false, TdsEnums.SQLNTEXT, TdsEnums.SQLNTEXT, MetaTypeName.NTEXT, typeof(System.String), typeof(SqlString), SqlDbType.NText, DbType.String, 7);
|
|
|
|
// MetaVariant has two bytes of properties for numeric/decimal types
|
|
// 1 byte precision
|
|
// 1 byte scale
|
|
internal static readonly MetaType MetaDecimal = new MetaType
|
|
(38, 4, 17, true, false, false, TdsEnums.SQLNUMERICN, TdsEnums.SQLNUMERICN, MetaTypeName.DECIMAL, typeof(System.Decimal), typeof(SqlDecimal), SqlDbType.Decimal, DbType.Decimal, 2);
|
|
|
|
internal static readonly MetaType MetaXml = new MetaType
|
|
(255, 255, -1, false, true, true, TdsEnums.SQLXMLTYPE, TdsEnums.SQLXMLTYPE, MetaTypeName.XML, typeof(System.String), typeof(SqlXml), SqlDbType.Xml, DbType.Xml, 0);
|
|
|
|
private static readonly MetaType MetaDateTime = new MetaType
|
|
(23, 3, 8, true, false, false, TdsEnums.SQLDATETIME, TdsEnums.SQLDATETIMN, MetaTypeName.DATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.DateTime, DbType.DateTime, 0);
|
|
|
|
private static readonly MetaType MetaSmallDateTime = new MetaType
|
|
(16, 0, 4, true, false, false, TdsEnums.SQLDATETIM4, TdsEnums.SQLDATETIMN, MetaTypeName.SMALLDATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.SmallDateTime, DbType.DateTime, 0);
|
|
|
|
private static readonly MetaType MetaMoney = new MetaType
|
|
(19, 255, 8, true, false, false, TdsEnums.SQLMONEY, TdsEnums.SQLMONEYN, MetaTypeName.MONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.Money, DbType.Currency, 0);
|
|
|
|
private static readonly MetaType MetaSmallMoney = new MetaType
|
|
(10, 255, 4, true, false, false, TdsEnums.SQLMONEY4, TdsEnums.SQLMONEYN, MetaTypeName.SMALLMONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.SmallMoney, DbType.Currency, 0);
|
|
|
|
private static readonly MetaType MetaUniqueId = new MetaType
|
|
(255, 255, 16, true, false, false, TdsEnums.SQLUNIQUEID, TdsEnums.SQLUNIQUEID, MetaTypeName.ROWGUID, typeof(System.Guid), typeof(SqlGuid), SqlDbType.UniqueIdentifier, DbType.Guid, 0);
|
|
|
|
private static readonly MetaType MetaVariant = new MetaType
|
|
(255, 255, -1, true, false, false, TdsEnums.SQLVARIANT, TdsEnums.SQLVARIANT, MetaTypeName.VARIANT, typeof(System.Object), typeof(System.Object), SqlDbType.Variant, DbType.Object, 0);
|
|
|
|
internal static readonly MetaType MetaUdt = new MetaType
|
|
(255, 255, -1, false, false, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0);
|
|
|
|
private static readonly MetaType MetaMaxUdt = new MetaType
|
|
(255, 255, -1, false, true, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0);
|
|
|
|
private static readonly MetaType MetaTable = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable<DbDataRecord>), typeof(IEnumerable<DbDataRecord>), SqlDbType.Structured, DbType.Object, 0);
|
|
|
|
//
|
|
|
|
private static readonly MetaType MetaSUDT = new MetaType
|
|
(255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(MSS.SqlDataRecord), typeof(MSS.SqlDataRecord), SqlDbType.Structured, DbType.Object, 0);
|
|
|
|
private static readonly MetaType MetaDate = new MetaType
|
|
(255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0);
|
|
|
|
internal static readonly MetaType MetaTime = new MetaType
|
|
(255, 7, -1, false, false, false, TdsEnums.SQLTIME, TdsEnums.SQLTIME, MetaTypeName.TIME, typeof(System.TimeSpan), typeof(System.TimeSpan), SqlDbType.Time, DbType.Time, 1);
|
|
|
|
private static readonly MetaType MetaDateTime2 = new MetaType
|
|
(255, 7, -1, false, false, false, TdsEnums.SQLDATETIME2, TdsEnums.SQLDATETIME2, MetaTypeName.DATETIME2, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.DateTime2, DbType.DateTime2, 1);
|
|
|
|
internal static readonly MetaType MetaDateTimeOffset = new MetaType
|
|
(255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1);
|
|
|
|
public static TdsDateTime FromDateTime(DateTime dateTime, byte cb) {
|
|
SqlDateTime sqlDateTime;
|
|
TdsDateTime tdsDateTime = new TdsDateTime();
|
|
|
|
Debug.Assert(cb == 8 || cb == 4, "Invalid date time size!");
|
|
|
|
if (cb == 8) {
|
|
sqlDateTime = new SqlDateTime(dateTime);
|
|
tdsDateTime.time = sqlDateTime.TimeTicks;
|
|
}
|
|
else {
|
|
// note that smalldatetime is days&minutes.
|
|
// Adding 30 seconds ensures proper roundup if the seconds are >= 30
|
|
// The AddSeconds function handles eventual carryover
|
|
sqlDateTime = new SqlDateTime(dateTime.AddSeconds(30));
|
|
tdsDateTime.time = sqlDateTime.TimeTicks / SqlDateTime.SQLTicksPerMinute;
|
|
}
|
|
tdsDateTime.days = sqlDateTime.DayTicks;
|
|
return tdsDateTime;
|
|
}
|
|
|
|
|
|
public static DateTime ToDateTime(int sqlDays, int sqlTime, int length) {
|
|
if (length == 4) {
|
|
return new SqlDateTime(sqlDays, sqlTime * SqlDateTime.SQLTicksPerMinute).Value;
|
|
}
|
|
else {
|
|
Debug.Assert(length == 8, "invalid length for DateTime");
|
|
return new SqlDateTime(sqlDays, sqlTime).Value;
|
|
}
|
|
}
|
|
|
|
internal static int GetTimeSizeFromScale(byte scale)
|
|
{
|
|
// Disable the assert here since we do not properly handle wrong Scale value on the parameter,
|
|
// see VSTFDEVDIV 795578 for more details.
|
|
// But, this assert is still valid when we receive Time/DateTime2/DateTimeOffset scale from server over TDS,
|
|
// so it is moved to TdsParser.CommonProcessMetaData.
|
|
// For new scenarios, assert and/or validate the scale value before this call!
|
|
// Debug.Assert(0 <= scale && scale <= 7);
|
|
|
|
if (scale <= 2)
|
|
return 3;
|
|
|
|
if (scale <= 4)
|
|
return 4;
|
|
|
|
return 5;
|
|
}
|
|
|
|
//
|
|
// please leave string sorted alphabetically
|
|
// note that these names should only be used in the context of parameters. We always send over BIG* and nullable types for SQL Server
|
|
//
|
|
private static class MetaTypeName {
|
|
public const string BIGINT = "bigint";
|
|
public const string BINARY = "binary";
|
|
public const string BIT = "bit";
|
|
public const string CHAR = "char";
|
|
public const string DATETIME = "datetime";
|
|
public const string DECIMAL = "decimal";
|
|
public const string FLOAT = "float";
|
|
public const string IMAGE = "image";
|
|
public const string INT = "int";
|
|
public const string MONEY = "money";
|
|
public const string NCHAR = "nchar";
|
|
public const string NTEXT = "ntext";
|
|
public const string NVARCHAR = "nvarchar";
|
|
public const string REAL = "real";
|
|
public const string ROWGUID = "uniqueidentifier";
|
|
public const string SMALLDATETIME = "smalldatetime";
|
|
public const string SMALLINT = "smallint";
|
|
public const string SMALLMONEY = "smallmoney";
|
|
public const string TEXT = "text";
|
|
public const string TIMESTAMP = "timestamp";
|
|
public const string TINYINT = "tinyint";
|
|
public const string UDT = "udt";
|
|
public const string VARBINARY = "varbinary";
|
|
public const string VARCHAR = "varchar";
|
|
public const string VARIANT = "sql_variant";
|
|
public const string XML = "xml";
|
|
public const string TABLE = "table";
|
|
public const string DATE = "date";
|
|
public const string TIME = "time";
|
|
public const string DATETIME2 = "datetime2";
|
|
public const string DATETIMEOFFSET = "datetimeoffset";
|
|
}
|
|
}
|
|
|
|
//
|
|
// note: it is the client's responsibility to know what size date time he is working with
|
|
//
|
|
internal struct TdsDateTime {
|
|
public int days; // offset in days from 1/1/1900
|
|
// private UInt32 time; // if smalldatetime, this is # of minutes since midnight
|
|
// otherwise: # of 1/300th of a second since midnight
|
|
public int time; //
|
|
}
|
|
|
|
}
|
|
|