|
//------------------------------------------------------------------------------
// <copyright file="ValueUtilsSmi.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Sql;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;
// 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 {
const int __maxByteChunkSize = TdsEnums.MAXSIZE;
const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char);
const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator; // make sure we use the same constant
// Constants
const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
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 (Boolean)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 Int16 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 (Int16) obj;
}
internal static Int32 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 (Int32) result;
}
internal static Int64 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 (Int64) result;
}
internal static Single 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 (Single) 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 );
result = new SqlChars( sc );
}
}
}
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 {
Int16 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 {
Int32 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 {
Int64 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 {
Single 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 = __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 = __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[] __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, Boolean value ) {
SetDBNull_Unchecked( sink, setters, ordinal );
}
internal static void SetBoolean( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Boolean 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( "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( "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, Int16 value ) {
ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int16 );
SetInt16_Unchecked( sink, setters, ordinal, value );
}
internal static void SetInt32( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int32 value ) {
ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int32 );
SetInt32_Unchecked( sink, setters, ordinal, value );
}
internal static void SetInt64( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Int64 value ) {
ThrowIfInvalidSetterAccess( metaData, ExtendedClrTypeCode.Int64 );
SetInt64_Unchecked( sink, setters, ordinal, value );
}
internal static void SetSingle( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Single 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, (Boolean) 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, (Int16) value ); break;
case ExtendedClrTypeCode.Int32: SetInt32_Unchecked( sink, setters, ordinal, (Int32) value ); break;
case ExtendedClrTypeCode.Int64: SetInt64_Unchecked( sink, setters, ordinal, (Int64) value ); break;
case ExtendedClrTypeCode.SByte: throw ADP.InvalidCast();
case ExtendedClrTypeCode.Single: SetSingle_Unchecked( sink, setters, ordinal, (Single) 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.Assert( false, "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<SqlDataRecord>)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 - it must be bug in our code
// not invalid user parameters.
Debug.Assert( false, "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<SmiExtendedMetaData> 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,
//
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 - it must be bug in our code
// not invalid user parameters.
Debug.Assert(false, "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.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 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, new Object[]{}, 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 x_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998);
private static readonly DateTime x_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999);
private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) {
if (SqlDbType.SmallDateTime == dbType && (x_dtSmallMax < value || x_dtSmallMin > value)) {
throw ADP.InvalidMetaDataValue();
}
}
private static readonly TimeSpan x_timeMin = TimeSpan.Zero;
private static readonly TimeSpan x_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1);
private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) {
if (SqlDbType.Time == dbType && (x_timeMin > value || value > x_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 > Int32.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 > Int32.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 > Int32.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 > Int32.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 {
System.IO.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 == __canAccessGetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessGetterDirectly" );
Debug.Assert( SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == __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 = __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 == __canAccessSetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessSetterDirectly" );
Debug.Assert( SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == __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 = __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("fieldOffset");
// if negative buffer index, throw
if ( bufferOffset < 0 ) {
throw ADP.InvalidDestinationBufferIndex( bufferLength, bufferOffset, "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, "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[,] __canAccessGetterDirectly = {
// SqlDbTypes as columns (abreviated, 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<SqlDataRecord>*/
/*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[,] __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<SqlDataRecord>*/
/*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, string.Format("Invalid ordinal: {0}", ordinal));
Debug.Assert(sink != null, "Null SmiEventSink");
Debug.Assert(getters != null, "Null getters");
Debug.Assert(fieldOffset >= 0, string.Format("Invalid field offset: {0}", fieldOffset));
Debug.Assert(buffer != null, "Null buffer");
Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, string.Format("Bad offset or length. bufferOffset: {0}, length: {1}, buffer.Length{2}", bufferOffset, 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, string.Format("Invalid ordinal: {0}", ordinal));
Debug.Assert(sink != null, "Null SmiEventSink");
Debug.Assert(getters != null, "Null getters");
Debug.Assert(fieldOffset >= 0, string.Format("Invalid field offset: {0}", fieldOffset));
Debug.Assert(buffer != null, "Null buffer");
Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, string.Format("Bad offset or length. bufferOffset: {0}, length: {1}, buffer.Length{2}", bufferOffset, 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 Int16 GetInt16_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
Int16 result = getters.GetInt16( sink, ordinal );
sink.ProcessMessagesAndThrow();
return result;
}
private static Int32 GetInt32_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
Int32 result = getters.GetInt32( sink, ordinal );
sink.ProcessMessagesAndThrow();
return result;
}
private static Int64 GetInt64_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
Int64 result = getters.GetInt64( sink, ordinal );
sink.ProcessMessagesAndThrow();
return result;
}
private static Single GetSingle_Unchecked( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal ) {
Debug.Assert( !IsDBNull_Unchecked( sink, getters, ordinal ) );
Single 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 ) );
Int64 temp = getters.GetInt64( sink, ordinal );
sink.ProcessMessagesAndThrow();
return new SqlMoney( 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, Boolean 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, Int16 value ) {
setters.SetInt16( sink, ordinal, value );
sink.ProcessMessagesAndThrow();
}
private static void SetInt32_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Int32 value ) {
setters.SetInt32( sink, ordinal, value );
sink.ProcessMessagesAndThrow();
}
private static void SetInt64_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Int64 value ) {
setters.SetInt64( sink, ordinal, value );
sink.ProcessMessagesAndThrow();
}
private static void SetSingle_Unchecked( SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Single 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, value.ToSqlInternalRepresentation() );
}
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,
//
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<SqlDataRecord> value,
ParameterPeekAheadValue peekAhead
) {
// Get target gettersetter
setters = setters.GetTypedGetterSetter(sink, ordinal);
sink.ProcessMessagesAndThrow();
IEnumerator<SqlDataRecord> 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();
}
}
}
}
}
|