diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 1bd80ed583..b3d906dd49 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -322,6 +322,9 @@ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs + Microsoft\Data\SqlClient\SignatureVerificationCache.cs @@ -484,7 +487,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index c88a172035..129a571e2f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -234,6 +234,12 @@ Microsoft\Data\SqlClient\Server\SmiMetaData.cs + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs + + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.netfx.cs + Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs @@ -590,7 +596,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs deleted file mode 100644 index 28bc1ae376..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs +++ /dev/null @@ -1,4420 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Reflection; -using System.Xml; -using Microsoft.Data.Common; -using Microsoft.Data.SqlTypes; - -namespace Microsoft.Data.SqlClient.Server -{ - // Utilities for manipulating values with the Smi interface. - // - // THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT! - // - // These are all based off of knowing the clr type of the value - // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). - internal static class ValueUtilsSmi - { - private const int __maxByteChunkSize = TdsEnums.MAXSIZE; - private const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char); - private const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator; // make sure we use the same constant - - // Constants - private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream - private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader - - // - // User-visible semantics-laden Getter/Setter support methods - // These methods implement common semantics for getters & setters - // All access to underlying Smi getters/setters must validate parameters - // in these methods - // - - // The idea for the getters is that there are two types associated with the field/column, - // the one the user asks for (implicitly via a strongly-typed getter) and the one the data - // is stored in (SmiMetaData). - // When a strong getter is invoked, we try one of two ways to get the value - // 1) go directly to the source for the requested type if possible - // 2) instantiate the value based on the stored type (GetValue), then ask the Clr - // to convert. - internal static bool IsDBNull(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - return IsDBNull_Unchecked(sink, getters, ordinal); - } - - internal static bool GetBoolean(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Boolean)) - { - return GetBoolean_Unchecked(sink, getters, ordinal); - } - - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (bool)result; - } - - internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Byte)) - { - return GetByte_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (byte)result; - } - - private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - SqlBinary value = (SqlBinary)obj; - - if (value.IsNull) - { - if (throwOnNull) - { - throw SQL.SqlNullValue(); - } - else - { - // return zero length in any case - return 0; - } - } - - if (null == buffer) - { - return value.Length; - } - - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, - fieldOffset, buffer.Length, bufferOffset, length); - Array.Copy(value.Value, checked((int)fieldOffset), buffer, bufferOffset, length); - return length; - } - - internal static long GetBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiExtendedMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - // Additional exclusions not caught by GetBytesInternal - if ((SmiMetaData.UnlimitedMaxLengthIndicator != metaData.MaxLength && - (SqlDbType.VarChar == metaData.SqlDbType || - SqlDbType.NVarChar == metaData.SqlDbType || - SqlDbType.Char == metaData.SqlDbType || - SqlDbType.NChar == metaData.SqlDbType)) || - SqlDbType.Xml == metaData.SqlDbType) - { - throw SQL.NonBlobColumn(metaData.Name); - } - else - { - return GetBytesInternal(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull); - } - } - - internal static long GetBytesInternal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.ByteArray)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (throwOnNull) - { - throw SQL.SqlNullValue(); - } - else - { - // check user's parameters for validity against a zero-length value - CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, 0, fieldOffset, buffer.Length, bufferOffset, length); - - // return zero length in any case - return 0; - } - } - long actualLength = GetBytesLength_Unchecked(sink, getters, ordinal); - if (null == buffer) - { - return actualLength; - } - if (MetaDataUtilsSmi.IsCharOrXmlType(metaData.SqlDbType)) - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), actualLength, - fieldOffset, buffer.Length, bufferOffset, length); - } - else - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length); - } - Debug.Assert(length >= 0, "Invalid CheckXetParameters return length!"); - if (length > 0) - { - length = GetBytes_Unchecked(sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - return length; - } - - return GetBytesConversion(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull); - } - - internal static long GetChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.CharArray)) - { - long actualLength = GetCharsLength_Unchecked(sink, getters, ordinal); - if (null == buffer) - { - return actualLength; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (length > 0) - { - length = GetChars_Unchecked(sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - return length; - } - - string value = ((string)GetValue(sink, getters, ordinal, metaData, null)); - if (null == value) - { - throw ADP.InvalidCast(); - } - if (null == buffer) - { - return value.Length; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, - fieldOffset, buffer.Length, bufferOffset, length); - value.CopyTo(checked((int)fieldOffset), buffer, bufferOffset, length); - return length; - } - - internal static DateTime GetDateTime(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.DateTime)) - { - return GetDateTime_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (DateTime)result; - } - - // calling GetDateTimeOffset on possibly v100 SMI - internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) - { - if (gettersSupportKatmaiDateTime) - { - return GetDateTimeOffset(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); - } - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (DateTimeOffset)result; - } - - // dealing with v200 SMI - internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.DateTimeOffset)) - { - return GetDateTimeOffset_Unchecked(sink, getters, ordinal); - } - return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData, null); - } - - internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Decimal)) - { - return GetDecimal_PossiblyMoney(sink, getters, ordinal, metaData); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (decimal)result; - } - - internal static double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Double)) - { - return GetDouble_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (double)result; - } - - internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Guid)) - { - return GetGuid_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (Guid)result; - } - - internal static short GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int16)) - { - return GetInt16_Unchecked(sink, getters, ordinal); - } - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (short)obj; - } - - internal static int GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int32)) - { - return GetInt32_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (int)result; - } - - internal static long GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int64)) - { - return GetInt64_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (long)result; - } - - internal static float GetSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Single)) - { - return GetSingle_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (float)result; - } - - internal static SqlBinary GetSqlBinary(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBinary)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlBinary.Null; - } - return GetSqlBinary_Unchecked(sink, getters, ordinal); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlBinary)result; - } - - internal static SqlBoolean GetSqlBoolean(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBoolean)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlBoolean.Null; - } - return new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlBoolean)result; - } - - internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlByte)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlByte.Null; - } - return new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlByte)result; - } - - internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlBytes result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBytes)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlBytes.Null; - } - else - { - long length = GetBytesLength_Unchecked(sink, getters, ordinal); - if (0 <= length && length < __maxByteChunkSize) - { - byte[] byteBuffer = GetByteArray_Unchecked(sink, getters, ordinal); - result = new SqlBytes(byteBuffer); - } - else - { - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - s = CopyIntoNewSmiScratchStream(s, sink, context); - result = new SqlBytes(s); - } - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - SqlBinary binaryVal = (SqlBinary)obj; - if (binaryVal.IsNull) - { - result = SqlBytes.Null; - } - else - { - result = new SqlBytes(binaryVal.Value); - } - } - - return result; - } - - internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlChars result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlChars)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlChars.Null; - } - else - { - long length = GetCharsLength_Unchecked(sink, getters, ordinal); - if (length < __maxCharChunkSize || !InOutOfProcHelper.InProc) - { - char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); - result = new SqlChars(charBuffer); - } - else - { // InProc only - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars(s, sink, context); - - Type SqlCharsType = (typeof(SqlChars)); - Type[] argTypes = new Type[] { typeof(SqlStreamChars) }; - SqlChars SqlCharsInstance = (SqlChars)SqlCharsType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, - null, argTypes, null).Invoke(new Object[] { sc }); - result = SqlCharsInstance; - } - } - } - else - { - SqlString stringValue; - if (SqlDbType.Xml == metaData.SqlDbType) - { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal, null); - - if (xmlValue.IsNull) - { - result = SqlChars.Null; - } - else - { - result = new SqlChars(xmlValue.Value.ToCharArray()); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - stringValue = (SqlString)obj; - - if (stringValue.IsNull) - { - result = SqlChars.Null; - } - else - { - result = new SqlChars(stringValue.Value.ToCharArray()); - } - } - } - - return result; - } - - internal static SqlDateTime GetSqlDateTime(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDateTime result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDateTime)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDateTime.Null; - } - else - { - DateTime temp = GetDateTime_Unchecked(sink, getters, ordinal); - result = new SqlDateTime(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDateTime)obj; - } - - return result; - } - - internal static SqlDecimal GetSqlDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDecimal result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDecimal)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDecimal.Null; - } - else - { - result = GetSqlDecimal_Unchecked(sink, getters, ordinal); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDecimal)obj; - } - - return result; - } - - internal static SqlDouble GetSqlDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDouble result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDouble)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDouble.Null; - } - else - { - double temp = GetDouble_Unchecked(sink, getters, ordinal); - result = new SqlDouble(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDouble)obj; - } - - return result; - } - - internal static SqlGuid GetSqlGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlGuid result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlGuid)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlGuid.Null; - } - else - { - Guid temp = GetGuid_Unchecked(sink, getters, ordinal); - result = new SqlGuid(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlGuid)obj; - } - - return result; - } - - internal static SqlInt16 GetSqlInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt16 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt16)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt16.Null; - } - else - { - short temp = GetInt16_Unchecked(sink, getters, ordinal); - result = new SqlInt16(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt16)obj; - } - - return result; - } - - internal static SqlInt32 GetSqlInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt32 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt32)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt32.Null; - } - else - { - int temp = GetInt32_Unchecked(sink, getters, ordinal); - result = new SqlInt32(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt32)obj; - } - return result; - } - - internal static SqlInt64 GetSqlInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt64 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt64)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt64.Null; - } - else - { - long temp = GetInt64_Unchecked(sink, getters, ordinal); - result = new SqlInt64(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt64)obj; - } - - return result; - } - - internal static SqlMoney GetSqlMoney(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlMoney result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlMoney)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlMoney.Null; - } - else - { - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlMoney)obj; - } - - return result; - } - - internal static SqlSingle GetSqlSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlSingle result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlSingle)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlSingle.Null; - } - else - { - float temp = GetSingle_Unchecked(sink, getters, ordinal); - result = new SqlSingle(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlSingle)obj; - } - - return result; - } - - internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlString result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlString)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlString.Null; - } - else - { - string temp = GetString_Unchecked(sink, getters, ordinal); - result = new SqlString(temp); - } - } - else if (SqlDbType.Xml == metaData.SqlDbType) - { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal, null); - - if (xmlValue.IsNull) - { - result = SqlString.Null; - } - else - { - result = new SqlString(xmlValue.Value); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlString)obj; - } - - return result; - } - - internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlXml result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlXml)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlXml.Null; - } - else - { - result = GetSqlXml_Unchecked(sink, getters, ordinal, context); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlXml)obj; - } - - return result; - } - - internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.String)) - { - return GetString_Unchecked(sink, getters, ordinal); - } - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (string)obj; - } - - internal static SqlSequentialStreamSmi GetSequentialStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) - { - Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialStreamSmi on a null column"); - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if ((!bypassTypeCheck) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) - { - throw ADP.InvalidCast(); - } - - // This will advance the column to ordinal - long length = GetBytesLength_Unchecked(sink, getters, ordinal); - return new SqlSequentialStreamSmi(sink, getters, ordinal, length); - } - - internal static SqlSequentialTextReaderSmi GetSequentialTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column"); - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader)) - { - throw ADP.InvalidCast(); - } - - // This will advance the column to ordinal - long length = GetCharsLength_Unchecked(sink, getters, ordinal); - return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length); - } - - internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) - { - bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); - - // If a sql_variant, get the internal type - if (!bypassTypeCheck) - { - if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) - { - metaData = getters.GetVariantType(sink, ordinal); - } - // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast - if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) - { - throw ADP.InvalidCast(); - } - } - - byte[] data; - if (isDbNull) - { - // "null" stream - data = new byte[0]; - } - else - { - // Read all data - data = GetByteArray_Unchecked(sink, getters, ordinal); - } - - // Wrap data in pre-built object - return new MemoryStream(data, writable: false); - } - - internal static TextReader GetTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); - - // If a sql_variant, get the internal type - if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) - { - metaData = getters.GetVariantType(sink, ordinal); - } - // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast - if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) - { - throw ADP.InvalidCast(); - } - - string data; - if (isDbNull) - { - // "null" textreader - data = string.Empty; - } - else - { - // Read all data - data = GetString_Unchecked(sink, getters, ordinal); - } - - // Wrap in pre-built object - return new StringReader(data); - } - - // calling GetTimeSpan on possibly v100 SMI - internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) - { - if (gettersSupportKatmaiDateTime) - { - return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); - } - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (TimeSpan)obj; - } - - // dealing with v200 SMI - internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TimeSpan)) - { - return GetTimeSpan_Unchecked(sink, getters, ordinal); - } - return (TimeSpan)GetValue200(sink, getters, ordinal, metaData, null); - } - - // GetValue() for v200 SMI (new Katmai Date/Time types) - internal static object GetValue200( - SmiEventSink_Default sink, - SmiTypedGetterSetter getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = DBNull.Value; - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue200(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Time: - result = GetTimeSpan_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTimeOffset: - result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); - break; - default: - result = GetValue(sink, getters, ordinal, metaData, context); - break; - } - } - - return result; - } - - // implements SqlClient 1.1-compatible GetValue() semantics for everything except output parameters - internal static object GetValue( - SmiEventSink_Default sink, - ITypedGettersV3 getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = DBNull.Value; - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - result = GetInt64_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Binary: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - result = GetBoolean_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Char: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTime: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Decimal: - result = GetSqlDecimal_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.Float: - result = GetDouble_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Image: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - result = GetInt32_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Money: - result = GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.NChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NText: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NVarChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Real: - result = GetSingle_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.UniqueIdentifier: - result = GetGuid_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallDateTime: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallInt: - result = GetInt16_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallMoney: - result = GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.Text: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Timestamp: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - result = GetByte_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarBinary: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Variant: - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal, context).Value; - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - } - } - - return result; - } - - // dealing with v200 SMI - internal static object GetSqlValue200( - SmiEventSink_Default sink, - SmiTypedGetterSetter getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType]; - } - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue200(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Time: - result = GetTimeSpan_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTimeOffset: - result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); - break; - default: - result = GetSqlValue(sink, getters, ordinal, metaData, context); - break; - } - } - - return result; - } - - // implements SqlClient 1.1-compatible GetSqlValue() semantics for everything except output parameters - internal static object GetSqlValue( - SmiEventSink_Default sink, - ITypedGettersV3 getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType]; - } - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - result = new SqlInt64(GetInt64_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Binary: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - result = new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Char: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime: - result = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Decimal: - result = GetSqlDecimal_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Float: - result = new SqlDouble(GetDouble_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Image: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - result = new SqlInt32(GetInt32_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Money: - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.NText: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.NVarChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Real: - result = new SqlSingle(GetSingle_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.UniqueIdentifier: - result = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallDateTime: - result = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallInt: - result = new SqlInt16(GetInt16_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallMoney: - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Text: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Timestamp: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - result = new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.VarBinary: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Variant: - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal, context); - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - } - } - - return result; - } - - // null return values for SqlClient 1.1-compatible GetSqlValue() - private static object[] s_typeSpecificNullForSqlValue = { - SqlInt64.Null, // SqlDbType.BigInt - SqlBinary.Null, // SqlDbType.Binary - SqlBoolean.Null, // SqlDbType.Bit - SqlString.Null, // SqlDbType.Char - SqlDateTime.Null, // SqlDbType.DateTime - SqlDecimal.Null, // SqlDbType.Decimal - SqlDouble.Null, // SqlDbType.Float - SqlBinary.Null, // SqlDbType.Image - SqlInt32.Null, // SqlDbType.Int - SqlMoney.Null, // SqlDbType.Money - SqlString.Null, // SqlDbType.NChar - SqlString.Null, // SqlDbType.NText - SqlString.Null, // SqlDbType.NVarChar - SqlSingle.Null, // SqlDbType.Real - SqlGuid.Null, // SqlDbType.UniqueIdentifier - SqlDateTime.Null, // SqlDbType.SmallDateTime - SqlInt16.Null, // SqlDbType.SmallInt - SqlMoney.Null, // SqlDbType.SmallMoney - SqlString.Null, // SqlDbType.Text - SqlBinary.Null, // SqlDbType.Timestamp - SqlByte.Null, // SqlDbType.TinyInt - SqlBinary.Null, // SqlDbType.VarBinary - SqlString.Null, // SqlDbType.VarChar - DBNull.Value, // SqlDbType.Variant - null, // 24 - SqlXml.Null, // SqlDbType.Xml - null, // 26 - null, // 27 - null, // 28 - null, // SqlDbType.Udt -- requires instantiating udt-specific type - null, // SqlDbType.Structured - DBNull.Value, // SqlDbType.Date - DBNull.Value, // SqlDbType.Time - DBNull.Value, // SqlDbType.DateTime2 - DBNull.Value, // SqlDbType.DateTimeOffset - }; - - internal static object NullUdtInstance(SmiMetaData metaData) - { - Type t = metaData.Type; - Debug.Assert(t != null, "Unexpected null of Udt type on NullUdtInstance!"); - return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[] { }, CultureInfo.InvariantCulture); - } - - internal static SqlBuffer.StorageType SqlDbTypeToStorageType(SqlDbType dbType) - { - int index = unchecked((int)dbType); - Debug.Assert(index >= 0 && index < __dbTypeToStorageType.Length, string.Format(CultureInfo.InvariantCulture, "Unexpected dbType value: {0}", dbType)); - return __dbTypeToStorageType[index]; - } - - private static void GetNullOutputParameterSmi(SmiMetaData metaData, SqlBuffer targetBuffer, ref object result) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - SqlBuffer.StorageType stype = SqlDbTypeToStorageType(metaData.SqlDbType); - if (SqlBuffer.StorageType.Empty == stype) - { - result = DBNull.Value; - } - else if (SqlBuffer.StorageType.SqlBinary == stype) - { - // special case SqlBinary, 'cause tds parser never sets SqlBuffer to null, just to empty! - targetBuffer.SqlBinary = SqlBinary.Null; - } - else if (SqlBuffer.StorageType.SqlGuid == stype) - { - targetBuffer.SqlGuid = SqlGuid.Null; - } - else - { - targetBuffer.SetToNullOfType(stype); - } - } - } - - // UDTs and null variants come back via return value, all else is via targetBuffer. - // implements SqlClient 2.0-compatible output parameter semantics - internal static object GetOutputParameterV3Smi( - SmiEventSink_Default sink, // event sink for errors - ITypedGettersV3 getters, // getters interface to grab value from - int ordinal, // parameter within getters - SmiMetaData metaData, // Getter's type for this ordinal - SmiContext context, // used to obtain scratch streams - SqlBuffer targetBuffer // destination - ) - { - object result = null; // Workaround for UDT hack in non-Smi code paths. - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - GetNullOutputParameterSmi(metaData, targetBuffer, ref result); - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - targetBuffer.Int64 = GetInt64_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Binary: - case SqlDbType.Image: - case SqlDbType.Timestamp: - case SqlDbType.VarBinary: - targetBuffer.SqlBinary = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - targetBuffer.Boolean = GetBoolean_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - case SqlDbType.Char: - case SqlDbType.VarChar: - case SqlDbType.Text: - targetBuffer.SetToString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime: - case SqlDbType.SmallDateTime: - { - SqlDateTime dt = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - targetBuffer.SetToDateTime(dt.DayTicks, dt.TimeTicks); - break; - } - case SqlDbType.Decimal: - { - SqlDecimal dec = GetSqlDecimal_Unchecked(sink, getters, ordinal); - targetBuffer.SetToDecimal(dec.Precision, dec.Scale, dec.IsPositive, dec.Data); - break; - } - case SqlDbType.Float: - targetBuffer.Double = GetDouble_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - targetBuffer.Int32 = GetInt32_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Money: - case SqlDbType.SmallMoney: - targetBuffer.SetToMoney(GetInt64_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Real: - targetBuffer.Single = GetSingle_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.UniqueIdentifier: - targetBuffer.SqlGuid = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallInt: - targetBuffer.Int16 = GetInt16_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - targetBuffer.Byte = GetByte_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Variant: - // For variants, recur using the current value's sqldbtype - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); - GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - case SqlDbType.Xml: - targetBuffer.SqlXml = GetSqlXml_Unchecked(sink, getters, ordinal, null); - break; - default: - Debug.Assert(false, "Unexpected SqlDbType"); - break; - } - } - - return result; - } - - // UDTs and null variants come back via return value, all else is via targetBuffer. - // implements SqlClient 1.1-compatible output parameter semantics - internal static object GetOutputParameterV200Smi( - SmiEventSink_Default sink, // event sink for errors - SmiTypedGetterSetter getters, // getters interface to grab value from - int ordinal, // parameter within getters - SmiMetaData metaData, // Getter's type for this ordinal - SmiContext context, // used to obtain scratch streams - SqlBuffer targetBuffer // destination - ) - { - object result = null; // Workaround for UDT hack in non-Smi code paths. - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - GetNullOutputParameterSmi(metaData, targetBuffer, ref result); - } - else - { - switch (metaData.SqlDbType) - { - // new types go here - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - // For variants, recur using the current value's sqldbtype - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); - GetOutputParameterV200Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - case SqlDbType.Date: - targetBuffer.SetToDate(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime2: - targetBuffer.SetToDateTime2(GetDateTime_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - case SqlDbType.Time: - targetBuffer.SetToTime(GetTimeSpan_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - case SqlDbType.DateTimeOffset: - targetBuffer.SetToDateTimeOffset(GetDateTimeOffset_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - default: - result = GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - } - } - - return result; - } - - private static SqlBuffer.StorageType[] __dbTypeToStorageType = new SqlBuffer.StorageType[] { - SqlBuffer.StorageType.Int64, // BigInt - SqlBuffer.StorageType.SqlBinary, // Binary - SqlBuffer.StorageType.Boolean, // Bit - SqlBuffer.StorageType.String, // Char - SqlBuffer.StorageType.DateTime, // DateTime - SqlBuffer.StorageType.Decimal, // Decimal - SqlBuffer.StorageType.Double, // Float - SqlBuffer.StorageType.SqlBinary, // Image - SqlBuffer.StorageType.Int32, // Int - SqlBuffer.StorageType.Money, // Money - SqlBuffer.StorageType.String, // NChar - SqlBuffer.StorageType.String, // NText - SqlBuffer.StorageType.String, // NVarChar - SqlBuffer.StorageType.Single, // Real - SqlBuffer.StorageType.SqlGuid, // UniqueIdentifier - SqlBuffer.StorageType.DateTime, // SmallDateTime - SqlBuffer.StorageType.Int16, // SmallInt - SqlBuffer.StorageType.Money, // SmallMoney - SqlBuffer.StorageType.String, // Text - SqlBuffer.StorageType.SqlBinary, // Timestamp - SqlBuffer.StorageType.Byte, // TinyInt - SqlBuffer.StorageType.SqlBinary, // VarBinary - SqlBuffer.StorageType.String, // VarChar - SqlBuffer.StorageType.Empty, // Variant - SqlBuffer.StorageType.Empty, // 24 - SqlBuffer.StorageType.SqlXml, // Xml - SqlBuffer.StorageType.Empty, // 26 - SqlBuffer.StorageType.Empty, // 27 - SqlBuffer.StorageType.Empty, // 28 - SqlBuffer.StorageType.Empty, // Udt - SqlBuffer.StorageType.Empty, // Structured - SqlBuffer.StorageType.Date, // Date - SqlBuffer.StorageType.Time, // Time - SqlBuffer.StorageType.DateTime2, // DateTime2 - SqlBuffer.StorageType.DateTimeOffset, // DateTimeOffset - }; - - // Strongly-typed setters are a bit simpler than their corresponding getters. - // 1) check to make sure the type is compatible (exception if not) - // 2) push the data - internal static void SetDBNull(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, bool value) - { - SetDBNull_Unchecked(sink, setters, ordinal); - } - - internal static void SetBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, bool value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Boolean); - - SetBoolean_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Byte); - - SetByte_Unchecked(sink, setters, ordinal, value); - } - - internal static long SetBytes(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.ByteArray); - if (null == buffer) - { - throw ADP.ArgumentNull(nameof(buffer)); - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (0 == length) - { - // Front end semantics says to ignore fieldOffset and bufferOffset - // if not doing any actual work. - // Back end semantics says they must be valid, even for no work. - // Compensate by setting offsets to zero here (valid for any scenario) - fieldOffset = 0; - bufferOffset = 0; - } - return SetBytes_Unchecked(sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - - internal static long SetBytesLength(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.ByteArray); - - if (length < 0) - { - throw ADP.InvalidDataLength(length); - } - - if (metaData.MaxLength >= 0 && length > metaData.MaxLength) - { - length = metaData.MaxLength; - } - - setters.SetBytesLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - - return length; - } - - internal static long SetChars(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.CharArray); - if (null == buffer) - { - throw ADP.ArgumentNull(nameof(buffer)); - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (0 == length) - { - // Front end semantics says to ignore fieldOffset and bufferOffset - // if not doing any actual work. - // Back end semantics says they must be valid, even for no work. - // Compensate by setting offsets to zero here (valid for any scenario) - fieldOffset = 0; - bufferOffset = 0; - } - return SetChars_Unchecked(sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - - internal static void SetDateTime(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTime); - - SetDateTime_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value, bool settersSupportKatmaiDateTime) - { - if (!settersSupportKatmaiDateTime) - { - throw ADP.InvalidCast(); - } - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTimeOffset); - SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value); - } - - internal static void SetDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, decimal value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Decimal); - - SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, value); - } - - internal static void SetDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, double value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Double); - - SetDouble_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetGuid(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Guid value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Guid); - - SetGuid_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, short value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int16); - - SetInt16_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, int value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int32); - - SetInt32_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int64); - - SetInt64_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, float value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Single); - - SetSingle_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlBinary(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBinary); - SetSqlBinary_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBoolean value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBoolean); - - SetSqlBoolean_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlByte value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlByte); - - SetSqlByte_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlBytes(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBytes); - - SetSqlBytes_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlChars(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlChars); - SetSqlChars_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlDateTime(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDateTime); - - SetSqlDateTime_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetSqlDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDecimal value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDecimal); - - SetSqlDecimal_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDouble value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDouble); - - SetSqlDouble_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlGuid(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlGuid value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlGuid); - - SetSqlGuid_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt16 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt16); - - SetSqlInt16_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt32 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt32); - - SetSqlInt32_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt64 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt64); - - SetSqlInt64_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlMoney(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlMoney); - - SetSqlMoney_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetSqlSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlSingle value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlSingle); - - SetSqlSingle_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlString); - SetSqlString_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlXml(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlXml value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlXml); - - SetSqlXml_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.String); - - SetString_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value, bool settersSupportKatmaiDateTime) - { - if (!settersSupportKatmaiDateTime) - { - throw ADP.InvalidCast(); - } - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.TimeSpan); - SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, value); - } - - // Implements SqlClient 2.0-compatible SetValue() semantics - // Assumes caller already validated type against the metadata, other than trimming lengths - internal static void SetCompatibleValue( - SmiEventSink_Default sink, - ITypedSettersV3 setters, - int ordinal, - SmiMetaData metaData, // metadata for target setter column - object value, - ExtendedClrTypeCode typeCode, - int offset - ) - { - // Ensure either an invalid type, or caller validated compatibility - // SqlDbType.Variant and have special handling - Debug.Assert(typeCode == ExtendedClrTypeCode.Invalid || - typeCode == ExtendedClrTypeCode.SByte || - typeCode == ExtendedClrTypeCode.UInt16 || - typeCode == ExtendedClrTypeCode.UInt32 || - typeCode == ExtendedClrTypeCode.UInt64 || - typeCode == ExtendedClrTypeCode.DBNull || - typeCode == ExtendedClrTypeCode.Empty || - CanAccessSetterDirectly(metaData, typeCode) || - value is DataFeed /* already validated */); - - switch (typeCode) - { - case ExtendedClrTypeCode.Invalid: - throw ADP.UnknownDataType(value.GetType()); - case ExtendedClrTypeCode.Boolean: - SetBoolean_Unchecked(sink, setters, ordinal, (bool)value); - break; - case ExtendedClrTypeCode.Byte: - SetByte_Unchecked(sink, setters, ordinal, (byte)value); - break; - case ExtendedClrTypeCode.Char: - { - char[] charsValue = new char[] { (char)value }; - // recur with array type - SetCompatibleValue(sink, setters, ordinal, metaData, charsValue, ExtendedClrTypeCode.CharArray, 0); - break; - } - case ExtendedClrTypeCode.DateTime: - SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value); - break; - case ExtendedClrTypeCode.DBNull: - SetDBNull_Unchecked(sink, setters, ordinal); - break; - case ExtendedClrTypeCode.Decimal: - SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, (decimal)value); - break; - case ExtendedClrTypeCode.Double: - SetDouble_Unchecked(sink, setters, ordinal, (double)value); - break; - case ExtendedClrTypeCode.Empty: - SetDBNull_Unchecked(sink, setters, ordinal); - break; - case ExtendedClrTypeCode.Int16: - SetInt16_Unchecked(sink, setters, ordinal, (short)value); - break; - case ExtendedClrTypeCode.Int32: - SetInt32_Unchecked(sink, setters, ordinal, (int)value); - break; - case ExtendedClrTypeCode.Int64: - SetInt64_Unchecked(sink, setters, ordinal, (long)value); - break; - case ExtendedClrTypeCode.SByte: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.Single: - SetSingle_Unchecked(sink, setters, ordinal, (float)value); - break; - case ExtendedClrTypeCode.String: - SetString_LengthChecked(sink, setters, ordinal, metaData, (string)value, offset); - break; - case ExtendedClrTypeCode.UInt16: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.UInt32: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.UInt64: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.Object: - SetUdt_LengthChecked(sink, setters, ordinal, metaData, value); - break; - case ExtendedClrTypeCode.ByteArray: - SetByteArray_LengthChecked(sink, setters, ordinal, metaData, (byte[])value, offset); - break; - case ExtendedClrTypeCode.CharArray: - SetCharArray_LengthChecked(sink, setters, ordinal, metaData, (char[])value, offset); - break; - case ExtendedClrTypeCode.Guid: - SetGuid_Unchecked(sink, setters, ordinal, (Guid)value); - break; - case ExtendedClrTypeCode.SqlBinary: - SetSqlBinary_LengthChecked(sink, setters, ordinal, metaData, (SqlBinary)value, offset); - break; - case ExtendedClrTypeCode.SqlBoolean: - SetSqlBoolean_Unchecked(sink, setters, ordinal, (SqlBoolean)value); - break; - case ExtendedClrTypeCode.SqlByte: - SetSqlByte_Unchecked(sink, setters, ordinal, (SqlByte)value); - break; - case ExtendedClrTypeCode.SqlDateTime: - SetSqlDateTime_Checked(sink, setters, ordinal, metaData, (SqlDateTime)value); - break; - case ExtendedClrTypeCode.SqlDouble: - SetSqlDouble_Unchecked(sink, setters, ordinal, (SqlDouble)value); - break; - case ExtendedClrTypeCode.SqlGuid: - SetSqlGuid_Unchecked(sink, setters, ordinal, (SqlGuid)value); - break; - case ExtendedClrTypeCode.SqlInt16: - SetSqlInt16_Unchecked(sink, setters, ordinal, (SqlInt16)value); - break; - case ExtendedClrTypeCode.SqlInt32: - SetSqlInt32_Unchecked(sink, setters, ordinal, (SqlInt32)value); - break; - case ExtendedClrTypeCode.SqlInt64: - SetSqlInt64_Unchecked(sink, setters, ordinal, (SqlInt64)value); - break; - case ExtendedClrTypeCode.SqlMoney: - SetSqlMoney_Checked(sink, setters, ordinal, metaData, (SqlMoney)value); - break; - case ExtendedClrTypeCode.SqlDecimal: - SetSqlDecimal_Unchecked(sink, setters, ordinal, (SqlDecimal)value); - break; - case ExtendedClrTypeCode.SqlSingle: - SetSqlSingle_Unchecked(sink, setters, ordinal, (SqlSingle)value); - break; - case ExtendedClrTypeCode.SqlString: - SetSqlString_LengthChecked(sink, setters, ordinal, metaData, (SqlString)value, offset); - break; - case ExtendedClrTypeCode.SqlChars: - SetSqlChars_LengthChecked(sink, setters, ordinal, metaData, (SqlChars)value, offset); - break; - case ExtendedClrTypeCode.SqlBytes: - SetSqlBytes_LengthChecked(sink, setters, ordinal, metaData, (SqlBytes)value, offset); - break; - case ExtendedClrTypeCode.SqlXml: - SetSqlXml_Unchecked(sink, setters, ordinal, (SqlXml)value); - break; - case ExtendedClrTypeCode.Stream: - SetStream_Unchecked(sink, setters, ordinal, metaData, (StreamDataFeed)value); - break; - case ExtendedClrTypeCode.TextReader: - SetTextReader_Unchecked(sink, setters, ordinal, metaData, (TextDataFeed)value); - break; - case ExtendedClrTypeCode.XmlReader: - SetXmlReader_Unchecked(sink, setters, ordinal, ((XmlDataFeed)value)._source); - break; - default: - Debug.Fail("Unvalidated extendedtypecode: " + typeCode); - break; - } - } - - // VSTFDevDiv#479681 - Data corruption when sending Katmai Date types to the server via TVP - // Ensures proper handling on DateTime2 sub type for Sql_Variants and TVPs. - internal static void SetCompatibleValueV200( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - object value, - ExtendedClrTypeCode typeCode, - int offset, - int length, - ParameterPeekAheadValue peekAhead, - SqlBuffer.StorageType storageType - ) - { - // Ensure caller validated compatibility for types handled directly in this method - Debug.Assert((ExtendedClrTypeCode.DataTable != typeCode && - ExtendedClrTypeCode.DbDataReader != typeCode && - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) || - CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType); - - if (typeCode == ExtendedClrTypeCode.DateTime) - { - if (storageType == SqlBuffer.StorageType.DateTime2) - SetDateTime2_Checked(sink, setters, ordinal, metaData, (DateTime)value); - else if (storageType == SqlBuffer.StorageType.Date) - SetDate_Checked(sink, setters, ordinal, metaData, (DateTime)value); - else - SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value); - } - else - { - SetCompatibleValueV200(sink, setters, ordinal, metaData, value, typeCode, offset, length, peekAhead); - } - } - - // Implements SqlClient 2.0-compatible SetValue() semantics + Orcas extensions - // Assumes caller already validated basic type against the metadata, other than trimming lengths and - // checking individual field values (TVPs) - internal static void SetCompatibleValueV200( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - object value, - ExtendedClrTypeCode typeCode, - int offset, - int length, - ParameterPeekAheadValue peekAhead - ) - { - // Ensure caller validated compatibility for types handled directly in this method - Debug.Assert((ExtendedClrTypeCode.DataTable != typeCode && - ExtendedClrTypeCode.DbDataReader != typeCode && - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) || - CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType); - - switch (typeCode) - { - case ExtendedClrTypeCode.DataTable: - SetDataTable_Unchecked(sink, setters, ordinal, metaData, (DataTable)value); - break; - case ExtendedClrTypeCode.DbDataReader: - SetDbDataReader_Unchecked(sink, setters, ordinal, metaData, (DbDataReader)value); - break; - case ExtendedClrTypeCode.IEnumerableOfSqlDataRecord: - SetIEnumerableOfSqlDataRecord_Unchecked(sink, setters, ordinal, metaData, (IEnumerable)value, peekAhead); - break; - case ExtendedClrTypeCode.TimeSpan: - SetTimeSpan_Checked(sink, setters, ordinal, metaData, (TimeSpan)value); - break; - case ExtendedClrTypeCode.DateTimeOffset: - SetDateTimeOffset_Unchecked(sink, setters, ordinal, (DateTimeOffset)value); - break; - default: - SetCompatibleValue(sink, setters, ordinal, metaData, value, typeCode, offset); - break; - } - } - - // Copy multiple fields from reader to ITypedSettersV3 - // Assumes caller enforces that reader and setter metadata are compatible - internal static void FillCompatibleITypedSettersFromReader(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataReader reader) - { - for (int i = 0; i < metaData.Length; i++) - { - if (reader.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - ValueUtilsSmi.SetInt64_Unchecked(sink, setters, i, reader.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - ValueUtilsSmi.SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, reader.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, reader.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, reader.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, reader.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], reader.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, reader.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, reader.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, reader.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], reader.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, reader.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, reader.GetSqlXml(i)); - break; - case SqlDbType.Variant: - object o = reader.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); - break; - - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - - default: - // In order for us to get here we would have to have an - // invalid instance of SqlDbType, or one would have to add - // new member to SqlDbType without adding a case in this - // switch, hence the assert. - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - // Copy multiple fields from reader to SmiTypedGetterSetter - // Supports V200 code path, without damaging backward compat for V100 code. - // Main differences are supporting DbDataReader, and for binary, character, decimal and Udt types. - // Assumes caller enforces that reader and setter metadata are compatible - internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, IList metaData, DbDataReader reader) - { - for (int i = 0; i < metaData.Count; i++) - { - if (reader.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, reader.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, reader.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Decimal: - { // block to scope sqlReader local to avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - // Support full fidelity for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) - { - SetSqlDecimal_Unchecked(sink, setters, i, sqlReader.GetSqlDecimal(i)); - } - else - { - SetSqlDecimal_Unchecked(sink, setters, i, new SqlDecimal(reader.GetDecimal(i))); - } - } - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, reader.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, reader.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i))); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, reader.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, reader.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, reader.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i))); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, reader.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Xml: - { - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) - { - SetSqlXml_Unchecked(sink, setters, i, sqlReader.GetSqlXml(i)); - } - else - { - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - } - } - break; - case SqlDbType.Variant: - { // block to scope sqlReader local and avoid conflicts - // Support better options for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - SqlBuffer.StorageType storageType = SqlBuffer.StorageType.Empty; - object o; - if (null != sqlReader) - { - o = sqlReader.GetSqlValue(i); - storageType = sqlReader.GetVariantInternalStorageType(i); - } - else - { - o = reader.GetValue(i); - } - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null, - // TODO: this version works for shipping Orcas, since only Katmai (TVP) codepath calls this method at this time. - // Need a better story for smi versioning of ValueUtilsSmi post-Orcas - SmiContextFactory.KatmaiVersion - ); - if ((storageType == SqlBuffer.StorageType.DateTime2) || (storageType == SqlBuffer.StorageType.Date)) - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null, storageType); - else - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null); - } - break; - - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - // Skip serialization for Udt types. - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - - // SqlDbType.Structured should have been caught before this point for TVPs. SUDTs will still need to implement. - - case SqlDbType.Date: - case SqlDbType.DateTime2: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Time: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataReader sqlReader = reader as SqlDataReader; - TimeSpan ts; - if (null != sqlReader) - { - ts = sqlReader.GetTimeSpan(i); - } - else - { - ts = (TimeSpan)reader.GetValue(i); - } - SetTimeSpan_Checked(sink, setters, i, metaData[i], ts); - } - break; - case SqlDbType.DateTimeOffset: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataReader sqlReader = reader as SqlDataReader; - DateTimeOffset dto; - if (null != sqlReader) - { - dto = sqlReader.GetDateTimeOffset(i); - } - else - { - dto = (DateTimeOffset)reader.GetValue(i); - } - SetDateTimeOffset_Unchecked(sink, setters, i, dto); - } - break; - - default: - // In order for us to get here we would have to have an - // invalid instance of SqlDbType, or one would have to add - // new member to SqlDbType without adding a case in this - // switch, hence the assert. - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record) - { - FillCompatibleITypedSettersFromRecord(sink, setters, metaData, record, null); - } - - internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) - { - for (int i = 0; i < metaData.Length; ++i) - { - if (null != useDefaultValues && useDefaultValues[i]) - { - continue; - } - if (record.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, record.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? - break; - case SqlDbType.Variant: - object o = record.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); - break; - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - default: - Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, SmiTypedGetterSetter setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) - { - for (int i = 0; i < metaData.Length; ++i) - { - if (null != useDefaultValues && useDefaultValues[i]) - { - continue; - } - if (record.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, record.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? - break; - case SqlDbType.Variant: - object o = record.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, -1 /* no length restriction */, null /* no peekahead */); - break; - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Time: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataRecord sqlRecord = record as SqlDataRecord; - TimeSpan ts; - if (null != sqlRecord) - { - ts = sqlRecord.GetTimeSpan(i); - } - else - { - ts = (TimeSpan)record.GetValue(i); - } - SetTimeSpan_Checked(sink, setters, i, metaData[i], ts); - } - break; - case SqlDbType.DateTimeOffset: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataRecord sqlRecord = record as SqlDataRecord; - DateTimeOffset dto; - if (null != sqlRecord) - { - dto = sqlRecord.GetDateTimeOffset(i); - } - else - { - dto = (DateTimeOffset)record.GetValue(i); - } - SetDateTimeOffset_Unchecked(sink, setters, i, dto); - } - break; - - default: - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - // spool a Stream into a scratch stream from the Smi interface and return it as a Stream - internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink, SmiContext context) - { - Stream dest; - if (null == context) - { - dest = new MemoryStream(); - } - else - { - dest = new SqlClientWrapperSmiStream(sink, context.GetScratchStream(sink)); - } - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // SQLBU 494334 - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - - // spool a Stream into a scratch stream from the Smi interface and return it as a SqlStreamChars - internal static SqlStreamChars CopyIntoNewSmiScratchStreamChars(Stream source, SmiEventSink_Default sink, SmiContext context) - { - SqlClientWrapperSmiStreamChars dest = new SqlClientWrapperSmiStreamChars(sink, context.GetScratchStream(sink)); - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // SQLBU 494334 - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - - // - // Common utility code to get lengths correct for trimming - // - private static object GetUdt_LengthChecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - object result; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - Type t = metaData.Type; - Debug.Assert(t != null, "Unexpected null of udtType on GetUdt_LengthChecked!"); - result = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, Array.Empty(), CultureInfo.InvariantCulture); - Debug.Assert(result != null); - } - else - { - // Note: do not need to copy getter stream, since it will not be used beyond - // deserialization (valid lifetime of getters is limited). - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - result = SerializationHelperSql9.Deserialize(s, metaData.Type); - } - return result; - } - - private static decimal GetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (SqlDbType.Decimal == metaData.SqlDbType) - { - return GetSqlDecimal_Unchecked(sink, getters, ordinal).Value; - } - else - { - Debug.Assert(SqlDbType.Money == metaData.SqlDbType || - SqlDbType.SmallMoney == metaData.SqlDbType, - "Unexpected sqldbtype=" + metaData.SqlDbType); - return GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - } - } - - private static void SetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, decimal value) - { - if (SqlDbType.Decimal == metaData.SqlDbType || SqlDbType.Variant == metaData.SqlDbType) - { - SetDecimal_Unchecked(sink, setters, ordinal, value); - } - else - { - Debug.Assert(SqlDbType.Money == metaData.SqlDbType || - SqlDbType.SmallMoney == metaData.SqlDbType, - "Unexpected sqldbtype=" + metaData.SqlDbType); - SetSqlMoney_Checked(sink, setters, ordinal, metaData, new SqlMoney(value)); - } - } - - // Hard coding smalldatetime limits... - private static readonly DateTime s_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998); - private static readonly DateTime s_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999); - private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) - { - if (SqlDbType.SmallDateTime == dbType && (s_dtSmallMax < value || s_dtSmallMin > value)) - { - throw ADP.InvalidMetaDataValue(); - } - } - - private static readonly TimeSpan s_timeMin = TimeSpan.Zero; - private static readonly TimeSpan s_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1); - private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) - { - if (SqlDbType.Time == dbType && (s_timeMin > value || value > s_timeMax)) - { - throw ADP.InvalidMetaDataValue(); - } - } - - private static void SetDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDateTime_Unchecked(sink, setters, ordinal, ((SqlDbType.Date == metaData.SqlDbType) ? value.Date : value)); - } - - private static void SetTimeSpan_Checked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, TimeSpan value) - { - VerifyTimeRange(metaData.SqlDbType, value); - SetTimeSpan_Unchecked(sink, setters, ordinal, value); - } - - private static void SetSqlDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value) - { - if (!value.IsNull) - { - VerifyDateTimeRange(metaData.SqlDbType, value.Value); - } - SetSqlDateTime_Unchecked(sink, setters, ordinal, value); - } - - private static void SetDateTime2_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDateTime2_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetDate_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDate_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetSqlMoney_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - if (!value.IsNull && SqlDbType.SmallMoney == metaData.SqlDbType) - { - decimal decimalValue = value.Value; - if (TdsEnums.SQL_SMALL_MONEY_MIN > decimalValue || TdsEnums.SQL_SMALL_MONEY_MAX < decimalValue) - { - throw SQL.MoneyOverflow(decimalValue.ToString(CultureInfo.InvariantCulture)); - } - } - SetSqlMoney_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetByteArray_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte[] buffer, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset); - Debug.Assert(length >= 0, "buffer.Length was invalid!"); - SetByteArray_Unchecked(sink, setters, ordinal, buffer, offset, length); - } - - private static void SetCharArray_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, char[] buffer, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset); - Debug.Assert(length >= 0, "buffer.Length was invalid!"); - SetCharArray_Unchecked(sink, setters, ordinal, buffer, offset, length); - } - - private static void SetSqlBinary_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value, int offset) - { - int length = 0; - if (!value.IsNull) - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, value.Length - offset); - Debug.Assert(length >= 0, "value.Length was invalid!"); - } - SetSqlBinary_Unchecked(sink, setters, ordinal, value, offset, length); - } - - private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case - long bufferLength = record.GetBytes(ordinal, 0, null, 0, 0); - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); - - int chunkSize; - if (length > __maxByteChunkSize || length < 0) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = record.GetBytes(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetBytes_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); - - // Use fixed chunk size for all cases to avoid inquiring from reader. - int chunkSize = __maxByteChunkSize; - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = reader.GetBytes(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBytes_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value, int offset) - { - int length = 0; - if (!value.IsNull) - { - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case - long bufferLength = value.Length; - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); - } - SetSqlBytes_Unchecked(sink, setters, ordinal, value, 0, length); - } - - private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit - // CheckXetParameters will ignore length checks in this case - long bufferLength = record.GetChars(ordinal, 0, null, 0, 0); - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); - - int chunkSize; - if (length > __maxCharChunkSize || length < 0) - { - if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = __maxCharChunkSize; - } - } - else - { - chunkSize = checked((int)length); - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = record.GetChars(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - // Transfer a character value from a reader when we're not sure which GetXXX method the reader will support. - // Prefers to chunk data via GetChars, but falls back to GetString if that fails. - // Mainly put in place because DataTableReader doesn't support GetChars on string columns, but others could fail too... - private static void SetCharsOrString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - bool success = false; - try - { - SetChars_FromReader(sink, setters, ordinal, metaData, reader, offset); - success = true; - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - } - - if (!success) - { - SetString_FromReader(sink, setters, ordinal, metaData, reader, offset); - } - } - - // Use chunking via SetChars to transfer a value from a reader to a gettersetter - private static void SetChars_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); - - // Use fixed chunk size for all cases to avoid inquiring from reader. - int chunkSize; - if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = __maxCharChunkSize; - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = reader.GetChars(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - string value = reader.GetString(ordinal); - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, value.Length, 0, NoLengthLimit /* buffer */, offset, NoLengthLimit /* request */); - - setters.SetString(sink, ordinal, value, offset, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlChars_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value, int offset) - { - int length = 0; - if (!value.IsNull) - { - // Deal with large values by sending bufferLength of NoLengthLimit - // CheckXetParameters will ignore length checks in this case - long bufferLength = value.Length; - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); - } - SetSqlChars_Unchecked(sink, setters, ordinal, value, 0, length); - } - - private static void SetSqlString_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset) - { - if (value.IsNull) - { - SetDBNull_Unchecked(sink, setters, ordinal); - } - else - { - string stringValue = value.Value; - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, stringValue.Length, offset, stringValue.Length - offset); - Debug.Assert(length >= 0, "value.Length was invalid!"); - SetSqlString_Unchecked(sink, setters, ordinal, metaData, value, offset, length); - } - } - - private static void SetString_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, checked(value.Length - offset)); - Debug.Assert(length >= 0, "value.Length was invalid!"); - SetString_Unchecked(sink, setters, ordinal, value, offset, length); - } - - private static void SetUdt_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, object value) - { - if (ADP.IsNull(value)) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - Stream target = new SmiSettersStream(sink, setters, ordinal, metaData); - SerializationHelperSql9.Serialize(target, value); - } - } - - // - // Semantics support routines - // - - private static void ThrowIfInvalidSetterAccess(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - if (!CanAccessSetterDirectly(metaData, setterTypeCode)) - { - throw ADP.InvalidCast(); - } - } - - private static void ThrowIfITypedGettersIsNull(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - throw SQL.SqlNullValue(); - } - } - - private static bool CanAccessGetterDirectly(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file! - Debug.Assert(ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == s_canAccessGetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessGetterDirectly"); - Debug.Assert(SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == s_canAccessGetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessGetterDirectly"); - Debug.Assert(ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode); - Debug.Assert(SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType); - - bool returnValue = s_canAccessGetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType]; - - // Additional restrictions to distinguish TVPs and Structured UDTs - if (returnValue && - (ExtendedClrTypeCode.DataTable == setterTypeCode || - ExtendedClrTypeCode.DbDataReader == setterTypeCode || - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) - { - returnValue = metaData.IsMultiValued; - } - - return returnValue; - } - - private static bool CanAccessSetterDirectly(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file! - Debug.Assert(ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == s_canAccessSetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessSetterDirectly"); - Debug.Assert(SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == s_canAccessSetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessSetterDirectly"); - Debug.Assert(ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode); - Debug.Assert(SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType); - - bool returnValue = s_canAccessSetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType]; - - // Additional restrictions to distinguish TVPs and Structured UDTs - if (returnValue && - (ExtendedClrTypeCode.DataTable == setterTypeCode || - ExtendedClrTypeCode.DbDataReader == setterTypeCode || - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) - { - returnValue = metaData.IsMultiValued; - } - - return returnValue; - } - - private static long PositiveMin(long first, long second) - { - if (first < 0) - { - return second; - } - - if (second < 0) - { - return first; - } - - return Math.Min(first, second); - } - - // Check Get Byte/Chars parameters, throw or adjust invalid values - private static int CheckXetParameters( - SqlDbType dbType, - long maxLength, - long actualLength, - long fieldOffset, - int bufferLength, - int bufferOffset, - int length) - { - if (0 > fieldOffset) - throw ADP.NegativeParameter(nameof(fieldOffset)); - - // if negative buffer index, throw - if (bufferOffset < 0) - { - throw ADP.InvalidDestinationBufferIndex(bufferLength, bufferOffset, nameof(bufferOffset)); - } - - // skip further length checks for LOB buffer lengths - if (bufferLength < 0) - { - length = checked((int)PositiveMin(length, PositiveMin(maxLength, actualLength))); - if (length < NoLengthLimit) - { - length = NoLengthLimit; - } - return length; - } - - // if bad buffer index, throw - if (bufferOffset > bufferLength) - { - throw ADP.InvalidDestinationBufferIndex(bufferLength, bufferOffset, nameof(bufferOffset)); - } - - // if there is not enough room in the buffer for data - if (checked(length + bufferOffset) > bufferLength) - throw ADP.InvalidBufferSizeOrIndex(length, bufferOffset); - - if (length < 0) - throw ADP.InvalidDataLength(length); - - if (0 <= actualLength && actualLength <= fieldOffset) - { - return 0; - } - - // trim length against both bufferLength and actual or max length - // (actual or max < 0 means don't trim against that value) - // Note that parameter UDTs don't know the correct maxlength, so the back end does - // the trimming. Actual length should still be trimmed against here, though. - length = Math.Min(length, bufferLength - bufferOffset); - - // special case for variants, since their maxLength is actually a bit bigger than - // the actual data length allowed. - if (SqlDbType.Variant == dbType) - { - length = Math.Min(length, TdsEnums.TYPE_SIZE_LIMIT); - } - - Debug.Assert(0 > maxLength || 0 > actualLength || - maxLength >= actualLength, "Actual = " + actualLength + ", max = " + maxLength + ", sqldbtype=" + dbType); - - if (0 <= actualLength) - { - // Length is guaranteed to be >= 0 coming in and actualLength >= fieldOffset, so this operation guarantees result >= 0 - length = (int)Math.Min((long)length, actualLength - fieldOffset); - Debug.Assert(length >= 0, "result < 0, actualLength/fieldOffset problem?"); - } - else if (SqlDbType.Udt != dbType && 0 <= maxLength) - { - length = (int)Math.Min((long)length, maxLength - fieldOffset); - Debug.Assert(length >= 0, "Result < 0, maxlen/fieldoffset problem?"); - } - - if (length < 0) - { - return 0; - } - else - { - return length; - } - } - - // - // These tables are formal encoding of the "unchecked" method access rules for various types - // The tables should only be accessed from the CanAccessXetterDirectly methods. - // - - // A couple of private constants to increase the getter/setter access tables' constrast - private const bool X = true; - private const bool _ = false; - - private static bool[,] s_canAccessGetterDirectly = { - // SqlDbTypes as columns (abbreviated, but in order) - // ExtendedClrTypeCodes as rows - - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO -/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ -/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ -/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ -/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ -/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ -/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ -/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ -/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ -/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ -/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ -/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ -/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ -/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ -/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ -/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ -/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ -/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ -/*BytAr*/{ _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ -/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ -/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ -/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ -/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ -/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ -/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ -/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ -/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ -/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ -/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ -/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ -/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ -/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ -/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ -/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ -/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ -/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ -/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ -/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ -/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ -/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ -/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ -/*Strm */{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ -/*TxRdr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ -/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - }; - - private static bool[,] s_canAccessSetterDirectly = { - // Setters as columns (labels are abreviated from ExtendedClrTypeCode names) - // SqlDbTypes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO -/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ -/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ -/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ -/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ -/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ -/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ -/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ -/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ -/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ -/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ -/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ -/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ -/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ -/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ -/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ -/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ -/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ -/*BytAr*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ -/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ -/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ -/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ -/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ -/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ -/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ -/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ -/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ -/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ -/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ -/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ -/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ -/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ -/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ -/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ -/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ -/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ -/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ -/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ -/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ -/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ -/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ -/*Strm */{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ -/*TxRdr*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ -/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - }; - - - // - // Private implementation of common mappings from a given type to corresponding Smi Getter/Setter - // These classes do type validation, parameter limit validation, nor coercions - // - private static bool IsDBNull_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - bool result = getters.IsDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static bool GetBoolean_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - bool result = getters.GetBoolean(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static byte GetByte_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - byte result = getters.GetByte(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static byte[] GetByteArray_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long length = getters.GetBytesLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - int len = checked((int)length); - - byte[] buffer = new byte[len]; - getters.GetBytes(sink, ordinal, 0, buffer, 0, len); - sink.ProcessMessagesAndThrow(); - return buffer; - } - - internal static int GetBytes_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - Debug.Assert(ordinal >= 0, $"Invalid ordinal: {ordinal}"); - Debug.Assert(sink != null, "Null SmiEventSink"); - Debug.Assert(getters != null, "Null getters"); - Debug.Assert(fieldOffset >= 0, $"Invalid field offset: {fieldOffset}"); - Debug.Assert(buffer != null, "Null buffer"); - Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, $"Bad offset or length. bufferOffset: {bufferOffset}, length: {length}, buffer.Length{buffer.Length}"); - - int result = getters.GetBytes(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetBytesLength_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetBytesLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - - private static char[] GetCharArray_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long length = getters.GetCharsLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - int len = checked((int)length); - - char[] buffer = new char[len]; - getters.GetChars(sink, ordinal, 0, buffer, 0, len); - sink.ProcessMessagesAndThrow(); - return buffer; - } - - internal static int GetChars_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - Debug.Assert(ordinal >= 0, $"Invalid ordinal: {ordinal}"); - Debug.Assert(sink != null, "Null SmiEventSink"); - Debug.Assert(getters != null, "Null getters"); - Debug.Assert(fieldOffset >= 0, $"Invalid field offset: {fieldOffset}"); - Debug.Assert(buffer != null, "Null buffer"); - Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, $"Bad offset or length. bufferOffset: {bufferOffset}, length: {length}, buffer.Length{buffer.Length}"); - - int result = getters.GetChars(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetCharsLength_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetCharsLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static DateTime GetDateTime_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - DateTime result = getters.GetDateTime(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static DateTimeOffset GetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - DateTimeOffset result = getters.GetDateTimeOffset(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static double GetDouble_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - double result = getters.GetDouble(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static Guid GetGuid_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - Guid result = getters.GetGuid(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static short GetInt16_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - short result = getters.GetInt16(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static int GetInt32_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - int result = getters.GetInt32(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetInt64_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetInt64(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static float GetSingle_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - float result = getters.GetSingle(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static SqlBinary GetSqlBinary_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - byte[] buffer = GetByteArray_Unchecked(sink, getters, ordinal); - return new SqlBinary(buffer); - } - - private static SqlDecimal GetSqlDecimal_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - SqlDecimal result = getters.GetSqlDecimal(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static SqlMoney GetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long temp = getters.GetInt64(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return SqlTypeWorkarounds.SqlMoneyCtor(temp, 1 /* ignored */ ); - } - - private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiContext context) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - // allow context to be null so strongly-typed getters can use - // this method without having to pass along the almost-never-used context as a parameter - // Looking the context up like this will be slightly slower, but still correct behavior - // since it's only used to get a scratch stream. - if (null == context && InOutOfProcHelper.InProc) - { - context = SmiContextFactory.Instance.GetCurrentContext(); // In the future we need to push the context checking to a higher level - } - - // Note: must make a copy of getter stream, since it will be used beyond - // this method (valid lifetime of getters is limited). - Stream s = new SmiGettersStream(sink, getters, ordinal, SmiMetaData.DefaultXml); - Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink, context); - SqlXml result = new SqlXml(copy); - return result; - } - - private static String GetString_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - // Note: depending on different getters, the result string maybed truncated, e.g. for - // Inproc process, the getter is InProcRecordBuffer (implemented in SqlAcess), string will be - // truncated to 4000 (if length is more than 4000). If MemoryRecordBuffer getter is used, data - // is not truncated. Please refer VSDD 479655 for more detailed information regarding the string length. - String result = getters.GetString(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static TimeSpan GetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - TimeSpan result = getters.GetTimeSpan(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetBoolean_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, bool value) - { - setters.SetBoolean(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetByteArray_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, byte[] buffer, int bufferOffset, int length) - { - if (length > 0) - { - setters.SetBytes(sink, ordinal, 0, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - } - setters.SetBytesLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, StreamDataFeed feed) - { - long len = metadata.MaxLength; - byte[] buff = new byte[constBinBufferSize]; - int nWritten = 0; - do - { - int nRead = 0; - int readSize = constBinBufferSize; - if (len > 0 && nWritten + readSize > len) - { - readSize = (int)(len - nWritten); - } - - Debug.Assert(readSize >= 0); - - nRead = feed._source.Read(buff, 0, readSize); - - if (nRead == 0) - { - break; - } - - setters.SetBytes(sink, ordinal, nWritten, buff, 0, nRead); - sink.ProcessMessagesAndThrow(); - - nWritten += nRead; - } while (len <= 0 || nWritten < len); - - setters.SetBytesLength(sink, ordinal, nWritten); - sink.ProcessMessagesAndThrow(); - } - - private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, TextDataFeed feed) - { - long len = metadata.MaxLength; - char[] buff = new char[constTextBufferSize]; - int nWritten = 0; - do - { - int nRead = 0; - int readSize = constTextBufferSize; - if (len > 0 && nWritten + readSize > len) - { - readSize = (int)(len - nWritten); - } - - Debug.Assert(readSize >= 0); - - nRead = feed._source.Read(buff, 0, readSize); - - if (nRead == 0) - { - break; - } - - setters.SetChars(sink, ordinal, nWritten, buff, 0, nRead); - sink.ProcessMessagesAndThrow(); - - nWritten += nRead; - } while (len <= 0 || nWritten < len); - - setters.SetCharsLength(sink, ordinal, nWritten); - sink.ProcessMessagesAndThrow(); - } - - private static void SetByte_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, byte value) - { - setters.SetByte(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static int SetBytes_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - int result = setters.SetBytes(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetCharArray_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, char[] buffer, int bufferOffset, int length) - { - if (length > 0) - { - setters.SetChars(sink, ordinal, 0, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - } - setters.SetCharsLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - } - - private static int SetChars_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - int result = setters.SetChars(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetDBNull_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDecimal_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, decimal value) - { - setters.SetSqlDecimal(sink, ordinal, new SqlDecimal(value)); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTime_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, DateTime value) - { - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTime2_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant."); - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDateTime2); - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDate_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant."); - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDate); - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, TimeSpan value) - { - setters.SetTimeSpan(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, DateTimeOffset value) - { - setters.SetDateTimeOffset(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDouble_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, double value) - { - setters.SetDouble(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetGuid_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Guid value) - { - setters.SetGuid(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt16_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, short value) - { - setters.SetInt16(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt32_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, int value) - { - setters.SetInt32(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt64_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long value) - { - setters.SetInt64(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSingle_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, float value) - { - setters.SetSingle(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBinary_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBinary value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - SetByteArray_Unchecked(sink, setters, ordinal, value.Value, offset, length); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBoolean_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBoolean value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetBoolean(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlByte_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlByte value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetByte(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - // note: length < 0 indicates write everything - private static void SetSqlBytes_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBytes value, int offset, long length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - int chunkSize; - if (length > __maxByteChunkSize || length < 0) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = value.Read(currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - } - - private static void SetSqlChars_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlChars value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - int chunkSize; - if (length > __maxCharChunkSize || length < 0) - { - chunkSize = __maxCharChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = value.Read(currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - } - - private static void SetSqlDateTime_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDateTime value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetDateTime(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlDecimal_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDecimal value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetSqlDecimal(sink, ordinal, value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlDouble_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDouble value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetDouble(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlGuid_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlGuid value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetGuid(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt16_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt16 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt16(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt32_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt32 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt32(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt64_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt64 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt64(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - if (SqlDbType.Variant == metaData.SqlDbType) - { - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultMoney); - sink.ProcessMessagesAndThrow(); - } - - setters.SetInt64(sink, ordinal, SqlTypeWorkarounds.SqlMoneyToSqlInternalRepresentation(value)); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlSingle_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlSingle value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetSingle(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlString_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - if (SqlDbType.Variant == metaData.SqlDbType) - { - // Set up a NVarChar metadata with correct LCID/Collation - metaData = new SmiMetaData( - SqlDbType.NVarChar, - SmiMetaData.MaxUnicodeCharacters, - 0, - 0, - value.LCID, - value.SqlCompareOptions, - null); - setters.SetVariantMetaData(sink, ordinal, metaData); - sink.ProcessMessagesAndThrow(); - } - SetString_Unchecked(sink, setters, ordinal, value.Value, offset, length); - } - } - - private static void SetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlXml value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - SetXmlReader_Unchecked(sink, setters, ordinal, value.CreateReader()); - } - } - - private static void SetXmlReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, XmlReader xmlReader) - { - // set up writer - XmlWriterSettings WriterSettings = new XmlWriterSettings(); - WriterSettings.CloseOutput = false; // don't close the memory stream - WriterSettings.ConformanceLevel = ConformanceLevel.Fragment; - WriterSettings.Encoding = System.Text.Encoding.Unicode; - WriterSettings.OmitXmlDeclaration = true; - - System.IO.Stream target = new SmiSettersStream(sink, setters, ordinal, SmiMetaData.DefaultXml); - - XmlWriter xmlWriter = XmlWriter.Create(target, WriterSettings); - - // now spool the data into the writer (WriteNode will call Read()) - xmlReader.Read(); - while (!xmlReader.EOF) - { - xmlWriter.WriteNode(xmlReader, true); - } - xmlWriter.Flush(); - sink.ProcessMessagesAndThrow(); - } - - private static void SetString_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, string value, int offset, int length) - { - setters.SetString(sink, ordinal, value, offset, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDataTable_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DataTable value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // iterate over all records - // if first record was obtained earlier, use it prior to pulling more - ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - cellTypes[i] = ExtendedClrTypeCode.Invalid; - } - foreach (DataRow row in value.Rows) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - // Set all columns in the record - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; - if (row.IsNull(i)) - { - SetDBNull_Unchecked(sink, setters, i); - } - else - { - object cellValue = row[i]; - - // Only determine cell types for first row, to save expensive - if (ExtendedClrTypeCode.Invalid == cellTypes[i]) - { - cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type, - // TODO: this version works for shipping Orcas, since only Katmai supports TVPs at this time. - // Need a better story for smi versioning of ValueUtilsSmi post-Orcas - SmiContextFactory.KatmaiVersion - ); - } - SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); - } - } - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - - // Set a DbDataReader to a Structured+MultiValued setter (table type) - // Assumes metaData correctly describes the reader's shape, and consumes only the current resultset - private static void SetDbDataReader_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DbDataReader value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // Iterate over all rows in the current set of results - while (value.Read()) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - FillCompatibleSettersFromReader(sink, setters, metaData.FieldMetaData, value); - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - - private static void SetIEnumerableOfSqlDataRecord_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - IEnumerable value, - ParameterPeekAheadValue peekAhead - ) - { - // Get target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - IEnumerator enumerator = null; - try - { - // Need to copy field metadata to an array to call FillCompatibleITypeSettersFromRecord - SmiExtendedMetaData[] mdFields = new SmiExtendedMetaData[metaData.FieldMetaData.Count]; - metaData.FieldMetaData.CopyTo(mdFields, 0); - - SmiDefaultFieldsProperty defaults = (SmiDefaultFieldsProperty)metaData.ExtendedProperties[SmiPropertySelector.DefaultFields]; - - int recordNumber = 1; // used only for reporting position when there are errors. - - // obtain enumerator and handle any peekahead values - if (null != peekAhead && null != peekAhead.FirstRecord) - { - // hook up to enumerator - enumerator = peekAhead.Enumerator; - - // send the first record that was obtained earlier - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - FillCompatibleSettersFromRecord(sink, setters, mdFields, peekAhead.FirstRecord, defaults); - recordNumber++; - } - else - { - enumerator = value.GetEnumerator(); - } - - using (enumerator) - { - while (enumerator.MoveNext()) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - SqlDataRecord record = enumerator.Current; - - if (record.FieldCount != mdFields.Length) - { - throw SQL.EnumeratedRecordFieldCountChanged(recordNumber); - } - - for (int i = 0; i < record.FieldCount; i++) - { - if (!MetaDataUtilsSmi.IsCompatible(metaData.FieldMetaData[i], record.GetSqlMetaData(i))) - { - throw SQL.EnumeratedRecordMetaDataChanged(record.GetName(i), recordNumber); - } - } - - FillCompatibleSettersFromRecord(sink, setters, mdFields, record, defaults); - recordNumber++; - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - } - finally - { - // Clean up! - IDisposable disposable = enumerator as IDisposable; - if (null != disposable) - { - disposable.Dispose(); - } - } - } - } -} - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs similarity index 86% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs index cdf0802ef3..f53396cdaa 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs @@ -23,7 +23,7 @@ namespace Microsoft.Data.SqlClient.Server // // These are all based off of knowing the clr type of the value // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). - internal static class ValueUtilsSmi + internal static partial class ValueUtilsSmi { private const int __maxByteChunkSize = TdsEnums.MAXSIZE; private const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char); @@ -60,7 +60,11 @@ internal static bool GetBoolean(SmiEventSink_Default sink, ITypedGettersV3 gette return GetBoolean_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -75,7 +79,11 @@ internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetByte_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -85,7 +93,11 @@ internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -197,7 +209,11 @@ internal static long GetChars(SmiEventSink_Default sink, ITypedGettersV3 getters return length; } - string value = ((string)GetValue(sink, getters, ordinal, metaData)); + string value = ((string)GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + )); if (null == value) { throw ADP.InvalidCast(); @@ -219,7 +235,11 @@ internal static DateTime GetDateTime(SmiEventSink_Default sink, ITypedGettersV3 { return GetDateTime_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -235,7 +255,11 @@ internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, ITyp return GetDateTimeOffset(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); } ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -251,7 +275,11 @@ internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiT { return GetDateTimeOffset_Unchecked(sink, getters, ordinal); } - return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData); + return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); } internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) @@ -261,7 +289,11 @@ internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 ge { return GetDecimal_PossiblyMoney(sink, getters, ordinal, metaData); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -276,7 +308,11 @@ internal static double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 gett { return GetDouble_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -291,7 +327,11 @@ internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetGuid_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -306,7 +346,11 @@ internal static short GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getter { return GetInt16_Unchecked(sink, getters, ordinal); } - object obj = GetValue(sink, getters, ordinal, metaData); + object obj = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -321,7 +365,11 @@ internal static int GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetInt32_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -336,7 +384,11 @@ internal static long GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters { return GetInt64_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -351,7 +403,11 @@ internal static float GetSingle(SmiEventSink_Default sink, ITypedGettersV3 gette { return GetSingle_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -369,7 +425,11 @@ internal static SqlBinary GetSqlBinary(SmiEventSink_Default sink, ITypedGettersV } return GetSqlBinary_Unchecked(sink, getters, ordinal); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -387,7 +447,11 @@ internal static SqlBoolean GetSqlBoolean(SmiEventSink_Default sink, ITypedGetter } return new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -405,7 +469,11 @@ internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 ge } return new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -413,7 +481,11 @@ internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 ge return (SqlByte)result; } - internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlBytes result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBytes)) @@ -433,14 +505,22 @@ internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 else { Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - s = CopyIntoNewSmiScratchStream(s, sink); + s = CopyIntoNewSmiScratchStream(s, sink +#if NETFRAMEWORK + , context +#endif + ); result = new SqlBytes(s); } } } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -459,7 +539,11 @@ internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 return result; } - internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlChars result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlChars)) @@ -470,8 +554,28 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 } else { +#if NETFRAMEWORK + long length = GetCharsLength_Unchecked(sink, getters, ordinal); + if (length < __maxCharChunkSize || !InOutOfProcHelper.InProc) + { + char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); + result = new SqlChars(charBuffer); + } + else + { // InProc only + Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); + SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars(s, sink, context); + + Type SqlCharsType = (typeof(SqlChars)); + Type[] argTypes = new Type[] { typeof(SqlStreamChars) }; + SqlChars SqlCharsInstance = (SqlChars)SqlCharsType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, + null, argTypes, null).Invoke(new object[] { sc }); + result = SqlCharsInstance; + } +#else char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); result = new SqlChars(charBuffer); +#endif } } else @@ -479,7 +583,11 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 SqlString stringValue; if (SqlDbType.Xml == metaData.SqlDbType) { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal); + SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , null +#endif + ); if (xmlValue.IsNull) { @@ -492,7 +600,11 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -530,7 +642,11 @@ internal static SqlDateTime GetSqlDateTime(SmiEventSink_Default sink, ITypedGett } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -557,7 +673,11 @@ internal static SqlDecimal GetSqlDecimal(SmiEventSink_Default sink, ITypedGetter } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -585,7 +705,11 @@ internal static SqlDouble GetSqlDouble(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -613,7 +737,11 @@ internal static SqlGuid GetSqlGuid(SmiEventSink_Default sink, ITypedGettersV3 ge } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -641,7 +769,11 @@ internal static SqlInt16 GetSqlInt16(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -669,7 +801,11 @@ internal static SqlInt32 GetSqlInt32(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -696,7 +832,11 @@ internal static SqlInt64 GetSqlInt64(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -723,7 +863,11 @@ internal static SqlMoney GetSqlMoney(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -751,7 +895,11 @@ internal static SqlSingle GetSqlSingle(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -779,7 +927,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV } else if (SqlDbType.Xml == metaData.SqlDbType) { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal); + SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , null +#endif + ); if (xmlValue.IsNull) { @@ -792,7 +944,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -803,7 +959,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV return result; } - internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlXml result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlXml)) @@ -814,12 +974,20 @@ internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 gett } else { - result = GetSqlXml_Unchecked(sink, getters, ordinal); + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ); } } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -837,7 +1005,11 @@ internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 gett { return GetString_Unchecked(sink, getters, ordinal); } - object obj = GetValue(sink, getters, ordinal, metaData); + object obj = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -845,8 +1017,7 @@ internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 gett return (string)obj; } - - // dealing with v200 SMI + // dealing with v200 SMI internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) { ThrowIfITypedGettersIsNull(sink, getters, ordinal); @@ -854,7 +1025,11 @@ internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSe { return GetTimeSpan_Unchecked(sink, getters, ordinal); } - return (TimeSpan)GetValue200(sink, getters, ordinal, metaData); + return (TimeSpan)GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); } // GetValue() for v200 SMI (new Katmai Date/Time types) @@ -863,6 +1038,9 @@ internal static object GetValue200( SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -878,7 +1056,11 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue200(sink, getters, ordinal, metaData); + result = GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Date: case SqlDbType.DateTime2: @@ -891,7 +1073,11 @@ SmiMetaData metaData result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); break; default: - result = GetValue(sink, getters, ordinal, metaData); + result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; } } @@ -905,6 +1091,9 @@ internal static object GetValue( ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -989,10 +1178,18 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue(sink, getters, ordinal, metaData); + result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal).Value; + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ).Value; break; case SqlDbType.Udt: result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); @@ -1009,6 +1206,9 @@ internal static object GetSqlValue200( SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -1031,7 +1231,11 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue200(sink, getters, ordinal, metaData); + result = GetSqlValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Date: case SqlDbType.DateTime2: @@ -1044,7 +1248,11 @@ SmiMetaData metaData result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); break; default: - result = GetSqlValue(sink, getters, ordinal, metaData); + result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; } } @@ -1058,6 +1266,9 @@ internal static object GetSqlValue( ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -1149,10 +1360,18 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue(sink, getters, ordinal, metaData); + result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal); + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Udt: result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); @@ -1164,7 +1383,7 @@ SmiMetaData metaData } // null return values for SqlClient 1.1-compatible GetSqlValue() - private static object[] s_typeSpecificNullForSqlValue = { + private static readonly object[] s_typeSpecificNullForSqlValue = { SqlInt64.Null, // SqlDbType.BigInt SqlBinary.Null, // SqlDbType.Binary SqlBoolean.Null, // SqlDbType.Bit @@ -1206,7 +1425,7 @@ internal static object NullUdtInstance(SmiMetaData metaData) { Type t = metaData.Type; Debug.Assert(t != null, "Unexpected null of Udt type on NullUdtInstance!"); - return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, Array.Empty(), CultureInfo.InvariantCulture); + return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new object[] { }, CultureInfo.InvariantCulture); } // Strongly-typed setters are a bit simpler than their corresponding getters. @@ -1300,8 +1519,18 @@ internal static void SetDateTime(SmiEventSink_Default sink, ITypedSettersV3 sett SetDateTime_Checked(sink, setters, ordinal, metaData, value); } - internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value) + internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value +#if NETFRAMEWORK + , bool settersSupportKatmaiDateTime +#endif + ) { +#if NETFRAMEWORK + if (!settersSupportKatmaiDateTime) + { + throw ADP.InvalidCast(); + } +#endif ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTimeOffset); SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value); } @@ -1471,8 +1700,18 @@ internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setter SetString_LengthChecked(sink, setters, ordinal, metaData, value, 0); } - internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value) + internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value +#if NETFRAMEWORK + , bool settersSupportKatmaiDateTime +#endif + ) { +#if NETFRAMEWORK + if (!settersSupportKatmaiDateTime) + { + throw ADP.InvalidCast(); + } +#endif ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.TimeSpan); SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, value); } @@ -1711,57 +1950,6 @@ ParameterPeekAheadValue peekAhead } } - private static void SetDataTable_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DataTable value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // iterate over all records - // if first record was obtained earlier, use it prior to pulling more - ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - cellTypes[i] = ExtendedClrTypeCode.Invalid; - } - foreach (DataRow row in value.Rows) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - // Set all columns in the record - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; - if (row.IsNull(i)) - { - SetDBNull_Unchecked(sink, setters, i); - } - else - { - object cellValue = row[i]; - - // Only determine cell types for first row, to save expensive - if (ExtendedClrTypeCode.Invalid == cellTypes[i]) - { - cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type); - } - SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); - } - } - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - // Copy multiple fields from reader to ITypedSettersV3 // Assumes caller enforces that reader and setter metadata are compatible internal static void FillCompatibleITypedSettersFromReader(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataReader reader) @@ -1929,8 +2117,7 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, { // block to scope sqlReader local to avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); // Support full fidelity for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { SetSqlDecimal_Unchecked(sink, setters, i, sqlReader.GetSqlDecimal(i)); } @@ -2005,8 +2192,7 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Xml: { Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { SetSqlXml_Unchecked(sink, setters, i, sqlReader.GetSqlXml(i)); } @@ -2019,10 +2205,9 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Variant: { // block to scope sqlReader local and avoid conflicts // Support better options for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; SqlBuffer.StorageType storageType = SqlBuffer.StorageType.Empty; object o; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { o = sqlReader.GetSqlValue(i); storageType = sqlReader.GetVariantInternalStorageType(i); @@ -2031,7 +2216,13 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, { o = reader.GetValue(i); } - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null +#if NETFRAMEWORK + ,// TODO: this version works for shipping Orcas, since only Katmai (TVP) codepath calls this method at this time. + // Need a better story for smi versioning of ValueUtilsSmi post-Orcas + SmiContextFactory.KatmaiVersion +#endif + ); if ((storageType == SqlBuffer.StorageType.DateTime2) || (storageType == SqlBuffer.StorageType.Date)) SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null, storageType); else @@ -2055,9 +2246,8 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Time: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataReader sqlReader = reader as SqlDataReader; TimeSpan ts; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { ts = sqlReader.GetTimeSpan(i); } @@ -2071,9 +2261,8 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.DateTimeOffset: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataReader sqlReader = reader as SqlDataReader; DateTimeOffset dto; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { dto = sqlReader.GetDateTimeOffset(i); } @@ -2097,7 +2286,6 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, } } - internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, SmiTypedGetterSetter setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) { for (int i = 0; i < metaData.Length; ++i) @@ -2221,9 +2409,8 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, case SqlDbType.Time: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataRecord sqlRecord = record as SqlDataRecord; TimeSpan ts; - if (null != sqlRecord) + if (record is SqlDataRecord sqlRecord) { ts = sqlRecord.GetTimeSpan(i); } @@ -2237,9 +2424,8 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, case SqlDbType.DateTimeOffset: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataRecord sqlRecord = record as SqlDataRecord; DateTimeOffset dto; - if (null != sqlRecord) + if (record is SqlDataRecord sqlRecord) { dto = sqlRecord.GetDateTimeOffset(i); } @@ -2258,36 +2444,7 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, } } } - - // spool a Stream into a scratch stream from the Smi interface and return it as a Stream - internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink) - { - Stream dest = new MemoryStream(); - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - + // // Common utility code to get lengths correct for trimming // @@ -2342,8 +2499,8 @@ private static void SetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedSe } // Hard coding smalldatetime limits... - private static readonly DateTime s_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998); - private static readonly DateTime s_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999); + private static readonly DateTime s_dtSmallMax = new(2079, 06, 06, 23, 59, 29, 998); + private static readonly DateTime s_dtSmallMin = new(1899, 12, 31, 23, 59, 29, 999); private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) { if (SqlDbType.SmallDateTime == dbType && (s_dtSmallMax < value || s_dtSmallMin > value)) @@ -2353,7 +2510,7 @@ private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) } private static readonly TimeSpan s_timeMin = TimeSpan.Zero; - private static readonly TimeSpan s_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1); + private static readonly TimeSpan s_timeMax = new(TimeSpan.TicksPerDay - 1); private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) { if (SqlDbType.Time == dbType && (s_timeMin > value || value > s_timeMax)) @@ -2435,7 +2592,6 @@ private static void SetSqlBinary_LengthChecked(SmiEventSink_Default sink, ITyped private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case @@ -2444,7 +2600,7 @@ private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSetters { bufferLength = NoLengthLimit; } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); int chunkSize; if (length > __maxByteChunkSize || length < 0) @@ -2485,11 +2641,10 @@ private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSetters private static void SetBytes_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); // Use fixed chunk size for all cases to avoid inquiring from reader. int chunkSize = __maxByteChunkSize; @@ -2540,7 +2695,6 @@ private static void SetSqlBytes_LengthChecked(SmiEventSink_Default sink, ITypedS private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit // CheckXetParameters will ignore length checks in this case @@ -2549,7 +2703,7 @@ private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSetters { bufferLength = NoLengthLimit; } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); int chunkSize; if (length > __maxCharChunkSize || length < 0) @@ -2623,11 +2777,10 @@ private static void SetCharsOrString_FromReader(SmiEventSink_Default sink, SmiTy // Use chunking via SetChars to transfer a value from a reader to a gettersetter private static void SetChars_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); // Use fixed chunk size for all cases to avoid inquiring from reader. int chunkSize; @@ -2903,199 +3056,109 @@ private static int CheckXetParameters( private const bool X = true; private const bool _ = false; - private static bool[,] s_canAccessGetterDirectly = { + private static readonly bool[,] s_canAccessGetterDirectly = { // SqlDbTypes as columns (abbreviated, but in order) // ExtendedClrTypeCodes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - /*Bool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ - /*Byte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ - /*Char*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ - /*DTime*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ - /*DBNul*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ - /*Decim*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ - /*Doubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ - /*Empty*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ - /*Int16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ - /*Int32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ - /*Int64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ - /*Singl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ - /*Strng*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ - /*UIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ - /*UIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ - /*UIn64*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ - /*Objct*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ - /*BytAr*/ - { _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ - /*ChrAr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ - /*Guid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ - /*SBin*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ - /*SBool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ - /*SDTme*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ - /*SDubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ - /*SGuid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ - /*SIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ - /*SIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ - /*SIn64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ - /*SMony*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ - /*SDeci*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ - /*SSngl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ - /*SStrn*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ - /*SChrs*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ - /*SByts*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ - /*SXml*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ - /*DTbl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ - /*Rdr */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ - /*EnSDR*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ - /*TmSpn*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ - /*DTOst*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ - /*Strm */ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ - /*TxRdr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ - /*XmlRd*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO +/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ +/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ +/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ +/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ +/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ +/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ +/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ +/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ +/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ +/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ +/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ +/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ +/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ +/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ +/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ +/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ +/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ +/*BytAr*/{ _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ +/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ +/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ +/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ +/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ +/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ +/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ +/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ +/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ +/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ +/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ +/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ +/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ +/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ +/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ +/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ +/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ +/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ +/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ +/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ +/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ +/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ +/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ +/*Strm */{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ +/*TxRdr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ +/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO }; - private static bool[,] s_canAccessSetterDirectly = { - // Setters as columns (labels are abbreviated from ExtendedClrTypeCode names) - // SqlDbTypes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - /*Bool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ - /*Byte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ - /*Char*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ - /*DTime*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ - /*DBNul*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ - /*Decim*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ - /*Doubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ - /*Empty*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ - /*Int16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ - /*Int32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ - /*Int64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ - /*Singl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ - /*Strng*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ - /*UIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ - /*UIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ - /*UIn64*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ - /*Objct*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ - /*BytAr*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ - /*ChrAr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ - /*Guid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ - /*SBin*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ - /*SBool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ - /*SDTme*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ - /*SDubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ - /*SGuid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ - /*SIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ - /*SIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ - /*SIn64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ - /*SMony*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ - /*SDeci*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ - /*SSngl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ - /*SStrn*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ - /*SChrs*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ - /*SByts*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ - /*SXml*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ - /*DTbl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ - /*Rdr */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ - /*EnSDR*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ - /*TmSpn*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ - /*DTOst*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ - /*Strm */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ - /*TxRdr*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ - /*XmlRd*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO + private static readonly bool[,] s_canAccessSetterDirectly = { + // Setters as columns (labels are abreviated from ExtendedClrTypeCode names) + // SqlDbTypes as rows + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO +/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ +/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ +/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ +/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ +/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ +/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ +/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ +/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ +/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ +/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ +/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ +/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ +/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ +/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ +/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ +/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ +/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ +/*BytAr*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ +/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ +/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ +/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ +/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ +/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ +/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ +/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ +/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ +/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ +/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ +/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ +/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ +/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ +/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ +/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ +/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ +/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ +/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ +/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ +/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ +/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ +/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ +/*Strm */{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ +/*TxRdr*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ +/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO }; @@ -3303,16 +3366,32 @@ private static SqlMoney GetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedG return SqlTypeWorkarounds.SqlMoneyCtor(temp, 1 /* ignored */ ); } - private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) + private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal +#if NETFRAMEWORK + , SmiContext context +#endif + ) { Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - +#if NETFRAMEWORK + // allow context to be null so strongly-typed getters can use + // this method without having to pass along the almost-never-used context as a parameter + // Looking the context up like this will be slightly slower, but still correct behavior + // since it's only used to get a scratch stream. + if (null == context && InOutOfProcHelper.InProc) + { + context = SmiContextFactory.Instance.GetCurrentContext(); // In the future we need to push the context checking to a higher level + } +#endif // Note: must make a copy of getter stream, since it will be used beyond // this method (valid lifetime of getters is limited). Stream s = new SmiGettersStream(sink, getters, ordinal, SmiMetaData.DefaultXml); - Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink); - SqlXml result = new SqlXml(copy); + Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink +#if NETFRAMEWORK + , context +#endif + ); + SqlXml result = new(copy); return result; } @@ -3320,7 +3399,7 @@ private static string GetString_Unchecked(SmiEventSink_Default sink, ITypedGette { Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - // Note: depending on different getters, the result string maybe truncated, e.g. for + // Note: depending on different getters, the result string may be truncated, e.g. for // Inproc process, the getter is InProcRecordBuffer (implemented in SqlAcess), string will be // truncated to 4000 (if length is more than 4000). If MemoryRecordBuffer getter is used, data // is not truncated. Please refer VSDD 479655 for more detailed information regarding the string length. @@ -3362,7 +3441,6 @@ private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSetters int nWritten = 0; do { - int nRead = 0; int readSize = constBinBufferSize; if (len > 0 && nWritten + readSize > len) { @@ -3371,7 +3449,7 @@ private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSetters Debug.Assert(readSize >= 0); - nRead = feed._source.Read(buff, 0, readSize); + int nRead = feed._source.Read(buff, 0, readSize); if (nRead == 0) { @@ -3395,7 +3473,6 @@ private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSet int nWritten = 0; do { - int nRead = 0; int readSize = constTextBufferSize; if (len > 0 && nWritten + readSize > len) { @@ -3404,7 +3481,7 @@ private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSet Debug.Assert(readSize >= 0); - nRead = feed._source.Read(buff, 0, readSize); + int nRead = feed._source.Read(buff, 0, readSize); if (nRead == 0) { @@ -3834,7 +3911,7 @@ private static void SetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedSetters private static void SetXmlReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, XmlReader xmlReader) { // set up writer - XmlWriterSettings WriterSettings = new XmlWriterSettings(); + XmlWriterSettings WriterSettings = new(); WriterSettings.CloseOutput = false; // don't close the memory stream WriterSettings.ConformanceLevel = ConformanceLevel.Fragment; WriterSettings.Encoding = System.Text.Encoding.Unicode; @@ -3860,8 +3937,7 @@ private static void SetString_Unchecked(SmiEventSink_Default sink, ITypedSetters sink.ProcessMessagesAndThrow(); } - - // Set a DbDataReader to a Structured+MultiValued setter (table type) + // Set a DbDataReader to a Structured+MultiValued setter (table type) // Assumes metaData correctly describes the reader's shape, and consumes only the current resultset private static void SetDbDataReader_Unchecked( SmiEventSink_Default sink, @@ -3962,13 +4038,115 @@ ParameterPeekAheadValue peekAhead finally { // Clean up! - IDisposable disposable = enumerator as IDisposable; - if (null != disposable) + if (enumerator is IDisposable disposable) { disposable.Dispose(); } } } + + private static void SetDataTable_Unchecked( + SmiEventSink_Default sink, + SmiTypedGetterSetter setters, + int ordinal, + SmiMetaData metaData, + DataTable value + ) + { + // Get the target gettersetter + setters = setters.GetTypedGetterSetter(sink, ordinal); + sink.ProcessMessagesAndThrow(); + + // iterate over all records + // if first record was obtained earlier, use it prior to pulling more + ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; + for (int i = 0; i < metaData.FieldMetaData.Count; i++) + { + cellTypes[i] = ExtendedClrTypeCode.Invalid; + } + foreach (DataRow row in value.Rows) + { + setters.NewElement(sink); + sink.ProcessMessagesAndThrow(); + + // Set all columns in the record + for (int i = 0; i < metaData.FieldMetaData.Count; i++) + { + SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; + if (row.IsNull(i)) + { + SetDBNull_Unchecked(sink, setters, i); + } + else + { + object cellValue = row[i]; + + // Only determine cell types for first row, to save expensive + if (ExtendedClrTypeCode.Invalid == cellTypes[i]) + { + cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type +#if NETFRAMEWORK + ,// TODO: this version works for shipping Orcas, since only Katmai supports TVPs at this time. + // Need a better story for smi versioning of ValueUtilsSmi post-Orcas + SmiContextFactory.KatmaiVersion +#endif + ); + } + SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); + } + } + } + + setters.EndElements(sink); + sink.ProcessMessagesAndThrow(); + } + + // spool a Stream into a scratch stream from the Smi interface and return it as a Stream + internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink +#if NETFRAMEWORK + , SmiContext context +#endif + ) + { +#if NETFRAMEWORK + Stream dest; + if (null == context) + { + dest = new MemoryStream(); + } + else + { + dest = new SqlClientWrapperSmiStream(sink, context.GetScratchStream(sink)); + } +#else + Stream dest = new MemoryStream(); +#endif + + int chunkSize; + if (source.CanSeek && __maxByteChunkSize > source.Length) + { + chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above + } + else + { + chunkSize = __maxByteChunkSize; + } + + byte[] copyBuffer = new byte[chunkSize]; + int bytesRead; + while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) + { + dest.Write(copyBuffer, 0, bytesRead); + } + dest.Flush(); + + // Need to re-wind scratch stream to beginning before returning + dest.Seek(0, SeekOrigin.Begin); + + return dest; + } + } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs new file mode 100644 index 0000000000..d48a8df2e1 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs @@ -0,0 +1,513 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlTypes; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Xml; +using Microsoft.Data.Common; +using Microsoft.Data.SqlTypes; + +namespace Microsoft.Data.SqlClient.Server +{ + // Utilities for manipulating values with the Smi interface. + // + // THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT! + // + // These are all based off of knowing the clr type of the value + // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). + internal static partial class ValueUtilsSmi + { + + internal static SqlSequentialStreamSmi GetSequentialStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) + { + Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialStreamSmi on a null column"); + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + if ((!bypassTypeCheck) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) + { + throw ADP.InvalidCast(); + } + + // This will advance the column to ordinal + long length = GetBytesLength_Unchecked(sink, getters, ordinal); + return new SqlSequentialStreamSmi(sink, getters, ordinal, length); + } + + internal static SqlSequentialTextReaderSmi GetSequentialTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + { + Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column"); + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + if (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader)) + { + throw ADP.InvalidCast(); + } + + // This will advance the column to ordinal + long length = GetCharsLength_Unchecked(sink, getters, ordinal); + return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length); + } + + internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) + { + bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); + + // If a sql_variant, get the internal type + if (!bypassTypeCheck) + { + if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) + { + metaData = getters.GetVariantType(sink, ordinal); + } + // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast + if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) + { + throw ADP.InvalidCast(); + } + } + + byte[] data; + if (isDbNull) + { + // "null" stream + data = new byte[0]; + } + else + { + // Read all data + data = GetByteArray_Unchecked(sink, getters, ordinal); + } + + // Wrap data in pre-built object + return new MemoryStream(data, writable: false); + } + + internal static TextReader GetTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + { + bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); + + // If a sql_variant, get the internal type + if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) + { + metaData = getters.GetVariantType(sink, ordinal); + } + // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast + if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) + { + throw ADP.InvalidCast(); + } + + string data; + if (isDbNull) + { + // "null" textreader + data = string.Empty; + } + else + { + // Read all data + data = GetString_Unchecked(sink, getters, ordinal); + } + + // Wrap in pre-built object + return new StringReader(data); + } + + // calling GetTimeSpan on possibly v100 SMI + internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) + { + if (gettersSupportKatmaiDateTime) + { + return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); + } + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + object obj = GetValue(sink, getters, ordinal, metaData, null); + if (null == obj) + { + throw ADP.InvalidCast(); + } + return (TimeSpan)obj; + } + + internal static SqlBuffer.StorageType SqlDbTypeToStorageType(SqlDbType dbType) + { + int index = unchecked((int)dbType); + Debug.Assert(index >= 0 && index < s_dbTypeToStorageType.Length, string.Format(CultureInfo.InvariantCulture, "Unexpected dbType value: {0}", dbType)); + return s_dbTypeToStorageType[index]; + } + + private static void GetNullOutputParameterSmi(SmiMetaData metaData, SqlBuffer targetBuffer, ref object result) + { + if (SqlDbType.Udt == metaData.SqlDbType) + { + result = NullUdtInstance(metaData); + } + else + { + SqlBuffer.StorageType stype = SqlDbTypeToStorageType(metaData.SqlDbType); + if (SqlBuffer.StorageType.Empty == stype) + { + result = DBNull.Value; + } + else if (SqlBuffer.StorageType.SqlBinary == stype) + { + // special case SqlBinary, 'cause tds parser never sets SqlBuffer to null, just to empty! + targetBuffer.SqlBinary = SqlBinary.Null; + } + else if (SqlBuffer.StorageType.SqlGuid == stype) + { + targetBuffer.SqlGuid = SqlGuid.Null; + } + else + { + targetBuffer.SetToNullOfType(stype); + } + } + } + + // UDTs and null variants come back via return value, all else is via targetBuffer. + // implements SqlClient 2.0-compatible output parameter semantics + internal static object GetOutputParameterV3Smi( + SmiEventSink_Default sink, // event sink for errors + ITypedGettersV3 getters, // getters interface to grab value from + int ordinal, // parameter within getters + SmiMetaData metaData, // Getter's type for this ordinal + SmiContext context, // used to obtain scratch streams + SqlBuffer targetBuffer // destination + ) + { + object result = null; // Workaround for UDT hack in non-Smi code paths. + if (IsDBNull_Unchecked(sink, getters, ordinal)) + { + GetNullOutputParameterSmi(metaData, targetBuffer, ref result); + } + else + { + switch (metaData.SqlDbType) + { + case SqlDbType.BigInt: + targetBuffer.Int64 = GetInt64_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Binary: + case SqlDbType.Image: + case SqlDbType.Timestamp: + case SqlDbType.VarBinary: + targetBuffer.SqlBinary = GetSqlBinary_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Bit: + targetBuffer.Boolean = GetBoolean_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.NChar: + case SqlDbType.NText: + case SqlDbType.NVarChar: + case SqlDbType.Char: + case SqlDbType.VarChar: + case SqlDbType.Text: + targetBuffer.SetToString(GetString_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.DateTime: + case SqlDbType.SmallDateTime: + { + SqlDateTime dt = new(GetDateTime_Unchecked(sink, getters, ordinal)); + targetBuffer.SetToDateTime(dt.DayTicks, dt.TimeTicks); + break; + } + case SqlDbType.Decimal: + { + SqlDecimal dec = GetSqlDecimal_Unchecked(sink, getters, ordinal); + targetBuffer.SetToDecimal(dec.Precision, dec.Scale, dec.IsPositive, dec.Data); + break; + } + case SqlDbType.Float: + targetBuffer.Double = GetDouble_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Int: + targetBuffer.Int32 = GetInt32_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Money: + case SqlDbType.SmallMoney: + targetBuffer.SetToMoney(GetInt64_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.Real: + targetBuffer.Single = GetSingle_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.UniqueIdentifier: + targetBuffer.SqlGuid = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.SmallInt: + targetBuffer.Int16 = GetInt16_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.TinyInt: + targetBuffer.Byte = GetByte_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Variant: + // For variants, recur using the current value's sqldbtype + metaData = getters.GetVariantType(sink, ordinal); + sink.ProcessMessagesAndThrow(); + Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); + GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + case SqlDbType.Udt: + result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); + break; + case SqlDbType.Xml: + targetBuffer.SqlXml = GetSqlXml_Unchecked(sink, getters, ordinal, null); + break; + default: + Debug.Assert(false, "Unexpected SqlDbType"); + break; + } + } + + return result; + } + + // UDTs and null variants come back via return value, all else is via targetBuffer. + // implements SqlClient 1.1-compatible output parameter semantics + internal static object GetOutputParameterV200Smi( + SmiEventSink_Default sink, // event sink for errors + SmiTypedGetterSetter getters, // getters interface to grab value from + int ordinal, // parameter within getters + SmiMetaData metaData, // Getter's type for this ordinal + SmiContext context, // used to obtain scratch streams + SqlBuffer targetBuffer // destination + ) + { + object result = null; // Workaround for UDT hack in non-Smi code paths. + if (IsDBNull_Unchecked(sink, getters, ordinal)) + { + GetNullOutputParameterSmi(metaData, targetBuffer, ref result); + } + else + { + switch (metaData.SqlDbType) + { + // new types go here + case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types + // For variants, recur using the current value's sqldbtype + metaData = getters.GetVariantType(sink, ordinal); + sink.ProcessMessagesAndThrow(); + Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); + GetOutputParameterV200Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + case SqlDbType.Date: + targetBuffer.SetToDate(GetDateTime_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.DateTime2: + targetBuffer.SetToDateTime2(GetDateTime_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + case SqlDbType.Time: + targetBuffer.SetToTime(GetTimeSpan_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + case SqlDbType.DateTimeOffset: + targetBuffer.SetToDateTimeOffset(GetDateTimeOffset_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + default: + result = GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + } + } + + return result; + } + + private static readonly SqlBuffer.StorageType[] s_dbTypeToStorageType = new SqlBuffer.StorageType[] { + SqlBuffer.StorageType.Int64, // BigInt + SqlBuffer.StorageType.SqlBinary, // Binary + SqlBuffer.StorageType.Boolean, // Bit + SqlBuffer.StorageType.String, // Char + SqlBuffer.StorageType.DateTime, // DateTime + SqlBuffer.StorageType.Decimal, // Decimal + SqlBuffer.StorageType.Double, // Float + SqlBuffer.StorageType.SqlBinary, // Image + SqlBuffer.StorageType.Int32, // Int + SqlBuffer.StorageType.Money, // Money + SqlBuffer.StorageType.String, // NChar + SqlBuffer.StorageType.String, // NText + SqlBuffer.StorageType.String, // NVarChar + SqlBuffer.StorageType.Single, // Real + SqlBuffer.StorageType.SqlGuid, // UniqueIdentifier + SqlBuffer.StorageType.DateTime, // SmallDateTime + SqlBuffer.StorageType.Int16, // SmallInt + SqlBuffer.StorageType.Money, // SmallMoney + SqlBuffer.StorageType.String, // Text + SqlBuffer.StorageType.SqlBinary, // Timestamp + SqlBuffer.StorageType.Byte, // TinyInt + SqlBuffer.StorageType.SqlBinary, // VarBinary + SqlBuffer.StorageType.String, // VarChar + SqlBuffer.StorageType.Empty, // Variant + SqlBuffer.StorageType.Empty, // 24 + SqlBuffer.StorageType.SqlXml, // Xml + SqlBuffer.StorageType.Empty, // 26 + SqlBuffer.StorageType.Empty, // 27 + SqlBuffer.StorageType.Empty, // 28 + SqlBuffer.StorageType.Empty, // Udt + SqlBuffer.StorageType.Empty, // Structured + SqlBuffer.StorageType.Date, // Date + SqlBuffer.StorageType.Time, // Time + SqlBuffer.StorageType.DateTime2, // DateTime2 + SqlBuffer.StorageType.DateTimeOffset, // DateTimeOffset + }; + + internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record) + { + FillCompatibleITypedSettersFromRecord(sink, setters, metaData, record, null); + } + + internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) + { + for (int i = 0; i < metaData.Length; ++i) + { + if (null != useDefaultValues && useDefaultValues[i]) + { + continue; + } + if (record.IsDBNull(i)) + { + ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); + } + else + { + switch (metaData[i].SqlDbType) + { + case SqlDbType.BigInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); + SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); + break; + case SqlDbType.Binary: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Bit: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); + SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); + break; + case SqlDbType.Char: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.DateTime: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); + SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); + break; + case SqlDbType.Decimal: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); + SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); + break; + case SqlDbType.Float: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); + SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); + break; + case SqlDbType.Image: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Int: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); + SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); + break; + case SqlDbType.Money: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); + SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); + break; + case SqlDbType.NChar: + case SqlDbType.NText: + case SqlDbType.NVarChar: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Real: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); + SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); + break; + case SqlDbType.UniqueIdentifier: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); + SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); + break; + case SqlDbType.SmallDateTime: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); + SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); + break; + case SqlDbType.SmallInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); + SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); + break; + case SqlDbType.SmallMoney: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); + SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); + break; + case SqlDbType.Text: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Timestamp: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.TinyInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); + SetByte_Unchecked(sink, setters, i, record.GetByte(i)); + break; + case SqlDbType.VarBinary: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.VarChar: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Xml: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); + SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? + break; + case SqlDbType.Variant: + object o = record.GetSqlValue(i); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); + SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); + break; + case SqlDbType.Udt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + default: + Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString()); + throw ADP.NotSupported(); + } + } + } + } + + // spool a Stream into a scratch stream from the Smi interface and return it as a SqlStreamChars + internal static SqlStreamChars CopyIntoNewSmiScratchStreamChars(Stream source, SmiEventSink_Default sink, SmiContext context) + { + SqlClientWrapperSmiStreamChars dest = new(sink, context.GetScratchStream(sink)); + + int chunkSize; + if (source.CanSeek && __maxByteChunkSize > source.Length) + { + chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above + } + else + { + chunkSize = __maxByteChunkSize; + } + + byte[] copyBuffer = new byte[chunkSize]; + int bytesRead; + while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) + { + dest.Write(copyBuffer, 0, bytesRead); + } + dest.Flush(); + + // SQLBU 494334 + // Need to re-wind scratch stream to beginning before returning + dest.Seek(0, SeekOrigin.Begin); + + return dest; + } + + } +}