Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <copyright file="ExtendedClrTypeCode.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
internal enum ExtendedClrTypeCode {
Invalid = -1,
Boolean, // System.Boolean
Byte, // System.Byte
Char, // System.Char
DateTime, // System.DateTime
DBNull, // System.DBNull
Decimal, // System.Decimal
Double, // System.Double
Empty, // null reference
Int16, // System.Int16
Int32, // System.Int32
Int64, // System.Int64
SByte, // System.SByte
Single, // System.Single
String, // System.String
UInt16, // System.UInt16
UInt32, // System.UInt32
UInt64, // System.UInt64
Object, // System.Object
ByteArray, // System.ByteArray
CharArray, // System.CharArray
Guid, // System.Guid
SqlBinary, // System.Data.SqlTypes.SqlBinary
SqlBoolean, // System.Data.SqlTypes.SqlBoolean
SqlByte, // System.Data.SqlTypes.SqlByte
SqlDateTime, // System.Data.SqlTypes.SqlDateTime
SqlDouble, // System.Data.SqlTypes.SqlDouble
SqlGuid, // System.Data.SqlTypes.SqlGuid
SqlInt16, // System.Data.SqlTypes.SqlInt16
SqlInt32, // System.Data.SqlTypes.SqlInt32
SqlInt64, // System.Data.SqlTypes.SqlInt64
SqlMoney, // System.Data.SqlTypes.SqlMoney
SqlDecimal, // System.Data.SqlTypes.SqlDecimal
SqlSingle, // System.Data.SqlTypes.SqlSingle
SqlString, // System.Data.SqlTypes.SqlString
SqlChars, // System.Data.SqlTypes.SqlChars
SqlBytes, // System.Data.SqlTypes.SqlBytes
SqlXml, // System.Data.SqlTypes.SqlXml
DataTable, // System.Data.DataTable
DbDataReader, // System.Data.DbDataReader (SqlDataReader falls under this category)
IEnumerableOfSqlDataRecord, // System.Collections.Generic.IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord>
TimeSpan, // System.TimeSpan
DateTimeOffset, // System.DateTimeOffset
Stream, // System.IO.Stream
TextReader, // System.IO.TextReader
XmlReader, // System.Xml.XmlReader
Last = XmlReader, // end-of-enum marker
First = Boolean, // beginning-of-enum marker
};
}

View File

@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
// <copyright file="ITypedGetters.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
using System.Data.SqlTypes;
// Interface for strongly-typed value getters
internal interface ITypedGetters {
// Null test
bool IsDBNull( int ordinal );
// Check what type current sql_variant value is
SqlDbType GetVariantType( int ordinal );
// By value accessors (data copy across the interface boundary implied)
Boolean GetBoolean( int ordinal );
Byte GetByte( int ordinal );
Int64 GetBytes( int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length );
Char GetChar( int ordinal );
Int64 GetChars( int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length );
Int16 GetInt16( int ordinal );
Int32 GetInt32( int ordinal );
Int64 GetInt64( int ordinal );
Single GetFloat( int ordinal );
Double GetDouble( int ordinal );
String GetString( int ordinal );
Decimal GetDecimal( int ordinal );
DateTime GetDateTime( int ordinal );
Guid GetGuid( int ordinal );
SqlBoolean GetSqlBoolean( int ordinal );
SqlByte GetSqlByte( int ordinal );
SqlInt16 GetSqlInt16( int ordinal );
SqlInt32 GetSqlInt32( int ordinal );
SqlInt64 GetSqlInt64( int ordinal );
SqlSingle GetSqlSingle( int ordinal );
SqlDouble GetSqlDouble( int ordinal );
SqlMoney GetSqlMoney( int ordinal );
SqlDateTime GetSqlDateTime( int ordinal );
SqlDecimal GetSqlDecimal( int ordinal );
SqlString GetSqlString( int ordinal );
SqlBinary GetSqlBinary( int ordinal );
SqlGuid GetSqlGuid( int ordinal );
SqlChars GetSqlChars( int ordinal );
SqlBytes GetSqlBytes( int ordinal );
SqlXml GetSqlXml( int ordinal );
// "By reference" accessors
// May hook to buffer.
// Semantics guarantee is that as long as the object exposing the accessor is not logically
// moved to a new set of values and the overall state (open/closed) isn't changed, it will not
// change the underlying value returned and continue to allow access to it.
//
// Example: GetSqlCharsRef called on an event stream value. The back-end optimizes by re-using
// the buffer wrapped by the returned SqlChars on the next row event, but guarantees that it
// won't change the value until the next event is consumed.
//
// Simplest way to guarantee this behavior is to simply call the corresponding by-value accessor.
SqlBytes GetSqlBytesRef( int ordinal );
SqlChars GetSqlCharsRef( int ordinal );
SqlXml GetSqlXmlRef( int ordinal );
}
}

View File

@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <copyright file="ITypedGettersV3.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
using System.Data.SqlTypes;
// Interface for strongly-typed value getters
internal interface ITypedGettersV3 {
// Null test
// valid for all types
bool IsDBNull( SmiEventSink sink, int ordinal );
// Check what type current sql_variant value is
// valid for SqlDbType.Variant
SmiMetaData GetVariantType( SmiEventSink sink, int ordinal );
//
// Actual value accessors
// valid type indicates column must be of the type or column must be variant
// and GetVariantType returned the type
//
// valid for SqlDbType.Bit
Boolean GetBoolean( SmiEventSink sink, int ordinal );
// valid for SqlDbType.TinyInt
Byte GetByte( SmiEventSink sink, int ordinal );
// valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml, Char, VarChar, Text, NChar, NVarChar, NText
// (Character type support needed for ExecuteXmlReader handling)
Int64 GetBytesLength( SmiEventSink sink, int ordinal );
int GetBytes( SmiEventSink sink, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length );
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
Int64 GetCharsLength( SmiEventSink sink, int ordinal );
int GetChars( SmiEventSink sink, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length );
String GetString( SmiEventSink sink, int ordinal );
// valid for SqlDbType.SmallInt
Int16 GetInt16( SmiEventSink sink, int ordinal );
// valid for SqlDbType.Int
Int32 GetInt32( SmiEventSink sink, int ordinal );
// valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney
Int64 GetInt64( SmiEventSink sink, int ordinal );
// valid for SqlDbType.Real
Single GetSingle( SmiEventSink sink, int ordinal );
// valid for SqlDbType.Float
Double GetDouble( SmiEventSink sink, int ordinal );
// valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range)
SqlDecimal GetSqlDecimal( SmiEventSink sink, int ordinal );
// valid for DateTime & SmallDateTime
DateTime GetDateTime( SmiEventSink sink, int ordinal );
// valid for UniqueIdentifier
Guid GetGuid( SmiEventSink sink, int ordinal );
}
}

View File

@@ -0,0 +1,100 @@
//------------------------------------------------------------------------------
// <copyright file="ITypedSetters.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data.SqlTypes;
// interface for strongly-typed value setters
internal interface ITypedSetters {
// By value setters (data copy across the interface boundary implied)
void SetDBNull( int ordinal );
void SetBoolean( int ordinal, Boolean value );
void SetByte( int ordinal, Byte value );
void SetBytes( int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length );
void SetChar( int ordinal, char value );
void SetChars( int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length );
void SetInt16( int ordinal, Int16 value );
void SetInt32( int ordinal, Int32 value );
void SetInt64( int ordinal, Int64 value );
void SetFloat( int ordinal, Single value );
void SetDouble( int ordinal, Double value );
[ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use setter with offset." )]
void SetString( int ordinal, string value );
// Method introduced as of SMI V2
void SetString( int ordinal, string value, int offset );
void SetDecimal( int ordinal, Decimal value );
void SetDateTime( int ordinal, DateTime value );
void SetGuid( int ordinal, Guid value );
void SetSqlBoolean( int ordinal, SqlBoolean value );
void SetSqlByte( int ordinal, SqlByte value );
void SetSqlInt16( int ordinal, SqlInt16 value );
void SetSqlInt32( int ordinal, SqlInt32 value );
void SetSqlInt64( int ordinal, SqlInt64 value );
void SetSqlSingle( int ordinal, SqlSingle value );
void SetSqlDouble( int ordinal, SqlDouble value );
void SetSqlMoney( int ordinal, SqlMoney value );
void SetSqlDateTime( int ordinal, SqlDateTime value );
void SetSqlDecimal( int ordinal, SqlDecimal value );
[ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use setter with offset." )]
void SetSqlString( int ordinal, SqlString value );
// Method introduced as of SMI V2
void SetSqlString( int ordinal, SqlString value, int offset );
[ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use setter with offset." )]
void SetSqlBinary( int ordinal, SqlBinary value );
// Method introduced as of SMI V2
void SetSqlBinary( int ordinal, SqlBinary value, int offset );
void SetSqlGuid( int ordinal, SqlGuid value );
[ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use setter with offset." )]
void SetSqlChars( int ordinal, SqlChars value );
// Method introduced as of SMI V2
void SetSqlChars( int ordinal, SqlChars value, int offset );
[ObsoleteAttribute( "Not supported as of SMI v2. Will be removed when v1 support dropped. Use setter with offset." )]
void SetSqlBytes( int ordinal, SqlBytes value );
// Method introduced as of SMI V2
void SetSqlBytes( int ordinal, SqlBytes value, int offset );
void SetSqlXml( int ordinal, SqlXml value );
}
}

View File

@@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// <copyright file="ITypedSettersV3.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data.SqlTypes;
// interface for strongly-typed value setters
internal interface ITypedSettersV3 {
// By value setters (data copy across the interface boundary implied)
// All setters are valid for SqlDbType.Variant
// SetVariantMetaData is used to set the precise type of data just before pushing
// data into a variant type via one one of the other setters. It
// is only valid to set metadata with a SqlDbType that associated with with the
// data setter that will be called.
// Since LOBs, Udt's and fixed-length types are not currently stored in a variant,
// the following pairs are the only setters/sqldbtypes that need this call:
// NVarChar/VarChar + SetString (needed only for non-global collation, i.e. SqlString)
// Money/SmallMoney + SetInt64
void SetVariantMetaData( SmiEventSink sink, int ordinal, SmiMetaData metaData );
// Set value to null
// valid for all types
void SetDBNull( SmiEventSink sink, int ordinal );
// valid for SqlDbType.Bit
void SetBoolean( SmiEventSink sink, int ordinal, Boolean value );
// valid for SqlDbType.TinyInt
void SetByte( SmiEventSink sink, int ordinal, Byte value );
// Semantics for SetBytes are to modify existing value, not overwrite
// Use in combination with SetLength to ensure overwriting when necessary
// valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml
// (VarBinary assumed for variants)
int SetBytes( SmiEventSink sink, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length );
void SetBytesLength( SmiEventSink sink, int ordinal, long length );
// Semantics for SetChars are to modify existing value, not overwrite
// Use in combination with SetLength to ensure overwriting when necessary
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
// (NVarChar and global clr collation assumed for variants)
int SetChars( SmiEventSink sink, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length );
void SetCharsLength( SmiEventSink sink, int ordinal, long length );
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
void SetString( SmiEventSink sink, int ordinal, string value, int offset, int length );
// valid for SqlDbType.SmallInt
void SetInt16( SmiEventSink sink, int ordinal, Int16 value );
// valid for SqlDbType.Int
void SetInt32( SmiEventSink sink, int ordinal, Int32 value );
// valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney
void SetInt64( SmiEventSink sink, int ordinal, Int64 value );
// valid for SqlDbType.Real
void SetSingle( SmiEventSink sink, int ordinal, Single value );
// valid for SqlDbType.Float
void SetDouble( SmiEventSink sink, int ordinal, Double value );
// valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range)
void SetSqlDecimal( SmiEventSink sink, int ordinal, SqlDecimal value );
// valid for DateTime & SmallDateTime
void SetDateTime( SmiEventSink sink, int ordinal, DateTime value );
// valid for UniqueIdentifier
void SetGuid( SmiEventSink sink, int ordinal, Guid value );
}
}

View File

@@ -0,0 +1,227 @@
//------------------------------------------------------------------------------
// <copyright file="MemoryRecordBuffer.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data.SqlTypes;
using System.Diagnostics;
// Class for implementing a record object used in out-of-proc scenarios.
internal sealed class MemoryRecordBuffer : SmiRecordBuffer {
private SqlRecordBuffer[] _buffer;
internal MemoryRecordBuffer(SmiMetaData[] metaData) {
Debug.Assert(null != metaData, "invalid attempt to instantiate MemoryRecordBuffer with null SmiMetaData[]");
_buffer = new SqlRecordBuffer[metaData.Length];
for (int i = 0; i < _buffer.Length; ++i) {
_buffer[i] = new SqlRecordBuffer(metaData[i]);
}
}
#region Getters
// Null test
// valid for all types
public override bool IsDBNull(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].IsNull;
}
// Check what type current sql_variant value is
// valid for SqlDbType.Variant
public override SmiMetaData GetVariantType(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].VariantType;
}
// valid for SqlDbType.Bit
public override Boolean GetBoolean(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Boolean;
}
// valid for SqlDbType.TinyInt
public override Byte GetByte(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Byte;
}
// valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml, Char, VarChar, Text, NChar, NVarChar, NText
// (Character type support needed for ExecuteXmlReader handling)
public override Int64 GetBytesLength(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].BytesLength;
}
public override int GetBytes(SmiEventSink sink, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) {
return _buffer[ordinal].GetBytes(fieldOffset, buffer, bufferOffset, length);
}
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
public override Int64 GetCharsLength(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].CharsLength;
}
public override int GetChars(SmiEventSink sink, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) {
return _buffer[ordinal].GetChars(fieldOffset, buffer, bufferOffset, length);
}
public override String GetString(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].String;
}
// valid for SqlDbType.SmallInt
public override Int16 GetInt16(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Int16;
}
// valid for SqlDbType.Int
public override Int32 GetInt32(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Int32;
}
// valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney
public override Int64 GetInt64(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Int64;
}
// valid for SqlDbType.Real
public override Single GetSingle(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Single;
}
// valid for SqlDbType.Float
public override Double GetDouble(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Double;
}
// valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range)
public override SqlDecimal GetSqlDecimal(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].SqlDecimal;
}
// valid for DateTime, SmallDateTime, Date, and DateTime2
public override DateTime GetDateTime(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].DateTime;
}
// valid for UniqueIdentifier
public override Guid GetGuid(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].Guid;
}
// valid for SqlDbType.Time
public override TimeSpan GetTimeSpan(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].TimeSpan;
}
// valid for DateTimeOffset
public override DateTimeOffset GetDateTimeOffset(SmiEventSink sink, int ordinal) {
return _buffer[ordinal].DateTimeOffset;
}
#endregion
#region Setters
// Set value to null
// valid for all types
public override void SetDBNull(SmiEventSink sink, int ordinal) {
_buffer[ordinal].SetNull();
}
// valid for SqlDbType.Bit
public override void SetBoolean(SmiEventSink sink, int ordinal, Boolean value) {
_buffer[ordinal].Boolean = value;
}
// valid for SqlDbType.TinyInt
public override void SetByte(SmiEventSink sink, int ordinal, Byte value) {
_buffer[ordinal].Byte = value;
}
// Semantics for SetBytes are to modify existing value, not overwrite
// Use in combination with SetLength to ensure overwriting when necessary
// valid for SqlDbTypes: Binary, VarBinary, Image, Udt, Xml
// (VarBinary assumed for variants)
public override int SetBytes(SmiEventSink sink, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) {
return _buffer[ordinal].SetBytes(fieldOffset, buffer, bufferOffset, length);
}
public override void SetBytesLength(SmiEventSink sink, int ordinal, long length) {
_buffer[ordinal].BytesLength = length;
}
// Semantics for SetChars are to modify existing value, not overwrite
// Use in combination with SetLength to ensure overwriting when necessary
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
// (NVarChar and global clr collation assumed for variants)
public override int SetChars(SmiEventSink sink, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) {
return _buffer[ordinal].SetChars(fieldOffset, buffer, bufferOffset, length);
}
public override void SetCharsLength(SmiEventSink sink, int ordinal, long length) {
_buffer[ordinal].CharsLength = length;
}
// valid for character types: Char, VarChar, Text, NChar, NVarChar, NText
public override void SetString(SmiEventSink sink, int ordinal, string value, int offset, int length) {
Debug.Assert(offset == 0 && length <= value.Length, "Invalid string length or offset"); // for sqlvariant, length could be less than value.Length
_buffer[ordinal].String = value.Substring(offset, length); // Perf test shows that Substring method has already optimized the case where length = value.Length
}
// valid for SqlDbType.SmallInt
public override void SetInt16(SmiEventSink sink, int ordinal, Int16 value) {
_buffer[ordinal].Int16 = value;
}
// valid for SqlDbType.Int
public override void SetInt32(SmiEventSink sink, int ordinal, Int32 value) {
_buffer[ordinal].Int32 = value;
}
// valid for SqlDbType.BigInt, SqlDbType.Money, SqlDbType.SmallMoney
public override void SetInt64(SmiEventSink sink, int ordinal, Int64 value) {
_buffer[ordinal].Int64 = value;
}
// valid for SqlDbType.Real
public override void SetSingle(SmiEventSink sink, int ordinal, Single value) {
_buffer[ordinal].Single = value;
}
// valid for SqlDbType.Float
public override void SetDouble(SmiEventSink sink, int ordinal, Double value) {
_buffer[ordinal].Double = value;
}
// valid for SqlDbType.Numeric (uses SqlDecimal since Decimal cannot hold full range)
public override void SetSqlDecimal(SmiEventSink sink, int ordinal, SqlDecimal value) {
_buffer[ordinal].SqlDecimal = value;
}
// valid for DateTime, SmallDateTime, Date, and DateTime2
public override void SetDateTime(SmiEventSink sink, int ordinal, DateTime value) {
_buffer[ordinal].DateTime = value;
}
// valid for UniqueIdentifier
public override void SetGuid(SmiEventSink sink, int ordinal, Guid value) {
_buffer[ordinal].Guid = value;
}
// SqlDbType.Time
public override void SetTimeSpan(SmiEventSink sink, int ordinal, TimeSpan value) {
_buffer[ordinal].TimeSpan = value;
}
// DateTimeOffset
public override void SetDateTimeOffset(SmiEventSink sink, int ordinal, DateTimeOffset value) {
_buffer[ordinal].DateTimeOffset = value;
}
// valid for SqlDbType.Variant
public override void SetVariantMetaData(SmiEventSink sink, int ordinal, SmiMetaData metaData) {
_buffer[ordinal].VariantType = metaData;
}
#endregion
}
}

View File

@@ -0,0 +1,99 @@
//------------------------------------------------------------------------------
// <copyright file="SmiConnection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
internal abstract class SmiConnection : IDisposable {
//
// Miscellaneous directives / accessors
//
internal abstract string GetCurrentDatabase(
SmiEventSink eventSink
);
internal abstract void SetCurrentDatabase (
string databaseName,
SmiEventSink eventSink
);
//
// IDisposable
//
public virtual void Dispose( ) {
// Obsoleting from SMI -- use Close( SmiEventSink ) instead.
// Intended to be removed (along with inheriting IDisposable) prior to RTM.
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V3+ and dropped support for V2-.
// 2) Server didn't implement V2- on some interface and negotiated V2-.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
public virtual void Close(
SmiEventSink eventSink
) {
// Adding as of V3
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V2- and hasn't implemented V3 yet.
// 2) Server didn't implement V3 on some interface, but negotiated V3+.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
//
// Transaction API (should we encapsulate in it's own class or interface?)
//
internal abstract void BeginTransaction (
string name,
IsolationLevel level,
SmiEventSink eventSink
);
internal abstract void CommitTransaction (
long transactionId,
SmiEventSink eventSink
);
internal abstract void CreateTransactionSavePoint (
long transactionId,
string name,
SmiEventSink eventSink
);
internal abstract byte[] GetDTCAddress( // better buffer management needed? I.e. non-allocating call needed/possible?
SmiEventSink eventSink
);
internal abstract void EnlistTransaction (
byte[] token, // better buffer management needed? I.e. non-allocating call needed/possible?
SmiEventSink eventSink
);
internal abstract byte[] PromoteTransaction ( // better buffer management needed? I.e. non-allocating call needed/possible?
long transactionId,
SmiEventSink eventSink
);
internal abstract void RollbackTransaction (
long transactionId,
string savePointName, // only roll back to save point if name non-null
SmiEventSink eventSink
);
}
}

View File

@@ -0,0 +1,79 @@
//------------------------------------------------------------------------------
// <copyright file="SmiContext.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
using System.Data.Sql;
using System.Data.SqlTypes;
using System.Security.Principal;
// NOTE: connection, transaction and context pipe operations could be
// encapsulated in their own classes, and should if they get complex
// (transaction is borderline at this point).
internal abstract class SmiContext {
internal abstract event EventHandler OutOfScope;
internal abstract SmiConnection ContextConnection { get; }
internal abstract long ContextTransactionId { get; }
internal abstract System.Transactions.Transaction ContextTransaction { get; }
internal abstract bool HasContextPipe { get; }
internal abstract WindowsIdentity WindowsIdentity { get; }
internal abstract SmiRecordBuffer CreateRecordBuffer (
SmiExtendedMetaData[] columnMetaData, // Extended metadata because it requires names, udttypename and xmlschemaname ignored
SmiEventSink eventSink
);
internal abstract SmiRequestExecutor CreateRequestExecutor (
string commandText,
CommandType commandType,
SmiParameterMetaData[] parameterMetaData,
SmiEventSink eventSink
);
//
internal abstract object GetContextValue ( int key );
internal abstract void GetTriggerInfo (
SmiEventSink eventSink,
out bool[] columnsUpdated,
out TriggerAction action,
out SqlXml eventInstanceData
);
internal abstract void SendMessageToPipe( string message, SmiEventSink eventSink );
internal abstract void SendResultsStartToPipe( SmiRecordBuffer recordBuffer, SmiEventSink eventSink );
internal abstract void SendResultsRowToPipe( SmiRecordBuffer recordBuffer, SmiEventSink eventSink );
internal abstract void SendResultsEndToPipe( SmiRecordBuffer recordBuffer, SmiEventSink eventSink );
internal abstract void SetContextValue ( int key, object value );
// Scratch LOB storage region
internal virtual SmiStream GetScratchStream( SmiEventSink sink ) {
// Adding as of V3
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V2- and hasn't implemented V3 yet.
// 2) Server didn't implement V3, but negotiated V3+.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
return null;
}
}
}

View File

@@ -0,0 +1,137 @@
//------------------------------------------------------------------------------
// <copyright file="SmiContextFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
sealed internal class SmiContextFactory {
public static readonly SmiContextFactory Instance = new SmiContextFactory();
private readonly SmiLink _smiLink;
private readonly ulong _negotiatedSmiVersion;
private readonly byte _majorVersion;
private readonly byte _minorVersion;
private readonly short _buildNum;
private readonly string _serverVersion;
private readonly SmiEventSink_Default _eventSinkForGetCurrentContext;
internal const ulong YukonVersion = 100;
internal const ulong KatmaiVersion = 210;
internal const ulong LatestVersion = KatmaiVersion;
private readonly ulong[] __supportedSmiVersions = new ulong[] {YukonVersion, KatmaiVersion};
// Used as the key for SmiContext.GetContextValue()
internal enum ContextKey {
Connection = 0,
SqlContext = 1
}
private SmiContextFactory() {
if (InOutOfProcHelper.InProc) {
Type smiLinkType = Type.GetType("Microsoft.SqlServer.Server.InProcLink, SqlAccess, PublicKeyToken=89845dcd8080cc91");
if (null == smiLinkType) {
Debug.Assert(false, "could not get InProcLink type");
throw SQL.ContextUnavailableOutOfProc(); // Must not be a valid version of Sql Server.
}
System.Reflection.FieldInfo instanceField = GetStaticField(smiLinkType, "Instance");
if (instanceField != null) {
_smiLink = (SmiLink)GetValue(instanceField);
}
else {
Debug.Assert(false, "could not get InProcLink.Instance");
throw SQL.ContextUnavailableOutOfProc(); // Must not be a valid version of Sql Server.
}
System.Reflection.FieldInfo buildVersionField = GetStaticField(smiLinkType, "BuildVersion");
if (buildVersionField != null) {
UInt32 buildVersion = (UInt32)GetValue(buildVersionField);
_majorVersion = (byte)(buildVersion >> 24);
_minorVersion = (byte)((buildVersion >> 16) & 0xff);
_buildNum = (short)(buildVersion & 0xffff);
_serverVersion = (String.Format((IFormatProvider)null, "{0:00}.{1:00}.{2:0000}", _majorVersion, (short) _minorVersion, _buildNum));
}
else {
_serverVersion = String.Empty; // default value if nothing exists.
}
_negotiatedSmiVersion = _smiLink.NegotiateVersion(SmiLink.InterfaceVersion);
bool isSupportedVersion = false;
for(int i=0; !isSupportedVersion && i<__supportedSmiVersions.Length; i++) {
if (__supportedSmiVersions[i] == _negotiatedSmiVersion) {
isSupportedVersion = true;
}
}
// Disconnect if we didn't get a supported version!!
if (!isSupportedVersion) {
_smiLink = null;
}
_eventSinkForGetCurrentContext = new SmiEventSink_Default();
}
}
internal ulong NegotiatedSmiVersion {
get {
if (null == _smiLink) {
throw SQL.ContextUnavailableOutOfProc(); // Must not be a valid version of Sql Server, or not be SqlCLR
}
return _negotiatedSmiVersion;
}
}
internal string ServerVersion {
get {
if (null == _smiLink) {
throw SQL.ContextUnavailableOutOfProc(); // Must not be a valid version of Sql Server, or not be SqlCLR
}
return _serverVersion;
}
}
internal SmiContext GetCurrentContext() {
if (null == _smiLink) {
throw SQL.ContextUnavailableOutOfProc(); // Must not be a valid version of Sql Server, or not be SqlCLR
}
object result = _smiLink.GetCurrentContext(_eventSinkForGetCurrentContext);
_eventSinkForGetCurrentContext.ProcessMessagesAndThrow();
if (null == result) {
throw SQL.ContextUnavailableWhileInProc();
}
Debug.Assert(typeof(SmiContext).IsInstanceOfType(result), "didn't get SmiContext from GetCurrentContext?");
return (SmiContext)result;
}
[System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
private object GetValue(System.Reflection.FieldInfo fieldInfo) {
object result = fieldInfo.GetValue(null);
return result;
}
[System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess=true)]
private System.Reflection.FieldInfo GetStaticField(Type aType, string fieldName) {
System.Reflection.FieldInfo result = aType.GetField(fieldName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.GetField);
return result;
}
}
}

View File

@@ -0,0 +1,131 @@
//------------------------------------------------------------------------------
// <copyright file="SmiEventSink.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
using System.Data.Sql;
// SqlEventSink is implemented by calling code. In all methods that accept
// a SqlEventSink directly the sink must be able to handle multiple callbacks
// without control returning from the original call.
// Methods that do not accept SmiEventSync are (generally) ProcessEvent on
// the SmiEventStream methods returning a SmiEventStream and methods that
// are certain to never call to the server (most will, for in-proc back end).
// Methods are commented with their corresponding TDS token
// NOTE: Throwing from these methods will not usually produce the desired
// effect -- the managed to native boundary will eat any exceptions,
// and will cause a simple "Something bad happened" exception to be
// thrown in the native to managed boundary...
internal abstract class SmiEventSink {
#region Active methods
// Called at end of stream whether errors or no
internal abstract void BatchCompleted( );
// Called zero or one time when output parameters are available (errors could prevent event from occuring)
internal virtual void ParameterAvailable(SmiParameterMetaData metaData, SmiTypedGetterSetter paramValue, int ordinal) {
// Adding as of V200
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V3- and hasn't implemented V200 yet.
// 2) Server didn't implement V200 on some interface, but negotiated V200+.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
// Called when the server database context changes (ENVCHANGE token)
internal abstract void DefaultDatabaseChanged( string databaseName );
// Called for messages and errors (ERROR and INFO tokens)
internal abstract void MessagePosted ( int number, byte state, byte errorClass, string server, string message, string procedure, int lineNumber );
// Called for new resultset starting (COLMETADATA token)
internal abstract void MetaDataAvailable( SmiQueryMetaData[] metaData, bool nextEventIsRow );
internal virtual void RowAvailable(SmiTypedGetterSetter rowData) {
// Adding as of V200
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V3- and hasn't implemented V200 yet.
// 2) Server didn't implement V200 on some interface, but negotiated V200+.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
// Called when any statement completes on server (DONE token)
internal abstract void StatementCompleted( int rowsAffected );
// Called when a transaction is commited (ENVCHANGE token)
internal abstract void TransactionCommitted( long transactionId );
// Called when a transaction is commited (ENVCHANGE token)
internal abstract void TransactionDefected( long transactionId );
// Called when a transaction is commited (ENVCHANGE token)
internal abstract void TransactionEnlisted( long transactionId );
// Called when a transaction is forcibly ended in the server, not requested
// by the provider's batch (ENVCHANGE token)
internal abstract void TransactionEnded( long transactionId );
// Called when a transaction is rolled back (ENVCHANGE token)
internal abstract void TransactionRolledBack( long transactionId );
// Called when a transaction is started (ENVCHANGE token)
internal abstract void TransactionStarted( long transactionId );
#endregion
#region OBSOLETE METHODS
#region OBSOLETED as of V200 but active in previous version
// Called zero or one time when output parameters are available (errors could prevent event from occuring)
internal virtual void ParametersAvailable( SmiParameterMetaData[] metaData, ITypedGettersV3 paramValues ) {
// Adding as of V3
// Obsoleting as of V200
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V200+ and dropped support for V200-.
// 2) Server didn't implement V3- on some interface and negotiated V3-.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
// Called when a new row arrives (ROW token)
internal virtual void RowAvailable( ITypedGettersV3 rowData ) {
// Adding as of V3
// Obsoleting as of V200
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V200+ and dropped support for V200-.
// 2) Server didn't implement V3- on some interface and negotiated V3-.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
#endregion
#region OBSOLETED and never shipped (without ObsoleteAttribute)
// Called when a new row arrives (ROW token)
internal virtual void RowAvailable( ITypedGetters rowData ) {
// Obsoleting from SMI -- use end of dispose that takes an event sink instead.
// Intended to be removed (along with inheriting IDisposable) prior to RTM.
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V3+ and dropped support for V2-.
// 2) Server didn't implement V2- on some interface and negotiated V2-.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
#endregion
#endregion
}
}

View File

@@ -0,0 +1,333 @@
//------------------------------------------------------------------------------
// <copyright file="SmiEventSink_Default.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System.Data.Sql;
using System.Data.SqlClient;
using System.Diagnostics;
internal class SmiEventSink_Default : SmiEventSink {
private SmiEventSink _parent; // next level up, which we'll defer to if we don't need to handle the event.
private SqlErrorCollection _errors;
private SqlErrorCollection _warnings;
private SqlErrorCollection Errors {
get {
if ( null == _errors ) {
_errors = new SqlErrorCollection( );
}
return _errors;
}
}
internal bool HasMessages {
get {
SmiEventSink_Default parent = (SmiEventSink_Default)_parent;
if (null != parent) {
return parent.HasMessages;
}
else {
bool result = (null != _errors || null != _warnings);
return result;
}
}
}
virtual internal string ServerVersion {
get {
return null;
}
}
internal SmiEventSink Parent {
get {
return _parent;
}
set {
_parent = value;
}
}
private SqlErrorCollection Warnings {
get {
if ( null == _warnings ) {
_warnings = new SqlErrorCollection( );
}
return _warnings;
}
}
protected virtual void DispatchMessages(bool ignoreNonFatalMessages) {
// virtual because we want a default implementation in the cases
// where we don't have a connection to process stuff, but we want to
// provide the connection the ability to fire info messages when it
// hooks up.
SmiEventSink_Default parent = (SmiEventSink_Default)_parent;
if (null != parent) {
parent.DispatchMessages(ignoreNonFatalMessages);
}
else {
SqlException errors = ProcessMessages(true, ignoreNonFatalMessages); // ignore warnings, because there's no place to send them...
if (null != errors) {
throw errors;
}
}
}
protected SqlException ProcessMessages(bool ignoreWarnings, bool ignoreNonFatalMessages) {
SqlException result = null;
SqlErrorCollection temp = null; // temp variable to store that which is being thrown - so that local copies can be deleted
if ( null != _errors ) {
Debug.Assert( 0 != _errors.Count, "empty error collection?" ); // must be something in the collection
if (ignoreNonFatalMessages) {
temp = new SqlErrorCollection();
foreach(SqlError error in _errors) {
if (error.Class >= TdsEnums.FATAL_ERROR_CLASS){
temp.Add(error);
}
}
if (temp.Count <= 0) {
temp = null;
}
}
else {
if (null != _warnings ) {
// When we throw an exception we place all the warnings that
// occurred at the end of the collection - after all the errors.
// That way the user can see all the errors AND warnings that
// occurred for the exception.
foreach ( SqlError warning in _warnings ) {
_errors.Add( warning );
}
}
temp = _errors;
}
_errors = null;
_warnings = null;
}
else {
Debug.Assert( null == _warnings || 0 != _warnings.Count, "empty warning collection?" );// must be something in the collection
if (!ignoreWarnings) {
temp = _warnings;
}
_warnings = null;
}
if ( null != temp ) {
result = SqlException.CreateException( temp, ServerVersion );
}
return result;
}
internal void CleanMessages() {
SmiEventSink_Default parent = (SmiEventSink_Default)_parent;
if (null != parent) {
parent.CleanMessages();
}
else {
_errors = null;
_warnings = null;
}
}
internal void ProcessMessagesAndThrow() {
ProcessMessagesAndThrow(false);
}
internal void ProcessMessagesAndThrow(bool ignoreNonFatalMessages) {
if (HasMessages) {
DispatchMessages(ignoreNonFatalMessages);
}
}
internal enum UnexpectedEventType {
BatchCompleted,
ColumnInfoAvailable,
DefaultDatabaseChanged,
MessagePosted,
MetaDataAvailable,
ParameterAvailable,
ParametersAvailable,
RowAvailable,
StatementCompleted,
TableNameAvailable,
TransactionCommitted,
TransactionDefected,
TransactionEnlisted,
TransactionEnded,
TransactionRolledBack,
TransactionStarted,
}
internal SmiEventSink_Default () {
}
internal SmiEventSink_Default ( SmiEventSink parent ) {
_parent = parent;
}
// NOTE: See the note in SmiEventSink about throwing from these methods;
// We're throwing here because we don't want to miss something, but
// you'll need to turn on Bid tracing to figure out what it is that
// was thrown, because they will be eaten by the server and replaced
// with a different exception.
// Called at end of stream
internal override void BatchCompleted( ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.BatchCompleted);
}
_parent.BatchCompleted();
}
internal override void ParametersAvailable(SmiParameterMetaData[] metaData, ITypedGettersV3 paramValues) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.ParametersAvailable);
}
_parent.ParametersAvailable(metaData, paramValues);
}
internal override void ParameterAvailable(SmiParameterMetaData metaData, SmiTypedGetterSetter paramValue, int ordinal) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.ParameterAvailable);
}
_parent.ParameterAvailable(metaData, paramValue, ordinal);
}
// Called when the server database context changes (ENVCHANGE token)
internal override void DefaultDatabaseChanged( string databaseName ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.DefaultDatabaseChanged);
}
_parent.DefaultDatabaseChanged( databaseName );
}
// Called for messages and errors (ERROR and INFO tokens)
internal override void MessagePosted ( int number, byte state, byte errorClass, string server, string message, string procedure, int lineNumber ) {
if (null == _parent) {
if (Bid.AdvancedOn) {
Bid.Trace("<sc.SmiEventSink_Default.MessagePosted|ADV> %d#, number=%d state=%d errorClass=%d server='%ls' message='%ls' procedure='%ls' linenumber=%d.\n",
0,
number,
state,
errorClass,
(null != server) ? server : "<null>",
(null != message) ? message : "<null>",
(null != procedure) ? procedure : "<null>",
lineNumber
);
}
SqlError error = new SqlError ( number, state, errorClass, server, message, procedure, lineNumber );
if ( error.Class < TdsEnums.MIN_ERROR_CLASS ) {
Warnings.Add( error );
}
else {
Errors.Add( error );
}
}
else {
_parent.MessagePosted( number, state, errorClass, server, message, procedure, lineNumber );
}
}
// Called for new resultset starting (COLMETADATA token)
internal override void MetaDataAvailable( SmiQueryMetaData[] metaData, bool nextEventIsRow ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.MetaDataAvailable);
}
_parent.MetaDataAvailable( metaData, nextEventIsRow );
}
// Called when a new row arrives (ROW token)
internal override void RowAvailable( ITypedGetters rowData ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.RowAvailable);
}
_parent.RowAvailable( rowData );
}
// Called when a new row arrives (ROW token)
internal override void RowAvailable( ITypedGettersV3 rowData ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.RowAvailable);
}
_parent.RowAvailable( rowData );
}
// Called when any statement completes on server (DONE token)
internal override void StatementCompleted( int rowsAffected ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.StatementCompleted);
}
_parent.StatementCompleted( rowsAffected );
}
// Called when a transaction is commited (ENVCHANGE token)
internal override void TransactionCommitted( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionCommitted);
}
_parent.TransactionCommitted( transactionId );
}
// Called when a transaction is commited (ENVCHANGE token)
internal override void TransactionDefected( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionDefected);
}
_parent.TransactionDefected( transactionId );
}
// Called when a transaction is commited (ENVCHANGE token)
internal override void TransactionEnlisted( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionEnlisted);
}
_parent.TransactionEnlisted( transactionId );
}
// Called when a transaction is forcibly ended in the server, not requested
// by the provider's batch (ENVCHANGE token)
internal override void TransactionEnded( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionEnded);
}
_parent.TransactionEnded( transactionId );
}
// Called when a transaction is rolled back (ENVCHANGE token)
internal override void TransactionRolledBack( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionRolledBack);
}
_parent.TransactionRolledBack( transactionId );
}
// Called when a transaction is started (ENVCHANGE token)
internal override void TransactionStarted( long transactionId ) {
if (null == _parent) {
throw SQL.UnexpectedSmiEvent(UnexpectedEventType.TransactionStarted);
}
_parent.TransactionStarted( transactionId );
}
}
}

View File

@@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
// <copyright file="SmiEventSink_DeferedProcessing.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System.Data.Sql;
using System.Data.SqlClient;
using System.Diagnostics;
// This class exists purely to defer processing of messages until a later time.
// It is designed to allow calling common code that interacts with the SMI layers
// without throwing or otherwise processing messages in the sink until later on.
//
// Main example:
// SqlCommand.ExecuteNonQuerySmi calls EventStream.ProcessEvent with it's command event sink (CES)
// ProcessEvent calls OnParametersAvailable on the CES
// OnParametersAvailable sets up a deferedprocessing event sink (DPES) with the CES as its parent
// OnParametersAvailable calls ValueUtils to extract param values passing the DPES
// ValueUtils calls Smi passing DPES
// Smi may call MessagePosted, which will send a message up the sink parent chain and save it.
// ValueUtils calls ProcessMessagesAndThrow on DPES, which skips handling
// ... return up the stack ...
// SqlCommand.ExecuteNonQuerySmi calls CES.ProcessMessagesAndThrow, which handles the messages
// sent from the Smi value extraction code.
//
// IMPORTANT: Code that uses the DeferedProccess event sink is responsible for ensuring that
// these messages ARE processed at some point.
internal class SmiEventSink_DeferedProcessing : SmiEventSink_Default {
internal SmiEventSink_DeferedProcessing ( SmiEventSink parent ) : base(parent) {
}
protected override void DispatchMessages(bool ignoreNonFatalMessages) {
// Skip processing messages. Since messages are sent to parent and calling code will call
// ProcessMessages against parent, messages ARE NOT LOST!
}
}
}

View File

@@ -0,0 +1,31 @@
//------------------------------------------------------------------------------
// <copyright file="SmiEventStream.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
internal abstract class SmiEventStream : IDisposable {
internal abstract bool HasEvents { get; }
internal abstract void Close( SmiEventSink sink );
public virtual void Dispose( ) {
// Obsoleting from SMI -- use Close instead.
// Intended to be removed (along with inheriting IDisposable) prior to RTM.
// Implement body with throw because there are only a couple of ways to get to this code:
// 1) Client is calling this method even though the server negotiated for V3+ and dropped support for V2-.
// 2) Server didn't implement V2- on some interface and negotiated V2-.
System.Data.Common.ADP.InternalError( System.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod );
}
internal abstract void ProcessEvent( SmiEventSink sink );
}
}

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <copyright file="SmiExecuteType.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">stevesta</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data;
using System.Data.Sql;
// enum representing the type of execution requested
internal enum SmiExecuteType {
NonQuery = 0,
Reader = 1,
ToPipe = 2,
}
}

View File

@@ -0,0 +1,96 @@
//------------------------------------------------------------------------------
// <copyright file="SmiGettersStream.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Diagnostics;
internal class SmiGettersStream : Stream {
private SmiEventSink_Default _sink;
private ITypedGettersV3 _getters;
private int _ordinal;
private long _readPosition;
private SmiMetaData _metaData;
internal SmiGettersStream( SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData ) {
Debug.Assert( null != sink );
Debug.Assert( null != getters );
Debug.Assert( 0 <= ordinal );
Debug.Assert( null != metaData );
_sink = sink;
_getters = getters;
_ordinal = ordinal;
_readPosition = 0;
_metaData = metaData;
}
public override bool CanRead {
get {
return true;
}
}
// If CanSeek is false, Position, Seek, Length, and SetLength should throw.
public override bool CanSeek {
get {
return false;
}
}
public override bool CanWrite {
get {
return false;
}
}
public override long Length {
get {
return ValueUtilsSmi.GetBytesInternal( _sink, _getters, _ordinal, _metaData, 0, null, 0, 0, false );
}
}
public override long Position {
get {
return _readPosition;
}
set {
throw SQL.StreamSeekNotSupported();
}
}
public override void Flush() {
throw SQL.StreamWriteNotSupported();
}
public override long Seek(long offset, SeekOrigin origin) {
throw SQL.StreamSeekNotSupported();
}
public override void SetLength(long value) {
throw SQL.StreamWriteNotSupported();
}
public override int Read( byte[] buffer, int offset, int count ) {
long bytesRead = ValueUtilsSmi.GetBytesInternal( _sink, _getters, _ordinal, _metaData, _readPosition, buffer, offset, count, false );
_readPosition += bytesRead;
return checked( (int) bytesRead );
}
public override void Write( byte[] buffer, int offset, int count ) {
throw SQL.StreamWriteNotSupported();
}
}
}

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
// <copyright file="SmiLink.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">alazela</owner>
// <owner current="true" primary="false">billin</owner>
//------------------------------------------------------------------------------
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("SqlAccess, PublicKey=0024000004800000940000000602000000240000525341310004000001000100272736ad6e5f9586bac2d531eabc3acc666c2f8ec879fa94f8f7b0327d2ff2ed523448f83c3d5c5dd2dfc7bc99c5286b2c125117bf5cbe242b9d41750732b2bdffe649c6efb8e5526d526fdd130095ecdb7bf210809c6cdad8824faa9ac0310ac3cba2aa0523567b2dfa7fe250b30facbd62d4ec99b94ac47c7d3b28f1f6e4c8")] // SQLBU 437687
namespace Microsoft.SqlServer.Server {
using System;
internal abstract class SmiLink {
// NOTE: Except for changing the constant value below, adding new members
// to this class may create versioning issues. We would prefer not
// to add additional items to this if possible.
internal const ulong InterfaceVersion = 210;
// Version negotiation (appdomain-wide negotiation)
// This needs to be the first method called when negotiating with a
// driver back end. Once called, the rest of the back end interface
// needs to conform to the returned version number's interface.
internal abstract ulong NegotiateVersion( ulong requestedVersion );
// Get utility class valid in current thread execution environment
// This returns an object, to allow us to version the context without
// having to version this class. (eg. SmiContext1 vs SmiContext2)
internal abstract object GetCurrentContext( SmiEventSink eventSink );
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
//------------------------------------------------------------------------------
// <copyright file="SmiMetaData.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <owner current="true" primary="true">[....]</owner>
// <owner current="true" primary="false">[....]</owner>
//------------------------------------------------------------------------------
namespace Microsoft.SqlServer.Server {
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Globalization;
// SmiMetaDataProperty defines an extended, optional property to be used on the SmiMetaData class
// This approach to adding properties is added combat the growing number of sparsely-used properties
// that are specially handled on the base classes
internal enum SmiPropertySelector {
DefaultFields = 0x0,
SortOrder = 0x1,
UniqueKey = 0x2,
}
// Simple collection for properties. Could extend to IDictionary support if needed in future.
internal class SmiMetaDataPropertyCollection {
private const int SelectorCount = 3; // number of elements in SmiPropertySelector
private SmiMetaDataProperty[] _properties;
private bool _isReadOnly;
internal static readonly SmiMetaDataPropertyCollection EmptyInstance;
// Singleton empty instances to ensure each property is always non-null
private static readonly SmiDefaultFieldsProperty __emptyDefaultFields = new SmiDefaultFieldsProperty(new List<bool>());
private static readonly SmiOrderProperty __emptySortOrder = new SmiOrderProperty(new List<SmiOrderProperty.SmiColumnOrder>());
private static readonly SmiUniqueKeyProperty __emptyUniqueKey = new SmiUniqueKeyProperty(new List<bool>());
static SmiMetaDataPropertyCollection() {
EmptyInstance = new SmiMetaDataPropertyCollection();
EmptyInstance.SetReadOnly();
}
internal SmiMetaDataPropertyCollection() {
_properties = new SmiMetaDataProperty[SelectorCount];
_isReadOnly = false;
_properties[(int)SmiPropertySelector.DefaultFields] = __emptyDefaultFields;
_properties[(int)SmiPropertySelector.SortOrder] = __emptySortOrder;
_properties[(int)SmiPropertySelector.UniqueKey] = __emptyUniqueKey;
}
internal SmiMetaDataProperty this[SmiPropertySelector key] {
get {
return _properties[(int)key];
}
set {
if (null == value) {
throw ADP.InternalError(ADP.InternalErrorCode.InvalidSmiCall);
}
EnsureWritable();
_properties[(int)key] = value;
}
}
internal bool IsReadOnly {
get {
return _isReadOnly;
}
}
internal IEnumerable<SmiMetaDataProperty> Values {
get {
return new List<SmiMetaDataProperty>(_properties);
}
}
// Allow switching to read only, but not back.
internal void SetReadOnly() {
_isReadOnly = true;
}
private void EnsureWritable() {
if (IsReadOnly) {
throw System.Data.Common.ADP.InternalError(System.Data.Common.ADP.InternalErrorCode.InvalidSmiCall);
}
}
}
// Base class for properties
internal abstract class SmiMetaDataProperty {
internal abstract string TraceString();
}
// Property defining a list of column ordinals that define a unique key
internal class SmiUniqueKeyProperty : SmiMetaDataProperty {
private IList<bool> _columns;
internal SmiUniqueKeyProperty(IList<bool> columnIsKey) {
_columns = new List<bool>(columnIsKey).AsReadOnly();
}
// indexed by column ordinal indicating for each column whether it is key or not
internal bool this[int ordinal] {
get {
if (_columns.Count <= ordinal) {
return false;
}
else {
return _columns[ordinal];
}
}
}
[Conditional("DEBUG")]
internal void CheckCount(int countToMatch) {
Debug.Assert(0 == _columns.Count || countToMatch == _columns.Count,
"SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _columns.Count +
") not equal to checked size (" + countToMatch + ")" );
}
internal override string TraceString() {
string returnValue = "UniqueKey(";
bool delimit = false;
for (int columnOrd = 0; columnOrd < _columns.Count; columnOrd++) {
if (delimit) {
returnValue += ",";
}
else {
delimit = true;
}
if (_columns[columnOrd]) {
returnValue += columnOrd.ToString(CultureInfo.InvariantCulture);
}
}
returnValue += ")";
return returnValue;
}
}
// Property defining a sort order for a set of columns (by ordinal and ASC/DESC).
internal class SmiOrderProperty : SmiMetaDataProperty {
internal struct SmiColumnOrder {
internal int SortOrdinal;
internal SortOrder Order;
internal string TraceString() {
return String.Format(CultureInfo.InvariantCulture, "{0} {1}", SortOrdinal, Order);
}
}
private IList<SmiColumnOrder> _columns;
internal SmiOrderProperty(IList<SmiColumnOrder> columnOrders) {
_columns = new List<SmiColumnOrder>(columnOrders).AsReadOnly();
}
// Readonly list of the columnorder instances making up the sort order
// order in list indicates precedence
internal SmiColumnOrder this[int ordinal] {
get {
if (_columns.Count <= ordinal) {
SmiColumnOrder order = new SmiColumnOrder();
order.Order = SortOrder.Unspecified;
order.SortOrdinal = -1;
return order;
}
else {
return _columns[ordinal];
}
}
}
[Conditional("DEBUG")]
internal void CheckCount(int countToMatch) {
Debug.Assert(0 == _columns.Count || countToMatch == _columns.Count,
"SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _columns.Count +
") not equal to checked size (" + countToMatch + ")" );
}
internal override string TraceString() {
string returnValue = "SortOrder(";
bool delimit = false;
foreach(SmiColumnOrder columnOrd in _columns) {
if (delimit) {
returnValue += ",";
}
else {
delimit = true;
}
if (System.Data.SqlClient.SortOrder.Unspecified != columnOrd.Order) {
returnValue += columnOrd.TraceString();
}
}
returnValue += ")";
return returnValue;
}
}
// property defining inheritance relationship(s)
internal class SmiDefaultFieldsProperty : SmiMetaDataProperty {
#region private fields
private IList<bool> _defaults;
#endregion
#region internal interface
internal SmiDefaultFieldsProperty(IList<bool> defaultFields) {
_defaults = new List<bool>(defaultFields).AsReadOnly();
}
internal bool this[int ordinal] {
get {
if (_defaults.Count <= ordinal) {
return false;
}
else {
return _defaults[ordinal];
}
}
}
[Conditional("DEBUG")]
internal void CheckCount(int countToMatch) {
Debug.Assert(0 == _defaults.Count || countToMatch == _defaults.Count,
"SmiDefaultFieldsProperty.CheckCount: DefaultFieldsProperty size (" + _defaults.Count +
") not equal to checked size (" + countToMatch + ")" );
}
internal override string TraceString() {
string returnValue = "DefaultFields(";
bool delimit = false;
for(int columnOrd = 0; columnOrd < _defaults.Count; columnOrd++) {
if (delimit) {
returnValue += ",";
}
else {
delimit = true;
}
if (_defaults[columnOrd]) {
returnValue += columnOrd;
}
}
returnValue += ")";
return returnValue;
}
#endregion
}
}

Some files were not shown because too many files have changed in this diff Show More