| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213 |
- //------------------------------------------------------------------------------
- // <copyright file="SqlDataReader.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.SqlClient {
- using System;
- using System.Data;
- using System.Data.Sql;
- using System.Data.SqlTypes;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Diagnostics; // for Conditional compilation
- using System.Diagnostics.CodeAnalysis;
- using System.Xml;
- using Microsoft.SqlServer.Server;
- using System.Data.ProviderBase;
- using System.Data.Common;
- using System.Threading.Tasks;
- // SqlServer provider's implementation of ISqlReader.
- // Supports ISqlReader and ISqlResultSet objects.
- //
- // User should never be able to create one of these themselves, nor subclass.
- // This is accomplished by having no public override constructors.
- internal sealed class SqlDataReaderSmi : SqlDataReader {
-
- //
- // IDBRecord properties
- //
- public override int FieldCount {
- get {
- ThrowIfClosed( "FieldCount" );
- return InternalFieldCount;
- }
- }
- public override int VisibleFieldCount {
- get {
- ThrowIfClosed("VisibleFieldCount");
- if (FNotInResults()) {
- return 0;
- }
- return _visibleColumnCount;
- }
- }
- //
- // IDBRecord Metadata Methods
- //
- public override String GetName(int ordinal) {
- EnsureCanGetMetaData( "GetName" );
- return _currentMetaData[ordinal].Name;
- }
- public override String GetDataTypeName(int ordinal) {
- EnsureCanGetMetaData( "GetDataTypeName" );
- SmiExtendedMetaData md = _currentMetaData[ordinal];
- if ( SqlDbType.Udt == md.SqlDbType ) {
- return md.TypeSpecificNamePart1 + "." + md.TypeSpecificNamePart2 + "." + md.TypeSpecificNamePart3;
- }
- else {
- return md.TypeName;
- }
- }
- public override Type GetFieldType(int ordinal) {
- EnsureCanGetMetaData( "GetFieldType" );
- if (SqlDbType.Udt == _currentMetaData[ordinal].SqlDbType) {
- return _currentMetaData[ordinal].Type;
- }
- else {
- return MetaType.GetMetaTypeFromSqlDbType(
- _currentMetaData[ordinal].SqlDbType, _currentMetaData[ordinal].IsMultiValued).ClassType ;
- }
- }
- override public Type GetProviderSpecificFieldType(int ordinal) {
- EnsureCanGetMetaData( "GetProviderSpecificFieldType" );
- if (SqlDbType.Udt == _currentMetaData[ordinal].SqlDbType) {
- return _currentMetaData[ordinal].Type;
- }
- else {
- return MetaType.GetMetaTypeFromSqlDbType(
- _currentMetaData[ordinal].SqlDbType, _currentMetaData[ordinal].IsMultiValued).SqlType ;
- }
- }
- public override int Depth {
- get{
- ThrowIfClosed( "Depth" );
- return 0;
- }
- } //
- public override Object GetValue(int ordinal) {
- EnsureCanGetCol( "GetValue", ordinal);
- SmiQueryMetaData metaData = _currentMetaData[ordinal];
- if (_currentConnection.IsKatmaiOrNewer) {
- return ValueUtilsSmi.GetValue200(_readerEventSink, (SmiTypedGetterSetter)_currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- else {
- return ValueUtilsSmi.GetValue(_readerEventSink, _currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- }
- public override T GetFieldValue<T>(int ordinal) {
- EnsureCanGetCol( "GetFieldValue<T>", ordinal);
- SmiQueryMetaData metaData = _currentMetaData[ordinal];
- if (_typeofINullable.IsAssignableFrom(typeof(T))) {
- // If its a SQL Type or Nullable UDT
- if (_currentConnection.IsKatmaiOrNewer) {
- return (T)ValueUtilsSmi.GetSqlValue200(_readerEventSink, (SmiTypedGetterSetter)_currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- else {
- return (T)ValueUtilsSmi.GetSqlValue(_readerEventSink, _currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- }
- else {
- // Otherwise Its a CLR or non-Nullable UDT
- if (_currentConnection.IsKatmaiOrNewer) {
- return (T)ValueUtilsSmi.GetValue200(_readerEventSink, (SmiTypedGetterSetter)_currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- else {
- return (T)ValueUtilsSmi.GetValue(_readerEventSink, _currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- }
- }
- public override Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) {
- // As per Async spec, Context Connections do not support async
- return ADP.CreatedTaskWithException<T>(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection()));
- }
- override internal SqlBuffer.StorageType GetVariantInternalStorageType(int ordinal) {
- Debug.Assert(null != _currentColumnValuesV3, "Attempting to get variant internal storage type without calling GetValue first");
- if (IsDBNull(ordinal))
- return SqlBuffer.StorageType.Empty;
- SmiMetaData valueMetaData = _currentColumnValuesV3.GetVariantType(_readerEventSink, ordinal);
- if (valueMetaData == null)
- return SqlBuffer.StorageType.Empty;
- else
- return ValueUtilsSmi.SqlDbTypeToStorageType(valueMetaData.SqlDbType);
- }
- public override int GetValues(object[] values) {
- EnsureCanGetCol( "GetValues", 0);
- if (null == values) {
- throw ADP.ArgumentNull("values");
- }
- int copyLength = (values.Length < _visibleColumnCount) ? values.Length : _visibleColumnCount;
- for(int i=0; i<copyLength; i++) {
- values[_indexMap[i]] = GetValue(i);
- }
- return copyLength;
- }
- public override int GetOrdinal(string name) {
- EnsureCanGetMetaData( "GetOrdinal" );
- if (null == _fieldNameLookup) {
- _fieldNameLookup = new FieldNameLookup( (IDataReader) this, -1 ); //
- }
- return _fieldNameLookup.GetOrdinal(name); // MDAC 71470
- }
- // Generic array access by column index (accesses column value)
- public override object this[int ordinal] {
- get {
- return GetValue( ordinal );
- }
- }
- // Generic array access by column name (accesses column value)
- public override object this[string strName] {
- get {
- return GetValue( GetOrdinal( strName ) );
- }
- }
- //
- // IDataRecord Data Access methods
- //
- public override bool IsDBNull(int ordinal) {
- EnsureCanGetCol( "IsDBNull", ordinal);
- return ValueUtilsSmi.IsDBNull(_readerEventSink, _currentColumnValuesV3, ordinal);
- }
- public override Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) {
- // As per Async spec, Context Connections do not support async
- return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection()));
- }
- public override bool GetBoolean(int ordinal) {
- EnsureCanGetCol( "GetBoolean", ordinal);
- return ValueUtilsSmi.GetBoolean(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override byte GetByte(int ordinal) {
- EnsureCanGetCol( "GetByte", ordinal);
- return ValueUtilsSmi.GetByte(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) {
- EnsureCanGetCol( "GetBytes", ordinal);
- return ValueUtilsSmi.GetBytes(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], fieldOffset, buffer, bufferOffset, length, true);
- }
- // XmlReader support code calls this method.
- internal override long GetBytesInternal(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) {
- EnsureCanGetCol( "GetBytes", ordinal);
- return ValueUtilsSmi.GetBytesInternal(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], fieldOffset, buffer, bufferOffset, length, false);
- }
- public override char GetChar(int ordinal) {
- throw ADP.NotSupported();
- }
- public override long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) {
- EnsureCanGetCol( "GetChars", ordinal);
- SmiExtendedMetaData metaData = _currentMetaData[ordinal];
- if (IsCommandBehavior(CommandBehavior.SequentialAccess)) {
- if (metaData.SqlDbType == SqlDbType.Xml) {
- return GetStreamingXmlChars(ordinal, fieldOffset, buffer, bufferOffset, length);
- }
- }
- return ValueUtilsSmi.GetChars(_readerEventSink, _currentColumnValuesV3, ordinal, metaData, fieldOffset, buffer, bufferOffset, length);
- }
- public override Guid GetGuid(int ordinal) {
- EnsureCanGetCol( "GetGuid", ordinal);
- return ValueUtilsSmi.GetGuid(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Int16 GetInt16(int ordinal) {
- EnsureCanGetCol( "GetInt16", ordinal);
- return ValueUtilsSmi.GetInt16(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Int32 GetInt32(int ordinal) {
- EnsureCanGetCol( "GetInt32", ordinal);
- return ValueUtilsSmi.GetInt32(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Int64 GetInt64(int ordinal) {
- EnsureCanGetCol( "GetInt64", ordinal);
- return ValueUtilsSmi.GetInt64(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Single GetFloat(int ordinal) {
- EnsureCanGetCol( "GetFloat", ordinal);
- return ValueUtilsSmi.GetSingle(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Double GetDouble(int ordinal) {
- EnsureCanGetCol( "GetDouble", ordinal);
- return ValueUtilsSmi.GetDouble(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override String GetString(int ordinal) {
- EnsureCanGetCol( "GetString", ordinal);
- return ValueUtilsSmi.GetString(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override Decimal GetDecimal(int ordinal) {
- EnsureCanGetCol( "GetDecimal", ordinal);
- return ValueUtilsSmi.GetDecimal(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override DateTime GetDateTime(int ordinal) {
- EnsureCanGetCol( "GetDateTime", ordinal);
- return ValueUtilsSmi.GetDateTime(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- //
- // IDataReader properties
- //
- // Logically closed test. I.e. is this object closed as far as external access is concerned?
- public override bool IsClosed {
- get {
- return IsReallyClosed();
- }
- }
- public override int RecordsAffected {
- get {
- return base.Command.InternalRecordsAffected;
- }
- }
- //
- // IDataReader methods
- //
- internal override void CloseReaderFromConnection() {
- // Context Connections do not support async - so there is no threading issues with closing from the connection
- CloseInternal(closeConnection: false);
- }
- public override void Close() {
- // Connection should be open at this point, so we can do multiple checks of HasEvents, and we may need to close the connection afterwards
- CloseInternal(closeConnection: IsCommandBehavior(CommandBehavior.CloseConnection));
- }
- private void CloseInternal(bool closeConnection) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<sc.SqlDataReaderSmi.Close|API> %d#", ObjectID);
- bool processFinallyBlock = true;
- try {
- if(!IsClosed) {
- _hasRows = false;
- // Process the remaining events. This makes sure that environment changes are applied and any errors are picked up.
- while(_eventStream.HasEvents) {
- _eventStream.ProcessEvent( _readerEventSink );
- _readerEventSink.ProcessMessagesAndThrow(true);
- }
- // Close the request executor
- _requestExecutor.Close(_readerEventSink);
- _readerEventSink.ProcessMessagesAndThrow(true);
- }
- }
- catch (Exception e) {
- processFinallyBlock = ADP.IsCatchableExceptionType(e);
- throw;
- }
- finally {
- if (processFinallyBlock) {
- _isOpen = false;
- if ((closeConnection) && (Connection != null)) {
- Connection.Close();
- }
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- // Move to the next resultset
- public override unsafe bool NextResult() {
- ThrowIfClosed( "NextResult" );
- bool hasAnotherResult = InternalNextResult(false);
- return hasAnotherResult;
- }
-
- public override Task<bool> NextResultAsync(CancellationToken cancellationToken)
- {
- // Async not supported on Context Connections
- return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection()));
- }
- internal unsafe bool InternalNextResult(bool ignoreNonFatalMessages) {
- IntPtr hscp = IntPtr.Zero;
- if (Bid.AdvancedOn) {
- Bid.ScopeEnter(out hscp, "<sc.SqlDataReaderSmi.InternalNextResult|ADV> %d#", ObjectID);
- }
- try {
- _hasRows = false;
- if( PositionState.AfterResults != _currentPosition )
- {
- // Consume any remaning rows in the current result.
-
- while( InternalRead(ignoreNonFatalMessages) ) {
- // This space intentionally left blank
- }
- // reset resultset metadata - it will be created again if there is a pending resultset
- ResetResultSet();
- // Process the events until metadata is found or all of the
- // available events have been consumed. If there is another
- // result, the metadata for it will be available after the last
- // read on the prior result.
- while(null == _currentMetaData && _eventStream.HasEvents) {
- _eventStream.ProcessEvent( _readerEventSink );
- _readerEventSink.ProcessMessagesAndThrow(ignoreNonFatalMessages);
- }
- }
- return PositionState.AfterResults != _currentPosition;
- }
- finally {
- if (Bid.AdvancedOn) {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- public override bool Read() {
- ThrowIfClosed( "Read" );
- bool hasAnotherRow = InternalRead(false);
- return hasAnotherRow;
- }
- public override Task<bool> ReadAsync(CancellationToken cancellationToken)
- {
- // Async not supported on Context Connections
- return ADP.CreatedTaskWithException<bool>(ADP.ExceptionWithStackTrace(SQL.NotAvailableOnContextConnection()));
- }
- internal unsafe bool InternalRead(bool ignoreNonFatalErrors) {
- IntPtr hscp = IntPtr.Zero;
- if (Bid.AdvancedOn) {
- Bid.ScopeEnter(out hscp, "<sc.SqlDataReaderSmi.InternalRead|ADV> %d#", ObjectID);
- }
- try {
- // Don't move unless currently in results.
- if( FInResults() ) {
-
- // Set current row to null so we can see if we get a new one
- _currentColumnValues = null;
- _currentColumnValuesV3 = null;
-
- // Reset blobs
- if (_currentStream != null) {
- _currentStream.SetClosed();
- _currentStream = null;
- }
- if (_currentTextReader != null) {
- _currentTextReader.SetClosed();
- _currentTextReader = null;
- }
- // NOTE: SQLBUDT #386118 -- may indicate that we want to break this loop when we get a MessagePosted callback, but we can't prove that.
- while( null == _currentColumnValues && // Did we find a row?
- null == _currentColumnValuesV3 && // Did we find a V3 row?
- FInResults() && // Was the batch terminated due to a serious error?
- PositionState.AfterRows != _currentPosition && // Have we seen a statement completed event?
- _eventStream.HasEvents ) { // Have we processed all events?
- _eventStream.ProcessEvent( _readerEventSink );
- _readerEventSink.ProcessMessagesAndThrow(ignoreNonFatalErrors);
- }
- }
-
- return PositionState.OnRow == _currentPosition;
- }
- finally {
- if (Bid.AdvancedOn) {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- public override DataTable GetSchemaTable() {
- ThrowIfClosed( "GetSchemaTable" );
- if ( null == _schemaTable && FInResults() )
- {
- DataTable schemaTable = new DataTable( "SchemaTable" );
- schemaTable.Locale = System.Globalization.CultureInfo.InvariantCulture;
- schemaTable.MinimumCapacity = InternalFieldCount;
- DataColumn ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(System.String));
- DataColumn Ordinal = new DataColumn(SchemaTableColumn.ColumnOrdinal, typeof(System.Int32));
- DataColumn Size = new DataColumn(SchemaTableColumn.ColumnSize, typeof(System.Int32));
- DataColumn Precision = new DataColumn(SchemaTableColumn.NumericPrecision, typeof(System.Int16));
- DataColumn Scale = new DataColumn(SchemaTableColumn.NumericScale, typeof(System.Int16));
- DataColumn DataType = new DataColumn(SchemaTableColumn.DataType, typeof(System.Type));
- DataColumn ProviderSpecificDataType = new DataColumn(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(System.Type));
- DataColumn ProviderType = new DataColumn(SchemaTableColumn.ProviderType, typeof(System.Int32));
- DataColumn NonVersionedProviderType = new DataColumn(SchemaTableColumn.NonVersionedProviderType, typeof(System.Int32));
- DataColumn IsLong = new DataColumn(SchemaTableColumn.IsLong, typeof(System.Boolean));
- DataColumn AllowDBNull = new DataColumn(SchemaTableColumn.AllowDBNull, typeof(System.Boolean));
- DataColumn IsReadOnly = new DataColumn(SchemaTableOptionalColumn.IsReadOnly, typeof(System.Boolean));
- DataColumn IsRowVersion = new DataColumn(SchemaTableOptionalColumn.IsRowVersion, typeof(System.Boolean));
- DataColumn IsUnique = new DataColumn(SchemaTableColumn.IsUnique, typeof(System.Boolean));
- DataColumn IsKey = new DataColumn(SchemaTableColumn.IsKey, typeof(System.Boolean));
- DataColumn IsAutoIncrement = new DataColumn(SchemaTableOptionalColumn.IsAutoIncrement, typeof(System.Boolean));
- DataColumn IsHidden = new DataColumn(SchemaTableOptionalColumn.IsHidden, typeof(System.Boolean));
- DataColumn BaseCatalogName = new DataColumn(SchemaTableOptionalColumn.BaseCatalogName, typeof(System.String));
- DataColumn BaseSchemaName = new DataColumn(SchemaTableColumn.BaseSchemaName, typeof(System.String));
- DataColumn BaseTableName = new DataColumn(SchemaTableColumn.BaseTableName, typeof(System.String));
- DataColumn BaseColumnName = new DataColumn(SchemaTableColumn.BaseColumnName, typeof(System.String));
- // unique to SqlClient
- DataColumn BaseServerName = new DataColumn(SchemaTableOptionalColumn.BaseServerName, typeof(System.String));
- DataColumn IsAliased = new DataColumn(SchemaTableColumn.IsAliased, typeof(System.Boolean));
- DataColumn IsExpression = new DataColumn(SchemaTableColumn.IsExpression, typeof(System.Boolean));
- DataColumn IsIdentity = new DataColumn("IsIdentity", typeof(System.Boolean));
- // UDT specific. Holds UDT typename ONLY if the type of the column is UDT, otherwise the data type
- DataColumn DataTypeName = new DataColumn("DataTypeName", typeof(System.String));
- DataColumn UdtAssemblyQualifiedName = new DataColumn("UdtAssemblyQualifiedName", typeof(System.String));
- // Xml metadata specific
- DataColumn XmlSchemaCollectionDatabase = new DataColumn("XmlSchemaCollectionDatabase", typeof(System.String));
- DataColumn XmlSchemaCollectionOwningSchema = new DataColumn("XmlSchemaCollectionOwningSchema", typeof(System.String));
- DataColumn XmlSchemaCollectionName = new DataColumn("XmlSchemaCollectionName", typeof(System.String));
- // SparseColumnSet
- DataColumn IsColumnSet = new DataColumn("IsColumnSet", typeof(System.Boolean));
- Ordinal.DefaultValue = 0;
- IsLong.DefaultValue = false;
- DataColumnCollection columns = schemaTable.Columns;
- // must maintain order for backward compatibility
- columns.Add(ColumnName);
- columns.Add(Ordinal);
- columns.Add(Size);
- columns.Add(Precision);
- columns.Add(Scale);
- columns.Add(IsUnique);
- columns.Add(IsKey);
- columns.Add(BaseServerName);
- columns.Add(BaseCatalogName);
- columns.Add(BaseColumnName);
- columns.Add(BaseSchemaName);
- columns.Add(BaseTableName);
- columns.Add(DataType);
- columns.Add(AllowDBNull);
- columns.Add(ProviderType);
- columns.Add(IsAliased);
- columns.Add(IsExpression);
- columns.Add(IsIdentity);
- columns.Add(IsAutoIncrement);
- columns.Add(IsRowVersion);
- columns.Add(IsHidden);
- columns.Add(IsLong);
- columns.Add(IsReadOnly);
- columns.Add(ProviderSpecificDataType);
- columns.Add(DataTypeName);
- columns.Add(XmlSchemaCollectionDatabase);
- columns.Add(XmlSchemaCollectionOwningSchema);
- columns.Add(XmlSchemaCollectionName);
- columns.Add(UdtAssemblyQualifiedName);
- columns.Add(NonVersionedProviderType);
- columns.Add(IsColumnSet);
- for (int i = 0; i < InternalFieldCount; i++) {
- SmiQueryMetaData colMetaData = _currentMetaData[i];
- long maxLength = colMetaData.MaxLength;
-
- MetaType metaType = MetaType.GetMetaTypeFromSqlDbType(colMetaData.SqlDbType, colMetaData.IsMultiValued);
- if ( SmiMetaData.UnlimitedMaxLengthIndicator == maxLength ) {
- metaType = MetaType.GetMaxMetaTypeFromMetaType( metaType );
- maxLength = (metaType.IsSizeInCharacters && !metaType.IsPlp) ? (0x7fffffff / 2) : 0x7fffffff;
- }
- DataRow schemaRow = schemaTable.NewRow();
- // NOTE: there is an impedence mismatch here - the server always
- // treats numeric data as variable length and sends a maxLength
- // based upon the precision, whereas TDS always sends 17 for
- // the max length; rather than push this logic into the server,
- // I've elected to make a fixup here instead.
- if (SqlDbType.Decimal == colMetaData.SqlDbType) {
- //
- maxLength = TdsEnums.MAX_NUMERIC_LEN; // SQLBUDT 339686
- }
- else if (SqlDbType.Variant == colMetaData.SqlDbType) {
- //
- maxLength = 8009; // SQLBUDT 340726
- }
- schemaRow[ColumnName] = colMetaData.Name;
- schemaRow[Ordinal] = i;
- schemaRow[Size] = maxLength;
-
- schemaRow[ProviderType] = (int) colMetaData.SqlDbType; // SqlDbType
- schemaRow[NonVersionedProviderType] = (int) colMetaData.SqlDbType; // SqlDbType
- if (colMetaData.SqlDbType != SqlDbType.Udt) {
- schemaRow[DataType] = metaType.ClassType; // com+ type
- schemaRow[ProviderSpecificDataType] = metaType.SqlType;
- }
- else {
- schemaRow[UdtAssemblyQualifiedName] = colMetaData.Type.AssemblyQualifiedName;
- schemaRow[DataType] = colMetaData.Type;
- schemaRow[ProviderSpecificDataType] = colMetaData.Type;
- }
- // NOTE: there is also an impedence mismatch here - the server
- // has different ideas about what the precision value should be
- // than does the client bits. I tried fixing up the default
- // meta data values in SmiMetaData, however, it caused the
- // server suites to fall over dead. Rather than attempt to
- // bake it into the server, I'm fixing it up in the client.
- byte precision = 0xff; // default for everything, except certain numeric types.
-
- //
- switch (colMetaData.SqlDbType) {
- case SqlDbType.BigInt:
- case SqlDbType.DateTime:
- case SqlDbType.Decimal:
- case SqlDbType.Int:
- case SqlDbType.Money:
- case SqlDbType.SmallDateTime:
- case SqlDbType.SmallInt:
- case SqlDbType.SmallMoney:
- case SqlDbType.TinyInt:
- precision = colMetaData.Precision;
- break;
- case SqlDbType.Float:
- precision = 15;
- break;
- case SqlDbType.Real:
- precision = 7;
- break;
- default:
- precision = 0xff; // everything else is unknown;
- break;
- }
- schemaRow[Precision] = precision;
-
- //
- if ( SqlDbType.Decimal == colMetaData.SqlDbType ||
- SqlDbType.Time == colMetaData.SqlDbType ||
- SqlDbType.DateTime2 == colMetaData.SqlDbType ||
- SqlDbType.DateTimeOffset == colMetaData.SqlDbType) {
- schemaRow[Scale] = colMetaData.Scale;
- }
- else {
- schemaRow[Scale] = MetaType.GetMetaTypeFromSqlDbType(
- colMetaData.SqlDbType, colMetaData.IsMultiValued).Scale;
- }
-
- schemaRow[AllowDBNull] = colMetaData.AllowsDBNull;
- if ( !( colMetaData.IsAliased.IsNull ) ) {
- schemaRow[IsAliased] = colMetaData.IsAliased.Value;
- }
- if ( !( colMetaData.IsKey.IsNull ) ) {
- schemaRow[IsKey] = colMetaData.IsKey.Value;
- }
- if ( !( colMetaData.IsHidden.IsNull ) ) {
- schemaRow[IsHidden] = colMetaData.IsHidden.Value;
- }
- if ( !( colMetaData.IsExpression.IsNull ) ) {
- schemaRow[IsExpression] = colMetaData.IsExpression.Value;
- }
- schemaRow[IsReadOnly] = colMetaData.IsReadOnly;
- schemaRow[IsIdentity] = colMetaData.IsIdentity;
- schemaRow[IsColumnSet] = colMetaData.IsColumnSet;
- schemaRow[IsAutoIncrement] = colMetaData.IsIdentity;
- schemaRow[IsLong] = metaType.IsLong;
- // mark unique for timestamp columns
- if ( SqlDbType.Timestamp == colMetaData.SqlDbType ) {
- schemaRow[IsUnique] = true;
- schemaRow[IsRowVersion] = true;
- }
- else {
- schemaRow[IsUnique] = false;
- schemaRow[IsRowVersion] = false;
- }
- if ( !ADP.IsEmpty( colMetaData.ColumnName ) ) {
- schemaRow[BaseColumnName] = colMetaData.ColumnName;
- }
- else if (!ADP.IsEmpty( colMetaData.Name)) {
- // Use projection name if base column name is not present
- schemaRow[BaseColumnName] = colMetaData.Name;
- }
- if ( !ADP.IsEmpty(colMetaData.TableName ) ) {
- schemaRow[BaseTableName] = colMetaData.TableName;
- }
- if (!ADP.IsEmpty(colMetaData.SchemaName)) {
- schemaRow[BaseSchemaName] = colMetaData.SchemaName;
- }
- if (!ADP.IsEmpty(colMetaData.CatalogName)) {
- schemaRow[BaseCatalogName] = colMetaData.CatalogName;
- }
- if (!ADP.IsEmpty(colMetaData.ServerName)) {
- schemaRow[BaseServerName] = colMetaData.ServerName;
- }
- if ( SqlDbType.Udt == colMetaData.SqlDbType ) {
- schemaRow[DataTypeName] = colMetaData.TypeSpecificNamePart1 + "." + colMetaData.TypeSpecificNamePart2 + "." + colMetaData.TypeSpecificNamePart3;
- }
- else {
- schemaRow[DataTypeName] = metaType.TypeName;
- }
- // Add Xml metadata
- if ( SqlDbType.Xml == colMetaData.SqlDbType ) {
- schemaRow[XmlSchemaCollectionDatabase] = colMetaData.TypeSpecificNamePart1;
- schemaRow[XmlSchemaCollectionOwningSchema] = colMetaData.TypeSpecificNamePart2;
- schemaRow[XmlSchemaCollectionName] = colMetaData.TypeSpecificNamePart3;
- }
- schemaTable.Rows.Add(schemaRow);
- schemaRow.AcceptChanges();
- }
- // mark all columns as readonly
- foreach(DataColumn column in columns) {
- column.ReadOnly = true; // MDAC 70943
- }
- _schemaTable = schemaTable;
- }
- return _schemaTable;
- }
- //
- // ISqlRecord methods
- //
- public override SqlBinary GetSqlBinary(int ordinal) {
- EnsureCanGetCol( "GetSqlBinary", ordinal);
- return ValueUtilsSmi.GetSqlBinary(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlBoolean GetSqlBoolean(int ordinal) {
- EnsureCanGetCol( "GetSqlBoolean", ordinal);
- return ValueUtilsSmi.GetSqlBoolean(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlByte GetSqlByte(int ordinal) {
- EnsureCanGetCol( "GetSqlByte", ordinal);
- return ValueUtilsSmi.GetSqlByte(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlInt16 GetSqlInt16(int ordinal) {
- EnsureCanGetCol( "GetSqlInt16", ordinal);
- return ValueUtilsSmi.GetSqlInt16(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlInt32 GetSqlInt32(int ordinal) {
- EnsureCanGetCol( "GetSqlInt32", ordinal);
- return ValueUtilsSmi.GetSqlInt32(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlInt64 GetSqlInt64(int ordinal) {
- EnsureCanGetCol( "GetSqlInt64", ordinal);
- return ValueUtilsSmi.GetSqlInt64(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlSingle GetSqlSingle(int ordinal) {
- EnsureCanGetCol( "GetSqlSingle", ordinal);
- return ValueUtilsSmi.GetSqlSingle(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlDouble GetSqlDouble(int ordinal) {
- EnsureCanGetCol( "GetSqlDouble", ordinal);
- return ValueUtilsSmi.GetSqlDouble(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlMoney GetSqlMoney(int ordinal) {
- EnsureCanGetCol( "GetSqlMoney", ordinal);
- return ValueUtilsSmi.GetSqlMoney(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlDateTime GetSqlDateTime(int ordinal) {
- EnsureCanGetCol( "GetSqlDateTime", ordinal);
- return ValueUtilsSmi.GetSqlDateTime(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlDecimal GetSqlDecimal(int ordinal) {
- EnsureCanGetCol( "GetSqlDecimal", ordinal);
- return ValueUtilsSmi.GetSqlDecimal(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlString GetSqlString(int ordinal) {
- EnsureCanGetCol( "GetSqlString", ordinal);
- return ValueUtilsSmi.GetSqlString(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlGuid GetSqlGuid(int ordinal) {
- EnsureCanGetCol( "GetSqlGuid", ordinal);
- return ValueUtilsSmi.GetSqlGuid(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal]);
- }
- public override SqlChars GetSqlChars(int ordinal) {
- EnsureCanGetCol( "GetSqlChars", ordinal);
- return ValueUtilsSmi.GetSqlChars(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], _currentConnection.InternalContext);
- }
- public override SqlBytes GetSqlBytes(int ordinal) {
- EnsureCanGetCol( "GetSqlBytes", ordinal);
- return ValueUtilsSmi.GetSqlBytes(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], _currentConnection.InternalContext);
- }
- public override SqlXml GetSqlXml(int ordinal) {
- EnsureCanGetCol( "GetSqlXml", ordinal);
- return ValueUtilsSmi.GetSqlXml(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], _currentConnection.InternalContext);
- }
- public override TimeSpan GetTimeSpan(int ordinal) {
- EnsureCanGetCol("GetTimeSpan", ordinal);
- return ValueUtilsSmi.GetTimeSpan(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], _currentConnection.IsKatmaiOrNewer);
- }
- public override DateTimeOffset GetDateTimeOffset(int ordinal) {
- EnsureCanGetCol("GetDateTimeOffset", ordinal);
- return ValueUtilsSmi.GetDateTimeOffset(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], _currentConnection.IsKatmaiOrNewer);
- }
- public override object GetSqlValue(int ordinal) {
- EnsureCanGetCol( "GetSqlValue", ordinal);
- SmiMetaData metaData = _currentMetaData[ordinal];
- if (_currentConnection.IsKatmaiOrNewer) {
- return ValueUtilsSmi.GetSqlValue200(_readerEventSink, (SmiTypedGetterSetter)_currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext);
- }
- return ValueUtilsSmi.GetSqlValue(_readerEventSink, _currentColumnValuesV3, ordinal, metaData, _currentConnection.InternalContext); ;
- }
- public override int GetSqlValues(object[] values) {
- EnsureCanGetCol( "GetSqlValues", 0);
- if (null == values) {
- throw ADP.ArgumentNull("values");
- }
- int copyLength = (values.Length < _visibleColumnCount) ? values.Length : _visibleColumnCount;
- for(int i=0; i<copyLength; i++) {
- values[_indexMap[i]] = GetSqlValue(i);
- }
- return copyLength;
- }
- //
- // ISqlReader methods/properties
- //
- public override bool HasRows {
- get {return _hasRows;}
- }
- //
- // SqlDataReader method/properties
- //
- public override Stream GetStream(int ordinal) {
- EnsureCanGetCol("GetStream", ordinal);
- SmiQueryMetaData metaData = _currentMetaData[ordinal];
- // For non-null, non-variant types with sequential access, we support proper streaming
- if ((metaData.SqlDbType != SqlDbType.Variant) && (IsCommandBehavior(CommandBehavior.SequentialAccess)) && (!ValueUtilsSmi.IsDBNull(_readerEventSink, _currentColumnValuesV3, ordinal))) {
- if (HasActiveStreamOrTextReaderOnColumn(ordinal)) {
- throw ADP.NonSequentialColumnAccess(ordinal, ordinal + 1);
- }
- _currentStream = ValueUtilsSmi.GetSequentialStream(_readerEventSink, _currentColumnValuesV3, ordinal, metaData);
- return _currentStream;
- }
- else {
- return ValueUtilsSmi.GetStream(_readerEventSink, _currentColumnValuesV3, ordinal, metaData);
- }
- }
- public override TextReader GetTextReader(int ordinal) {
- EnsureCanGetCol("GetTextReader", ordinal);
-
- SmiQueryMetaData metaData = _currentMetaData[ordinal];
- // For non-variant types with sequential access, we support proper streaming
- if ((metaData.SqlDbType != SqlDbType.Variant) && (IsCommandBehavior(CommandBehavior.SequentialAccess)) && (!ValueUtilsSmi.IsDBNull(_readerEventSink, _currentColumnValuesV3, ordinal))) {
- if (HasActiveStreamOrTextReaderOnColumn(ordinal)) {
- throw ADP.NonSequentialColumnAccess(ordinal, ordinal + 1);
- }
- _currentTextReader = ValueUtilsSmi.GetSequentialTextReader(_readerEventSink, _currentColumnValuesV3, ordinal, metaData);
- return _currentTextReader;
- }
- else {
- return ValueUtilsSmi.GetTextReader(_readerEventSink, _currentColumnValuesV3, ordinal, metaData);
- }
- }
- public override XmlReader GetXmlReader(int ordinal) {
- // NOTE: sql_variant can not contain a XML data type: http://msdn.microsoft.com/en-us/library/ms173829.aspx
-
- EnsureCanGetCol("GetXmlReader", ordinal);
- if (_currentMetaData[ordinal].SqlDbType != SqlDbType.Xml) {
- throw ADP.InvalidCast();
- }
- Stream stream = null;
- if ((IsCommandBehavior(CommandBehavior.SequentialAccess)) && (!ValueUtilsSmi.IsDBNull(_readerEventSink, _currentColumnValuesV3, ordinal))) {
- if (HasActiveStreamOrTextReaderOnColumn(ordinal)) {
- throw ADP.NonSequentialColumnAccess(ordinal, ordinal + 1);
- }
- // Need to bypass the type check since streams are not usually allowed on XML types
- _currentStream = ValueUtilsSmi.GetSequentialStream(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], bypassTypeCheck: true);
- stream = _currentStream;
- }
- else {
- stream = ValueUtilsSmi.GetStream(_readerEventSink, _currentColumnValuesV3, ordinal, _currentMetaData[ordinal], bypassTypeCheck: true);
- }
- return SqlXml.CreateSqlXmlReader(stream);
- }
- //
- // Internal reader state
- //
- // Logical state of reader/resultset as viewed by the client
- // Does not necessarily match up with server state.
- internal enum PositionState
- {
- BeforeResults, // Before all resultset in request
- BeforeRows, // Before all rows in current resultset
- OnRow, // On a valid row in the current resultset
- AfterRows, // After all rows in current resultset
- AfterResults // After all resultsets in request
- }
- private PositionState _currentPosition; // Where is the reader relative to incoming results?
- //
- // Fields
- //
- private bool _isOpen; // Is the reader open?
- private SmiQueryMetaData[] _currentMetaData; // Metadata for current resultset
- private int[] _indexMap; // map of indices for visible column
- private int _visibleColumnCount; // number of visible columns
- private DataTable _schemaTable; // Cache of user-visible extended metadata while in results.
- private ITypedGetters _currentColumnValues; // Unmanaged-managed data marshalers/cache
- private ITypedGettersV3 _currentColumnValuesV3; // Unmanaged-managed data marshalers/cache for SMI V3
- private bool _hasRows; // Are there any rows in the current resultset? Must be able to say before moving to first row.
- private SmiEventStream _eventStream; // The event buffer that receives the events from the execution engine.
- private SmiRequestExecutor _requestExecutor; // The used to request actions from the execution engine.
- private SqlInternalConnectionSmi _currentConnection;
- private ReaderEventSink _readerEventSink; // The event sink that will process events from the event buffer.
- private FieldNameLookup _fieldNameLookup; // cached lookup object to improve access time based on field name
- private SqlSequentialStreamSmi _currentStream; // The stream on the current column (if any)
- private SqlSequentialTextReaderSmi _currentTextReader; // The text reader on the current column (if any)
- //
- // Internal methods for use by other classes in project
- //
- // Constructor
- //
- // Assumes that if there were any results, the first chunk of them are in the data stream
- // (up to the first actual row or the end of the resultsets).
- unsafe internal SqlDataReaderSmi (
- SmiEventStream eventStream, // the event stream that receives the events from the execution engine
- SqlCommand parent, // command that owns reader
- CommandBehavior behavior, // behavior specified for this execution
- SqlInternalConnectionSmi connection, // connection that owns everybody
- SmiEventSink parentSink, // Event sink of parent command
- SmiRequestExecutor requestExecutor
- ) : base( parent, behavior ) { //
- _eventStream = eventStream;
- _currentConnection = connection;
- _readerEventSink = new ReaderEventSink( this, parentSink );
- _currentPosition = PositionState.BeforeResults;
- _isOpen = true;
- _indexMap = null;
- _visibleColumnCount = 0;
- _currentStream = null;
- _currentTextReader = null;
- _requestExecutor = requestExecutor;
- }
- internal override SmiExtendedMetaData[] GetInternalSmiMetaData() {
- if (null == _currentMetaData || _visibleColumnCount == this.InternalFieldCount) {
- return _currentMetaData;
- }
- else {
- #if DEBUG
- // DEVNOTE: Interpretation of returned array currently depends on hidden columns
- // always appearing at the end, since there currently is no access to the index map
- // outside of this class. In Debug code, we check this assumption.
- bool sawHiddenColumn = false;
- #endif
- SmiExtendedMetaData[] visibleMetaData = new SmiExtendedMetaData[_visibleColumnCount];
- for(int i=0; i<_visibleColumnCount; i++) {
- #if DEBUG
- if (_currentMetaData[_indexMap[i]].IsHidden.IsTrue) {
- sawHiddenColumn = true;
- }
- else {
- Debug.Assert(!sawHiddenColumn);
- }
- #endif
- visibleMetaData[i] = _currentMetaData[_indexMap[i]];
- }
- return visibleMetaData;
- }
- }
- internal override int GetLocaleId(int ordinal) {
- EnsureCanGetMetaData( "GetLocaleId" );
- return (int)_currentMetaData[ordinal].LocaleId;
- }
-
- //
- // Private implementation methods
- //
- private int InternalFieldCount {
- get {
- if ( FNotInResults() ) {
- return 0;
- }
- else {
- return _currentMetaData.Length;
- }
- }
- }
- // Have we cleaned up internal resources?
- private bool IsReallyClosed() {
- return !_isOpen;
- }
- // Central checkpoint for closed recordset.
- // Any code that requires an open recordset should call this method first!
- // Especially any code that accesses unmanaged memory structures whose lifetime
- // matches the lifetime of the unmanaged recordset.
- internal void ThrowIfClosed( string operationName ) {
- if (IsClosed)
- throw ADP.DataReaderClosed( operationName );
- }
- // Central checkpoint to ensure the requested column can be accessed.
- // Calling this function serves to notify that it has been accessed by the user.
- [SuppressMessage("Microsoft.Performance", "CA1801:AvoidUnusedParameters")] // for future compatibility
- private void EnsureCanGetCol( string operationName, int ordinal) {
- EnsureOnRow( operationName );
- }
- internal void EnsureOnRow( string operationName ) {
- ThrowIfClosed( operationName );
- if (_currentPosition != PositionState.OnRow) {
- throw SQL.InvalidRead();
- }
- }
- internal void EnsureCanGetMetaData( string operationName ) {
- ThrowIfClosed( operationName );
- if (FNotInResults()) {
- throw SQL.InvalidRead(); //
- }
- }
- private bool FInResults() {
- return !FNotInResults();
- }
- private bool FNotInResults() {
- return (PositionState.AfterResults == _currentPosition || PositionState.BeforeResults == _currentPosition);
- }
- private void MetaDataAvailable( SmiQueryMetaData[] md, bool nextEventIsRow ) {
- Debug.Assert( _currentPosition != PositionState.AfterResults );
-
- _currentMetaData = md;
- _hasRows = nextEventIsRow;
- _fieldNameLookup = null;
- _schemaTable = null; // will be rebuilt based on new metadata
- _currentPosition = PositionState.BeforeRows;
- // calculate visible column indices
- _indexMap = new int[_currentMetaData.Length];
- int i;
- int visibleCount = 0;
- for(i=0; i<_currentMetaData.Length; i++) {
- if (!_currentMetaData[i].IsHidden.IsTrue) {
- _indexMap[visibleCount] = i;
- visibleCount++;
- }
- }
- _visibleColumnCount = visibleCount;
- }
- private bool HasActiveStreamOrTextReaderOnColumn(int columnIndex) {
- bool active = false;
- active |= ((_currentStream != null) && (_currentStream.ColumnIndex == columnIndex));
- active |= ((_currentTextReader != null) && (_currentTextReader.ColumnIndex == columnIndex));
- return active;
- }
- // Obsolete V2- method
- private void RowAvailable( ITypedGetters row ) {
- Debug.Assert( _currentPosition != PositionState.AfterResults );
- _currentColumnValues = row;
- _currentPosition = PositionState.OnRow;
- }
- private void RowAvailable( ITypedGettersV3 row ) {
- Debug.Assert( _currentPosition != PositionState.AfterResults );
- _currentColumnValuesV3 = row;
- _currentPosition = PositionState.OnRow;
- }
- private void StatementCompleted( ) {
- Debug.Assert( _currentPosition != PositionState.AfterResults );
- _currentPosition = PositionState.AfterRows;
- }
- private void ResetResultSet() {
- _currentMetaData = null;
- _visibleColumnCount = 0;
- _schemaTable = null;
- }
- private void BatchCompleted() {
- Debug.Assert( _currentPosition != PositionState.AfterResults );
- ResetResultSet();
- _currentPosition = PositionState.AfterResults;
- _eventStream.Close( _readerEventSink );
- }
- // An implementation of the IEventSink interface that either performs
- // the required enviornment changes or forwards the events on to the
- // corresponding reader instance. Having the event sink be a separate
- // class keeps the IEventSink methods out of SqlDataReader's inteface.
- private sealed class ReaderEventSink : SmiEventSink_Default {
- private readonly SqlDataReaderSmi reader;
- internal ReaderEventSink( SqlDataReaderSmi reader, SmiEventSink parent )
- : base( parent ) {
- this.reader = reader;
- }
- internal override void MetaDataAvailable( SmiQueryMetaData[] md, bool nextEventIsRow ) {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.MetaDataAvailable|ADV> %d#, md.Length=%d nextEventIsRow=%d.\n", reader.ObjectID, (null != md) ? md.Length : -1, nextEventIsRow);
-
- if (null != md) {
- for (int i=0; i < md.Length; i++) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.MetaDataAvailable|ADV> %d#, metaData[%d] is %ls%ls\n",
- reader.ObjectID, i, md[i].GetType().ToString(), md[i].TraceString());
- }
- }
- }
- this.reader.MetaDataAvailable( md, nextEventIsRow );
- }
- // Obsolete V2- method
- internal override void RowAvailable( ITypedGetters row ) {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.RowAvailable|ADV> %d# (v2).\n", reader.ObjectID);
- }
- this.reader.RowAvailable( row );
- }
- internal override void RowAvailable( ITypedGettersV3 row ) {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.RowAvailable|ADV> %d# (ITypedGettersV3).\n", reader.ObjectID);
- }
- this.reader.RowAvailable( row );
- }
- internal override void RowAvailable(SmiTypedGetterSetter rowData) {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.RowAvailable|ADV> %d# (SmiTypedGetterSetter).\n", reader.ObjectID);
- }
- this.reader.RowAvailable(rowData);
- }
- internal override void StatementCompleted( int recordsAffected ) {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.StatementCompleted|ADV> %d# recordsAffected=%d.\n", reader.ObjectID, recordsAffected);
- }
- // devnote: relies on SmiEventSink_Default to pass event to parent
- // Both command and reader care about StatementCompleted, but for different reasons.
- base.StatementCompleted( recordsAffected );
- this.reader.StatementCompleted( );
- }
- internal override void BatchCompleted() {
- if (Bid.AdvancedOn) {
- Bid.Trace("<sc.SqlDataReaderSmi.ReaderEventSink.BatchCompleted|ADV> %d#.\n", reader.ObjectID);
- }
- // devnote: relies on SmiEventSink_Default to pass event to parent
- // parent's callback *MUST* come before reader's BatchCompleted, since
- // reader will close the event stream during this call, and parent wants
- // to extract parameter values before that happens.
- base.BatchCompleted();
- this.reader.BatchCompleted();
- }
- }
-
- }
- }
|