OracleDataReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / DataOracleClient / System / Data / OracleClient / OracleDataReader.cs / 2 / OracleDataReader.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    using System.Collections;
    using System.Data;
    using System.Data.Common;
    using System.Data.ProviderBase; 
    using System.Data.SqlTypes;
    using System.Diagnostics; 
    using System.Runtime.CompilerServices; 
    using System.Runtime.InteropServices;
 
    //---------------------------------------------------------------------
    // OracleDataReader
    //
    //  Contains all the information about a single column in a result set, 
    //  and implements the methods necessary to describe column to Oracle
    //  and to extract the column data from the native buffer used to fetch 
    //  it. 
    //
    sealed public class OracleDataReader : DbDataReader { 
        private const int _prefetchMemory = 65536;  // maximum amount of data to prefetch

        private OracleConnection    _connection;
        private int                 _connectionCloseCount;  // The close count of the connection; used to decide if we're zombied 

        private OciStatementHandle  _statementHandle;       // the OCI statement handle we'll use to get data from; it must be non-null 
                                                            // for the data reader to be considered open 

        private string              _statementText;         // the text of the statement we executed; in Oracle9i, you can ask for this from the Statement handle. 

        private CommandBehavior     _commandBehavior;

        private OracleColumn[]      _columnInfo; 
        private NativeBuffer_RowBuffer        _buffer;
        private int                 _rowBufferLength;       // length of one buffered row. 
        private int                 _rowsToPrefetch;        // maximum number of rows we should prefetch (fits into _prefetchMemory) 

        private int                 _rowsTotal = 0;         // number of rows that we've fetched so far. 
        private bool                _isLastBuffer;          // true when we're pre-fetching, and we got end of data from the fetch. (There are still rows in the buffer)

        private bool                _endOfData;             // true when we've reached the end of the results
        private bool                _closeConnectionToo;    // true when we're created with CommandBehavior.CloseConnection 
        private bool                _keyInfoRequested;      // true when we're created with CommandBehavior.KeyInfo
 
        private byte                _hasRows;               // true when there is at least one row to be read. 
        private const byte x_hasRows_Unknown = 0;
        private const byte x_hasRows_False   = 1; 
        private const byte x_hasRows_True    = 2;

        private static int _objectTypeCount; // Bid counter
        internal readonly int ObjectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); 

        private FieldNameLookup     _fieldNameLookup;       // optimizes searching by strings 
        private DataTable           _schemaTable; 
        private int                 _recordsAffected;
 
        private OracleDataReader[]  _refCursorDataReaders;
        private int                 _nextRefCursor;

 

        // Construct from a command and a statement handle 
        internal OracleDataReader( OracleCommand command, OciStatementHandle statementHandle, string statementText, CommandBehavior commandBehavior ) { 
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = commandBehavior;
            _statementHandle        = statementHandle;

            _connection             = (OracleConnection)command.Connection; 
            _connectionCloseCount   = _connection.CloseCount;
            _columnInfo             = null; 
 
            if (OCI.STMT.OCI_STMT_SELECT == command.StatementType) {
                FillColumnInfo(); 

                _recordsAffected = -1;  // Don't know this until we read the last row

                if (IsCommandBehavior(CommandBehavior.SchemaOnly)) 
                    _endOfData = true;
            } 
            else { 
                _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out _recordsAffected, ErrorHandle);
                _endOfData = true; 
                _hasRows = x_hasRows_False;
            }

            _statementText          = statementText; 
            _closeConnectionToo     = IsCommandBehavior(CommandBehavior.CloseConnection);
 
            if (CommandType.Text == command.CommandType) 
                _keyInfoRequested   = IsCommandBehavior(CommandBehavior.KeyInfo);
        } 

        internal OracleDataReader( OracleConnection connection, OciStatementHandle statementHandle ){
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = CommandBehavior.Default;
            _statementHandle        = statementHandle; 
            _connection             = connection; 
            _connectionCloseCount   = _connection.CloseCount;
 
            _recordsAffected        = -1;   // REF CURSORS must be a select statement, yes?

            FillColumnInfo();
        } 

        // Construct from a command and an array of ref cursor parameter ordinals 
        internal OracleDataReader( OracleCommand command, ArrayList  refCursorParameterOrdinals, string  statementText, CommandBehavior commandBehavior ) { 
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = commandBehavior;
            _statementText          = statementText;
            _closeConnectionToo     = IsCommandBehavior(CommandBehavior.CloseConnection);
 
            if (CommandType.Text == command.CommandType)
                _keyInfoRequested   = IsCommandBehavior(CommandBehavior.KeyInfo); 
 
            ArrayList refCursorDataReaders = new ArrayList();
            int currentRecordsAffected = 0; 
            OracleDataReader currentDataReader = null;

            for (int i=0; i < refCursorParameterOrdinals.Count; i++) {
                int refCursorParameterOrdinal = (int)refCursorParameterOrdinals[i]; 

                OracleParameter resultParameter = command.Parameters[refCursorParameterOrdinal]; 
 
                if (OracleType.Cursor == resultParameter.OracleType) {
                    currentDataReader = (OracleDataReader)resultParameter.Value; 
                    currentDataReader._recordsAffected = currentRecordsAffected;
                    refCursorDataReaders.Add(currentDataReader);
                    resultParameter.Value = DBNull.Value;   // Remove this from the output parameter list to avoid confusion.
                } 
                else {
                    Debug.Assert(0 < resultParameter.CommandSetResult, "non-ref cursor, non recordsaffected parameter?"); 
                    currentRecordsAffected += (int)resultParameter.Value; 
                }
            } 
            _refCursorDataReaders = new OracleDataReader[refCursorDataReaders.Count];
            refCursorDataReaders.CopyTo(_refCursorDataReaders);

            // Set the first ref cursor as the result set 
            _nextRefCursor = 0;
            NextResultInternal(); 
        } 

        override public int Depth { 
            get {
                AssertReaderIsOpen("Depth");
                return 0;
            } 
        }
 
        private OciErrorHandle ErrorHandle { 
            //  Every OCI call needs an error handle, so make it available
            //  internally. 
            get {
                return _connection.ErrorHandle;
            }
        } 

        override public int FieldCount { 
            get { 
                AssertReaderIsOpen();
 
                if (null == _columnInfo)
                    return 0;

                return _columnInfo.Length; 
            }
        } 
 
        override public bool HasRows {
            get { 
                AssertReaderIsOpen();
                bool result = (x_hasRows_True == _hasRows);

                if (x_hasRows_Unknown == _hasRows) { 
                    result = ReadInternal();
 
                    if (null != _buffer) 
                        _buffer.MovePrevious(); // back up over the row in the buffer so the next read will return the row we read
 
                    _hasRows = (result) ? x_hasRows_True : x_hasRows_False;
                }
                return result;
            } 
        }
 
        override public bool IsClosed { 
            //  We rely upon the statement handle not being null as long as the
            //  data reader is open; once the data reader is closed, the first 
            //  thing that happens is the statement handle is nulled out.
            get { return (null == _statementHandle) || (null == _connection) || (_connectionCloseCount != _connection.CloseCount); }
        }
 
        private bool IsValidRow {
            get { 
                return !(_endOfData || null == _buffer || !_buffer.CurrentPositionIsValid); 
            }
        } 

        override public int RecordsAffected {
            get { return _recordsAffected; }
        } 

        override public object this[int i] { 
            get { return GetValue(i); } 
        }
 
        override public object this[string name] {
            get {
                int ordinal = GetOrdinal(name);
                return GetValue(ordinal); 
            }
        } 
 
        private void AssertReaderHasColumns() {
            if (0 >= FieldCount) { 
                throw ADP.DataReaderNoData();
            }
        }
        private void AssertReaderHasData() { 
            if (!IsValidRow) {
                throw ADP.DataReaderNoData(); 
            } 
        }
        private void AssertReaderIsOpen(string methodName) { 
            if (IsClosed) {
                throw ADP.DataReaderClosed(methodName);
            }
        } 

        private void AssertReaderIsOpen() { 
            //  perform all the checks to make sure that the data reader and it's 
            //  connection are still open, and throw if they aren't
 
            if (null != _connection && (_connectionCloseCount != _connection.CloseCount))
                Close();

            if (null == _statementHandle) 
                throw ADP.ClosedDataReaderError();
 
            if (null == _connection || ConnectionState.Open != _connection.State) 
                throw ADP.ClosedConnectionError();
        } 

        private object SetSchemaValue(string value) {
             if (ADP.IsEmpty(value))
                return DBNull.Value; 

             return value; 
        } 

        private void Cleanup() { 
            // release everything; we can't do anything from here on out.

            if (null != _buffer) {
                _buffer.Dispose(); 
                _buffer = null;
            } 
 
            if (null != _columnInfo) {
                // Only cleanup the column info when it's not the data reader 
                // that owns all the ref cursor data readers;
                if (null == _refCursorDataReaders) {
                    int i = _columnInfo.Length;
 
                    while (--i >= 0) {
                        if (null != _columnInfo[i]) { 
                            _columnInfo[i].Dispose(); 
                            _columnInfo[i] = null;
                        } 
                    }
                }
                _columnInfo = null;
            } 

        } 
 
        override public void Close() {
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try {
                // Note that we do this first, which triggers IsClosed to return true.
                OciHandle.SafeDispose(ref _statementHandle); 

                Cleanup(); 
 
                if (null != _refCursorDataReaders) {
                    int i = _refCursorDataReaders.Length; 

                    while (--i >= 0) {
                        OracleDataReader refCursorDataReader = _refCursorDataReaders[i];
                        _refCursorDataReaders[i] = null; 

                        if (null != refCursorDataReader) 
                            refCursorDataReader.Dispose(); 
                    }
                    _refCursorDataReaders = null; 
                }

                // If we were asked to close the connection when we're closed, then we need to
                // do that now. 
                if (_closeConnectionToo && null != _connection)
                    _connection.Close(); 
 
                _connection = null;
                _fieldNameLookup = null; 
                _schemaTable = null;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        private DataTable CreateSchemaTable(int columnCount) {
            DataTable schemaTable = new DataTable("SchemaTable"); 
            schemaTable.Locale = System.Globalization.CultureInfo.InvariantCulture;

            schemaTable.MinimumCapacity = columnCount;
 
            //
 
            DataColumn name             = 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 providerType     = new DataColumn(SchemaTableColumn.ProviderType,     typeof(System.Int32));
 
            DataColumn isLong           = new DataColumn(SchemaTableColumn.IsLong,           typeof(System.Boolean)); 
            DataColumn isNullable       = new DataColumn(SchemaTableColumn.AllowDBNull,      typeof(System.Boolean));
            DataColumn isAliased        = new DataColumn(SchemaTableColumn.IsAliased,        typeof(System.Boolean)); 
            DataColumn isExpression     = new DataColumn(SchemaTableColumn.IsExpression,     typeof(System.Boolean));
            DataColumn isKey            = new DataColumn(SchemaTableColumn.IsKey,            typeof(System.Boolean));
            DataColumn isUnique         = new DataColumn(SchemaTableColumn.IsUnique,         typeof(System.Boolean));
 
            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)); 

            ordinal.DefaultValue = 0; 
            isLong.DefaultValue = false;

            DataColumnCollection columns = schemaTable.Columns;
 
            columns.Add(name);
            columns.Add(ordinal); 
            columns.Add(size); 
            columns.Add(precision);
            columns.Add(scale); 

            columns.Add(dataType);
            columns.Add(providerType);
 
            columns.Add(isLong);
            columns.Add(isNullable); 
            columns.Add(isAliased); 
            columns.Add(isExpression);
            columns.Add(isKey); 
            columns.Add(isUnique);

            columns.Add(baseSchemaName);
            columns.Add(baseTableName); 
            columns.Add(baseColumnName);
 
            // mark all columns as readonly 
            for (int i=0; i < columns.Count; i++) {
                columns[i].ReadOnly = true; 
            }

            return schemaTable;
        } 

        internal void FillColumnInfo() { 
            // Gather the column information for the statement handle 

            int     columnCount; 
            bool    cannotPrefetch = false;

            // Count the number of columns
            _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_PARAM_COUNT, out columnCount, ErrorHandle); 
            _columnInfo = new OracleColumn[columnCount];
 
            // Create column objects for each column, have them get their 
            // descriptions and determine their location in a row buffer.
            _rowBufferLength = 0; 
            for (int i = 0; i < columnCount; i++) {
                _columnInfo[i] = new OracleColumn(_statementHandle, i, ErrorHandle, _connection);
                if (_columnInfo[i].Describe(ref _rowBufferLength, _connection, ErrorHandle))
                    cannotPrefetch = true; 
            }
 
            if (cannotPrefetch || 0 == _rowBufferLength) 
                _rowsToPrefetch = 1;
            else 
                _rowsToPrefetch = (_prefetchMemory + _rowBufferLength - 1) / _rowBufferLength;  // at least one row...

            Debug.Assert(1 <= _rowsToPrefetch, "bad prefetch rows value!");
        } 

        private void FillSchemaTable(DataTable schemaTable) { 
            Debug.Assert(null != _columnInfo, "FillSchemaTable: no columnInfo"); 

            DataColumn ProviderSpecificDataType = new DataColumn(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(System.Type)); 
            schemaTable.Columns.Add(ProviderSpecificDataType);

            int             columnCount = FieldCount;
            OracleSqlParser parser; 
            DbSqlParserColumnCollection parsedColumns = null;
            int parsedColumnsCount = 0; 
 
            if (_keyInfoRequested) {
                parser = new OracleSqlParser(); 
                parser.Parse(_statementText, _connection);

                parsedColumns = parser.Columns;
                parsedColumnsCount = parsedColumns.Count; 
            }
 
            for (int i = 0; i < columnCount; ++i) { 
                OracleColumn column = _columnInfo[i];
 
                DataRow newRow = schemaTable.NewRow();

                newRow[SchemaTableColumn.ColumnName]         = column.ColumnName;
                newRow[SchemaTableColumn.ColumnOrdinal]      = column.Ordinal; 

                if (column.IsLong | column.IsLob) 
                    newRow[SchemaTableColumn.ColumnSize]     = Int32.MaxValue;   //MDAC 82554 
                else
                    newRow[SchemaTableColumn.ColumnSize]     = column.SchemaTableSize; 

                newRow[SchemaTableColumn.NumericPrecision]   = column.Precision;
                newRow[SchemaTableColumn.NumericScale]       = column.Scale;
 
                newRow[SchemaTableColumn.DataType]           = column.GetFieldType();
                newRow[ProviderSpecificDataType]             = column.GetFieldOracleType(); 
                newRow[SchemaTableColumn.ProviderType]       = column.OracleType; 

                newRow[SchemaTableColumn.IsLong]             = column.IsLong | column.IsLob; 
                newRow[SchemaTableColumn.AllowDBNull]        = column.IsNullable;

                if (_keyInfoRequested && parsedColumnsCount == columnCount) {
                    DbSqlParserColumn parsedColumn = parsedColumns[i]; 

                    newRow[SchemaTableColumn.IsAliased]      = parsedColumn.IsAliased; 
                    newRow[SchemaTableColumn.IsExpression]   = parsedColumn.IsExpression; 
                    newRow[SchemaTableColumn.IsKey]          = parsedColumn.IsKey;
                    newRow[SchemaTableColumn.IsUnique]       = parsedColumn.IsUnique; 
                    newRow[SchemaTableColumn.BaseSchemaName] = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.SchemaName));
                    newRow[SchemaTableColumn.BaseTableName]  = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.TableName));
                    newRow[SchemaTableColumn.BaseColumnName] = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.ColumnName));
                } 
                else {
                    newRow[SchemaTableColumn.IsAliased]      = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.IsExpression]   = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.IsKey]          = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.IsUnique]       = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.BaseSchemaName] = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.BaseTableName]  = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.BaseColumnName] = DBNull.Value;     // don't know
                } 

                schemaTable.Rows.Add(newRow); 
                newRow.AcceptChanges(); 
            }
        } 

        override public string GetDataTypeName(int i) {
            AssertReaderIsOpen();
 
            if (null == _columnInfo)
                throw ADP.NoData(); 
 
            return _columnInfo[i].GetDataTypeName();
        } 

        override public Type GetProviderSpecificFieldType(int i) {
            if (null == _columnInfo) {
                AssertReaderIsOpen(); 
                throw ADP.NoData();
            } 
            return _columnInfo[i].GetFieldOracleType(); 
        }
 
        override public IEnumerator GetEnumerator() {
            return new DbEnumerator((IDataReader)this, IsCommandBehavior(CommandBehavior.CloseConnection));
        }
 
        override public Type GetFieldType(int i) {
            if (null == _columnInfo) { 
                AssertReaderIsOpen(); 
                throw ADP.NoData();
            } 
            return _columnInfo[i].GetFieldType();
        }

        override public string GetName(int i) { 
            if (null == _columnInfo) {
                AssertReaderIsOpen(); 
                throw ADP.NoData(); 
            }
            return _columnInfo[i].ColumnName; 
        }

        override public int GetOrdinal(string name) {
            AssertReaderIsOpen("GetOrdinal"); 
            AssertReaderHasColumns();
 
            if (null == _fieldNameLookup) { 
                _fieldNameLookup = new FieldNameLookup(this, -1);
            } 
            return _fieldNameLookup.GetOrdinal(name);
        }

        override public DataTable GetSchemaTable() { 
            DataTable schemaTable = _schemaTable;
            if (null == schemaTable) { 
                AssertReaderIsOpen("GetSchemaTable"); 

                if (0 < FieldCount) { 
                    schemaTable = CreateSchemaTable(FieldCount);
                    FillSchemaTable(schemaTable);
                    _schemaTable = schemaTable;
                } 
                else if (0 > FieldCount) {
                    throw ADP.DataReaderNoData(); 
                } 
            }
            return schemaTable; 
        }

        override public object GetValue(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            object value = _columnInfo[i].GetValue(_buffer); 
            return value; 
        }
 
        override public int GetValues(object[] values) {
            if (null == values)
                throw ADP.ArgumentNull("values");
 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            int copy = Math.Min(values.Length, FieldCount); 
            for (int i = 0; i < copy; ++i) {
                values[i] = _columnInfo[i].GetValue(_buffer); 
            }
            return copy;
        }
 
        override public bool GetBoolean(int i) {
            //  The Get methods all defer to the OracleColumn object 
            //  to perform the work. 

            throw ADP.NotSupported();   // Oracle doesn't really have boolean values 
        }

        override public byte GetByte(int i) {
            throw ADP.NotSupported();   // Oracle doesn't really have single-byte values 
        }
 
        override public long GetBytes( int i, long fieldOffset, byte[] buffer2, int bufferoffset, int length ) { 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetBytes(_buffer, fieldOffset, buffer2, bufferoffset, length);
        }

        override public char GetChar(int i) { 
            throw ADP.NotSupported();   // Oracle doesn't really have single-char values
        } 
 
        override public long GetChars( int i, long fieldOffset, char[] buffer2, int bufferoffset, int length ) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetChars(_buffer, fieldOffset, buffer2, bufferoffset, length);
        }
 
        override public DateTime GetDateTime(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].GetDateTime(_buffer);
        } 

        override public decimal GetDecimal(int i) {
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetDecimal(_buffer);
        } 
 
        override public double GetDouble(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetDouble(_buffer);
        }
 
        override public float GetFloat(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].GetFloat(_buffer);
        } 

        override public Guid GetGuid(int i) {
            throw ADP.NotSupported();   // Oracle doesn't really have GUID values.
        } 

        override public short GetInt16(int i) { 
            throw ADP.NotSupported();   // Oracle doesn't really have GUID values. 
        }
 
        override public int GetInt32(int i) {
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetInt32(_buffer); 
        }
 
        override public long GetInt64(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetInt64(_buffer);
        }

        override public Object GetProviderSpecificValue(int i) { 
            return GetOracleValue(i);
        } 
 
        override public int GetProviderSpecificValues(object[] values) {
            return GetOracleValues(values); 
        }

        override public string GetString(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetString(_buffer); 
        } 

        public TimeSpan GetTimeSpan(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetTimeSpan(_buffer);
        } 

        public OracleBFile GetOracleBFile(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleBFile(_buffer); 
        }

        public OracleBinary GetOracleBinary(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleBinary(_buffer); 
        } 

        public OracleDateTime GetOracleDateTime(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleDateTime(_buffer);
        } 

        public OracleLob GetOracleLob(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleLob(_buffer); 
        }

        public OracleMonthSpan GetOracleMonthSpan(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleMonthSpan(_buffer); 
        } 

        public OracleNumber GetOracleNumber(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleNumber(_buffer);
        } 

        public OracleString GetOracleString(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleString(_buffer); 
        }

        public OracleTimeSpan GetOracleTimeSpan(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleTimeSpan(_buffer); 
        } 

        public object GetOracleValue(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleValue(_buffer);
        } 

        public int GetOracleValues(object[] values) { 
            if (null == values) 
                throw ADP.ArgumentNull("values");
 
            AssertReaderIsOpen();
            AssertReaderHasData();
            int copy = Math.Min(values.Length, FieldCount);
            for (int i = 0; i < copy; ++i) { 
                values[i] = GetOracleValue(i);
            } 
            return copy; 
        }
 
        private bool IsCommandBehavior(CommandBehavior condition) {
            return (condition == (condition & _commandBehavior));
        }
 
        override public bool IsDBNull(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].IsDBNull(_buffer);
        } 

        override public bool NextResult() {
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                AssertReaderIsOpen("NextResult"); 
                _fieldNameLookup = null; 
                _schemaTable = null;
                return NextResultInternal(); 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        private bool NextResultInternal() { 
            Cleanup();
 
            if (null == _refCursorDataReaders || _nextRefCursor >= _refCursorDataReaders.Length) {
                _endOfData = true; // force current result to be done.
                _hasRows = x_hasRows_False;
                return false; 
            }
 
            if (_nextRefCursor > 0) { 
                _refCursorDataReaders[_nextRefCursor-1].Dispose();
                _refCursorDataReaders[_nextRefCursor-1] = null; 
            }

            // Note that we do this first, which triggers IsClosed to return true.
            OciStatementHandle oldStatementHandle = _statementHandle; 
            _statementHandle        = _refCursorDataReaders[_nextRefCursor]._statementHandle;
            OciHandle.SafeDispose(ref oldStatementHandle); 
 
            _connection             = _refCursorDataReaders[_nextRefCursor]._connection;
            _connectionCloseCount   = _refCursorDataReaders[_nextRefCursor]._connectionCloseCount; 
            _hasRows                = _refCursorDataReaders[_nextRefCursor]._hasRows;
            _recordsAffected        = _refCursorDataReaders[_nextRefCursor]._recordsAffected;
            _columnInfo             = _refCursorDataReaders[_nextRefCursor]._columnInfo;
            _rowBufferLength        = _refCursorDataReaders[_nextRefCursor]._rowBufferLength; 
            _rowsToPrefetch         = _refCursorDataReaders[_nextRefCursor]._rowsToPrefetch;
 
            _nextRefCursor++; 
            _endOfData = false;
            _isLastBuffer = false; 
            _rowsTotal = 0;
            return true;
        }
 
        override public bool Read() {
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                AssertReaderIsOpen("Read"); 
                bool result = ReadInternal();
                if (result)
                    _hasRows = x_hasRows_True;
                return result; 
            }
            finally { 
                Bid.ScopeLeave(ref hscp); 
            }
        } 

        private bool ReadInternal() {
            if (_endOfData)
                return false; 

            int rc; 
            int columnCount = _columnInfo.Length; 
            int i;
            NativeBuffer_RowBuffer buffer = _buffer; 
            bool mustRelease = false;
            bool[] mustReleaseBindHandle = new bool[columnCount];
            SafeHandle[] bindHandle = new SafeHandle[columnCount];
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                // Define each of the column buffers to Oracle, but only if it hasn't 
                // been defined before.
                if (null == buffer) { 
                    int templen = (_rowsToPrefetch > 1) ? _rowBufferLength : 0;  // Only tell oracle about the buffer length if we intend to fetch more rows

                    buffer = new NativeBuffer_RowBuffer(_rowBufferLength, _rowsToPrefetch);
 
                    buffer.DangerousAddRef(ref mustRelease);
 
                    for (i = 0; i < columnCount; ++i) 
                        _columnInfo[i].Bind(_statementHandle, buffer, ErrorHandle, templen);
 
                    _buffer = buffer;
                }
                else {
                    buffer.DangerousAddRef(ref mustRelease); 
                }
 
                // If we still have more data in the buffers we've pre-fetched, then 
                // we'll use it; we don't want to go to the server more than we absolutely
                // have to. 
                if (buffer.MoveNext())
                    return true;

                // If we've read the last buffer, and we've exhausted it, then we're 
                // really at the end of the data.
                if ( _isLastBuffer ) { 
                    _endOfData = true; 
                    return false;
                } 

                // Reset the buffer back to the beginning.
                buffer.MoveFirst();
 
                // For LONG and LOB data, we have to do work to prepare for each row (that's
                // why we don't prefetch rows that have these data types) 
                if (1 == _rowsToPrefetch) { 
                    for (i = 0; i < columnCount; ++i)
                        _columnInfo[i].Rebind(_connection, ref mustReleaseBindHandle[i], ref bindHandle[i]); 
                }

                // Now fetch the rows required.
                Debug.Assert(0 < _rowsToPrefetch, "fetching 0 rows will cancel the cursor"); 
                rc = TracedNativeMethods.OCIStmtFetch(
                                        _statementHandle,           // stmtp 
                                        ErrorHandle,                // errhp 
                                        _rowsToPrefetch,            // crows
                                        OCI.FETCH.OCI_FETCH_NEXT,   // orientation 
                                        OCI.MODE.OCI_DEFAULT        // mode
                                        );

                // Keep track of how many rows we actually fetched so far. 
                int previousRowsTotal = _rowsTotal;
                _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out _rowsTotal, ErrorHandle); 
 
                if (0 == rc)
                    return true; 

                if ((int)OCI.RETURNCODE.OCI_SUCCESS_WITH_INFO == rc) {
                    _connection.CheckError(ErrorHandle, rc);
                    return true; 
                }
                if ((int)OCI.RETURNCODE.OCI_NO_DATA == rc) { 
                    int rowsFetched = _rowsTotal - previousRowsTotal; 

                    if (0 == rowsFetched) { 
                        if (0 == _rowsTotal)
                            _hasRows = x_hasRows_False;

                        _endOfData = true; 
                        return false;
                    } 
 
                    buffer.NumberOfRows = rowsFetched;
                    _isLastBuffer = true; 
                    return true;
                }

                _endOfData = true; 
                _connection.CheckError(ErrorHandle, rc);
                return false; 
            } 
            finally {
                if (1 == _rowsToPrefetch) { 
                    for (i = 0; i < columnCount; ++i) {
                        if (mustReleaseBindHandle[i]) {
                            bindHandle[i].DangerousRelease();
                        } 
                    }
                } 
                if (mustRelease) { 
                    buffer.DangerousRelease();
                } 
            }
        }
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.OracleClient 
{
    using System; 
    using System.Collections;
    using System.Data;
    using System.Data.Common;
    using System.Data.ProviderBase; 
    using System.Data.SqlTypes;
    using System.Diagnostics; 
    using System.Runtime.CompilerServices; 
    using System.Runtime.InteropServices;
 
    //---------------------------------------------------------------------
    // OracleDataReader
    //
    //  Contains all the information about a single column in a result set, 
    //  and implements the methods necessary to describe column to Oracle
    //  and to extract the column data from the native buffer used to fetch 
    //  it. 
    //
    sealed public class OracleDataReader : DbDataReader { 
        private const int _prefetchMemory = 65536;  // maximum amount of data to prefetch

        private OracleConnection    _connection;
        private int                 _connectionCloseCount;  // The close count of the connection; used to decide if we're zombied 

        private OciStatementHandle  _statementHandle;       // the OCI statement handle we'll use to get data from; it must be non-null 
                                                            // for the data reader to be considered open 

        private string              _statementText;         // the text of the statement we executed; in Oracle9i, you can ask for this from the Statement handle. 

        private CommandBehavior     _commandBehavior;

        private OracleColumn[]      _columnInfo; 
        private NativeBuffer_RowBuffer        _buffer;
        private int                 _rowBufferLength;       // length of one buffered row. 
        private int                 _rowsToPrefetch;        // maximum number of rows we should prefetch (fits into _prefetchMemory) 

        private int                 _rowsTotal = 0;         // number of rows that we've fetched so far. 
        private bool                _isLastBuffer;          // true when we're pre-fetching, and we got end of data from the fetch. (There are still rows in the buffer)

        private bool                _endOfData;             // true when we've reached the end of the results
        private bool                _closeConnectionToo;    // true when we're created with CommandBehavior.CloseConnection 
        private bool                _keyInfoRequested;      // true when we're created with CommandBehavior.KeyInfo
 
        private byte                _hasRows;               // true when there is at least one row to be read. 
        private const byte x_hasRows_Unknown = 0;
        private const byte x_hasRows_False   = 1; 
        private const byte x_hasRows_True    = 2;

        private static int _objectTypeCount; // Bid counter
        internal readonly int ObjectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); 

        private FieldNameLookup     _fieldNameLookup;       // optimizes searching by strings 
        private DataTable           _schemaTable; 
        private int                 _recordsAffected;
 
        private OracleDataReader[]  _refCursorDataReaders;
        private int                 _nextRefCursor;

 

        // Construct from a command and a statement handle 
        internal OracleDataReader( OracleCommand command, OciStatementHandle statementHandle, string statementText, CommandBehavior commandBehavior ) { 
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = commandBehavior;
            _statementHandle        = statementHandle;

            _connection             = (OracleConnection)command.Connection; 
            _connectionCloseCount   = _connection.CloseCount;
            _columnInfo             = null; 
 
            if (OCI.STMT.OCI_STMT_SELECT == command.StatementType) {
                FillColumnInfo(); 

                _recordsAffected = -1;  // Don't know this until we read the last row

                if (IsCommandBehavior(CommandBehavior.SchemaOnly)) 
                    _endOfData = true;
            } 
            else { 
                _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out _recordsAffected, ErrorHandle);
                _endOfData = true; 
                _hasRows = x_hasRows_False;
            }

            _statementText          = statementText; 
            _closeConnectionToo     = IsCommandBehavior(CommandBehavior.CloseConnection);
 
            if (CommandType.Text == command.CommandType) 
                _keyInfoRequested   = IsCommandBehavior(CommandBehavior.KeyInfo);
        } 

        internal OracleDataReader( OracleConnection connection, OciStatementHandle statementHandle ){
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = CommandBehavior.Default;
            _statementHandle        = statementHandle; 
            _connection             = connection; 
            _connectionCloseCount   = _connection.CloseCount;
 
            _recordsAffected        = -1;   // REF CURSORS must be a select statement, yes?

            FillColumnInfo();
        } 

        // Construct from a command and an array of ref cursor parameter ordinals 
        internal OracleDataReader( OracleCommand command, ArrayList  refCursorParameterOrdinals, string  statementText, CommandBehavior commandBehavior ) { 
            OracleConnection.VerifyExecutePermission();
 
            _commandBehavior        = commandBehavior;
            _statementText          = statementText;
            _closeConnectionToo     = IsCommandBehavior(CommandBehavior.CloseConnection);
 
            if (CommandType.Text == command.CommandType)
                _keyInfoRequested   = IsCommandBehavior(CommandBehavior.KeyInfo); 
 
            ArrayList refCursorDataReaders = new ArrayList();
            int currentRecordsAffected = 0; 
            OracleDataReader currentDataReader = null;

            for (int i=0; i < refCursorParameterOrdinals.Count; i++) {
                int refCursorParameterOrdinal = (int)refCursorParameterOrdinals[i]; 

                OracleParameter resultParameter = command.Parameters[refCursorParameterOrdinal]; 
 
                if (OracleType.Cursor == resultParameter.OracleType) {
                    currentDataReader = (OracleDataReader)resultParameter.Value; 
                    currentDataReader._recordsAffected = currentRecordsAffected;
                    refCursorDataReaders.Add(currentDataReader);
                    resultParameter.Value = DBNull.Value;   // Remove this from the output parameter list to avoid confusion.
                } 
                else {
                    Debug.Assert(0 < resultParameter.CommandSetResult, "non-ref cursor, non recordsaffected parameter?"); 
                    currentRecordsAffected += (int)resultParameter.Value; 
                }
            } 
            _refCursorDataReaders = new OracleDataReader[refCursorDataReaders.Count];
            refCursorDataReaders.CopyTo(_refCursorDataReaders);

            // Set the first ref cursor as the result set 
            _nextRefCursor = 0;
            NextResultInternal(); 
        } 

        override public int Depth { 
            get {
                AssertReaderIsOpen("Depth");
                return 0;
            } 
        }
 
        private OciErrorHandle ErrorHandle { 
            //  Every OCI call needs an error handle, so make it available
            //  internally. 
            get {
                return _connection.ErrorHandle;
            }
        } 

        override public int FieldCount { 
            get { 
                AssertReaderIsOpen();
 
                if (null == _columnInfo)
                    return 0;

                return _columnInfo.Length; 
            }
        } 
 
        override public bool HasRows {
            get { 
                AssertReaderIsOpen();
                bool result = (x_hasRows_True == _hasRows);

                if (x_hasRows_Unknown == _hasRows) { 
                    result = ReadInternal();
 
                    if (null != _buffer) 
                        _buffer.MovePrevious(); // back up over the row in the buffer so the next read will return the row we read
 
                    _hasRows = (result) ? x_hasRows_True : x_hasRows_False;
                }
                return result;
            } 
        }
 
        override public bool IsClosed { 
            //  We rely upon the statement handle not being null as long as the
            //  data reader is open; once the data reader is closed, the first 
            //  thing that happens is the statement handle is nulled out.
            get { return (null == _statementHandle) || (null == _connection) || (_connectionCloseCount != _connection.CloseCount); }
        }
 
        private bool IsValidRow {
            get { 
                return !(_endOfData || null == _buffer || !_buffer.CurrentPositionIsValid); 
            }
        } 

        override public int RecordsAffected {
            get { return _recordsAffected; }
        } 

        override public object this[int i] { 
            get { return GetValue(i); } 
        }
 
        override public object this[string name] {
            get {
                int ordinal = GetOrdinal(name);
                return GetValue(ordinal); 
            }
        } 
 
        private void AssertReaderHasColumns() {
            if (0 >= FieldCount) { 
                throw ADP.DataReaderNoData();
            }
        }
        private void AssertReaderHasData() { 
            if (!IsValidRow) {
                throw ADP.DataReaderNoData(); 
            } 
        }
        private void AssertReaderIsOpen(string methodName) { 
            if (IsClosed) {
                throw ADP.DataReaderClosed(methodName);
            }
        } 

        private void AssertReaderIsOpen() { 
            //  perform all the checks to make sure that the data reader and it's 
            //  connection are still open, and throw if they aren't
 
            if (null != _connection && (_connectionCloseCount != _connection.CloseCount))
                Close();

            if (null == _statementHandle) 
                throw ADP.ClosedDataReaderError();
 
            if (null == _connection || ConnectionState.Open != _connection.State) 
                throw ADP.ClosedConnectionError();
        } 

        private object SetSchemaValue(string value) {
             if (ADP.IsEmpty(value))
                return DBNull.Value; 

             return value; 
        } 

        private void Cleanup() { 
            // release everything; we can't do anything from here on out.

            if (null != _buffer) {
                _buffer.Dispose(); 
                _buffer = null;
            } 
 
            if (null != _columnInfo) {
                // Only cleanup the column info when it's not the data reader 
                // that owns all the ref cursor data readers;
                if (null == _refCursorDataReaders) {
                    int i = _columnInfo.Length;
 
                    while (--i >= 0) {
                        if (null != _columnInfo[i]) { 
                            _columnInfo[i].Dispose(); 
                            _columnInfo[i] = null;
                        } 
                    }
                }
                _columnInfo = null;
            } 

        } 
 
        override public void Close() {
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID);
            try {
                // Note that we do this first, which triggers IsClosed to return true.
                OciHandle.SafeDispose(ref _statementHandle); 

                Cleanup(); 
 
                if (null != _refCursorDataReaders) {
                    int i = _refCursorDataReaders.Length; 

                    while (--i >= 0) {
                        OracleDataReader refCursorDataReader = _refCursorDataReaders[i];
                        _refCursorDataReaders[i] = null; 

                        if (null != refCursorDataReader) 
                            refCursorDataReader.Dispose(); 
                    }
                    _refCursorDataReaders = null; 
                }

                // If we were asked to close the connection when we're closed, then we need to
                // do that now. 
                if (_closeConnectionToo && null != _connection)
                    _connection.Close(); 
 
                _connection = null;
                _fieldNameLookup = null; 
                _schemaTable = null;
            }
            finally {
                Bid.ScopeLeave(ref hscp); 
            }
        } 
 
        private DataTable CreateSchemaTable(int columnCount) {
            DataTable schemaTable = new DataTable("SchemaTable"); 
            schemaTable.Locale = System.Globalization.CultureInfo.InvariantCulture;

            schemaTable.MinimumCapacity = columnCount;
 
            //
 
            DataColumn name             = 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 providerType     = new DataColumn(SchemaTableColumn.ProviderType,     typeof(System.Int32));
 
            DataColumn isLong           = new DataColumn(SchemaTableColumn.IsLong,           typeof(System.Boolean)); 
            DataColumn isNullable       = new DataColumn(SchemaTableColumn.AllowDBNull,      typeof(System.Boolean));
            DataColumn isAliased        = new DataColumn(SchemaTableColumn.IsAliased,        typeof(System.Boolean)); 
            DataColumn isExpression     = new DataColumn(SchemaTableColumn.IsExpression,     typeof(System.Boolean));
            DataColumn isKey            = new DataColumn(SchemaTableColumn.IsKey,            typeof(System.Boolean));
            DataColumn isUnique         = new DataColumn(SchemaTableColumn.IsUnique,         typeof(System.Boolean));
 
            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)); 

            ordinal.DefaultValue = 0; 
            isLong.DefaultValue = false;

            DataColumnCollection columns = schemaTable.Columns;
 
            columns.Add(name);
            columns.Add(ordinal); 
            columns.Add(size); 
            columns.Add(precision);
            columns.Add(scale); 

            columns.Add(dataType);
            columns.Add(providerType);
 
            columns.Add(isLong);
            columns.Add(isNullable); 
            columns.Add(isAliased); 
            columns.Add(isExpression);
            columns.Add(isKey); 
            columns.Add(isUnique);

            columns.Add(baseSchemaName);
            columns.Add(baseTableName); 
            columns.Add(baseColumnName);
 
            // mark all columns as readonly 
            for (int i=0; i < columns.Count; i++) {
                columns[i].ReadOnly = true; 
            }

            return schemaTable;
        } 

        internal void FillColumnInfo() { 
            // Gather the column information for the statement handle 

            int     columnCount; 
            bool    cannotPrefetch = false;

            // Count the number of columns
            _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_PARAM_COUNT, out columnCount, ErrorHandle); 
            _columnInfo = new OracleColumn[columnCount];
 
            // Create column objects for each column, have them get their 
            // descriptions and determine their location in a row buffer.
            _rowBufferLength = 0; 
            for (int i = 0; i < columnCount; i++) {
                _columnInfo[i] = new OracleColumn(_statementHandle, i, ErrorHandle, _connection);
                if (_columnInfo[i].Describe(ref _rowBufferLength, _connection, ErrorHandle))
                    cannotPrefetch = true; 
            }
 
            if (cannotPrefetch || 0 == _rowBufferLength) 
                _rowsToPrefetch = 1;
            else 
                _rowsToPrefetch = (_prefetchMemory + _rowBufferLength - 1) / _rowBufferLength;  // at least one row...

            Debug.Assert(1 <= _rowsToPrefetch, "bad prefetch rows value!");
        } 

        private void FillSchemaTable(DataTable schemaTable) { 
            Debug.Assert(null != _columnInfo, "FillSchemaTable: no columnInfo"); 

            DataColumn ProviderSpecificDataType = new DataColumn(SchemaTableOptionalColumn.ProviderSpecificDataType, typeof(System.Type)); 
            schemaTable.Columns.Add(ProviderSpecificDataType);

            int             columnCount = FieldCount;
            OracleSqlParser parser; 
            DbSqlParserColumnCollection parsedColumns = null;
            int parsedColumnsCount = 0; 
 
            if (_keyInfoRequested) {
                parser = new OracleSqlParser(); 
                parser.Parse(_statementText, _connection);

                parsedColumns = parser.Columns;
                parsedColumnsCount = parsedColumns.Count; 
            }
 
            for (int i = 0; i < columnCount; ++i) { 
                OracleColumn column = _columnInfo[i];
 
                DataRow newRow = schemaTable.NewRow();

                newRow[SchemaTableColumn.ColumnName]         = column.ColumnName;
                newRow[SchemaTableColumn.ColumnOrdinal]      = column.Ordinal; 

                if (column.IsLong | column.IsLob) 
                    newRow[SchemaTableColumn.ColumnSize]     = Int32.MaxValue;   //MDAC 82554 
                else
                    newRow[SchemaTableColumn.ColumnSize]     = column.SchemaTableSize; 

                newRow[SchemaTableColumn.NumericPrecision]   = column.Precision;
                newRow[SchemaTableColumn.NumericScale]       = column.Scale;
 
                newRow[SchemaTableColumn.DataType]           = column.GetFieldType();
                newRow[ProviderSpecificDataType]             = column.GetFieldOracleType(); 
                newRow[SchemaTableColumn.ProviderType]       = column.OracleType; 

                newRow[SchemaTableColumn.IsLong]             = column.IsLong | column.IsLob; 
                newRow[SchemaTableColumn.AllowDBNull]        = column.IsNullable;

                if (_keyInfoRequested && parsedColumnsCount == columnCount) {
                    DbSqlParserColumn parsedColumn = parsedColumns[i]; 

                    newRow[SchemaTableColumn.IsAliased]      = parsedColumn.IsAliased; 
                    newRow[SchemaTableColumn.IsExpression]   = parsedColumn.IsExpression; 
                    newRow[SchemaTableColumn.IsKey]          = parsedColumn.IsKey;
                    newRow[SchemaTableColumn.IsUnique]       = parsedColumn.IsUnique; 
                    newRow[SchemaTableColumn.BaseSchemaName] = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.SchemaName));
                    newRow[SchemaTableColumn.BaseTableName]  = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.TableName));
                    newRow[SchemaTableColumn.BaseColumnName] = SetSchemaValue(OracleSqlParser.CatalogCase(parsedColumn.ColumnName));
                } 
                else {
                    newRow[SchemaTableColumn.IsAliased]      = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.IsExpression]   = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.IsKey]          = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.IsUnique]       = DBNull.Value;     // don't know 
                    newRow[SchemaTableColumn.BaseSchemaName] = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.BaseTableName]  = DBNull.Value;     // don't know
                    newRow[SchemaTableColumn.BaseColumnName] = DBNull.Value;     // don't know
                } 

                schemaTable.Rows.Add(newRow); 
                newRow.AcceptChanges(); 
            }
        } 

        override public string GetDataTypeName(int i) {
            AssertReaderIsOpen();
 
            if (null == _columnInfo)
                throw ADP.NoData(); 
 
            return _columnInfo[i].GetDataTypeName();
        } 

        override public Type GetProviderSpecificFieldType(int i) {
            if (null == _columnInfo) {
                AssertReaderIsOpen(); 
                throw ADP.NoData();
            } 
            return _columnInfo[i].GetFieldOracleType(); 
        }
 
        override public IEnumerator GetEnumerator() {
            return new DbEnumerator((IDataReader)this, IsCommandBehavior(CommandBehavior.CloseConnection));
        }
 
        override public Type GetFieldType(int i) {
            if (null == _columnInfo) { 
                AssertReaderIsOpen(); 
                throw ADP.NoData();
            } 
            return _columnInfo[i].GetFieldType();
        }

        override public string GetName(int i) { 
            if (null == _columnInfo) {
                AssertReaderIsOpen(); 
                throw ADP.NoData(); 
            }
            return _columnInfo[i].ColumnName; 
        }

        override public int GetOrdinal(string name) {
            AssertReaderIsOpen("GetOrdinal"); 
            AssertReaderHasColumns();
 
            if (null == _fieldNameLookup) { 
                _fieldNameLookup = new FieldNameLookup(this, -1);
            } 
            return _fieldNameLookup.GetOrdinal(name);
        }

        override public DataTable GetSchemaTable() { 
            DataTable schemaTable = _schemaTable;
            if (null == schemaTable) { 
                AssertReaderIsOpen("GetSchemaTable"); 

                if (0 < FieldCount) { 
                    schemaTable = CreateSchemaTable(FieldCount);
                    FillSchemaTable(schemaTable);
                    _schemaTable = schemaTable;
                } 
                else if (0 > FieldCount) {
                    throw ADP.DataReaderNoData(); 
                } 
            }
            return schemaTable; 
        }

        override public object GetValue(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            object value = _columnInfo[i].GetValue(_buffer); 
            return value; 
        }
 
        override public int GetValues(object[] values) {
            if (null == values)
                throw ADP.ArgumentNull("values");
 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            int copy = Math.Min(values.Length, FieldCount); 
            for (int i = 0; i < copy; ++i) {
                values[i] = _columnInfo[i].GetValue(_buffer); 
            }
            return copy;
        }
 
        override public bool GetBoolean(int i) {
            //  The Get methods all defer to the OracleColumn object 
            //  to perform the work. 

            throw ADP.NotSupported();   // Oracle doesn't really have boolean values 
        }

        override public byte GetByte(int i) {
            throw ADP.NotSupported();   // Oracle doesn't really have single-byte values 
        }
 
        override public long GetBytes( int i, long fieldOffset, byte[] buffer2, int bufferoffset, int length ) { 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetBytes(_buffer, fieldOffset, buffer2, bufferoffset, length);
        }

        override public char GetChar(int i) { 
            throw ADP.NotSupported();   // Oracle doesn't really have single-char values
        } 
 
        override public long GetChars( int i, long fieldOffset, char[] buffer2, int bufferoffset, int length ) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetChars(_buffer, fieldOffset, buffer2, bufferoffset, length);
        }
 
        override public DateTime GetDateTime(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].GetDateTime(_buffer);
        } 

        override public decimal GetDecimal(int i) {
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetDecimal(_buffer);
        } 
 
        override public double GetDouble(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetDouble(_buffer);
        }
 
        override public float GetFloat(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].GetFloat(_buffer);
        } 

        override public Guid GetGuid(int i) {
            throw ADP.NotSupported();   // Oracle doesn't really have GUID values.
        } 

        override public short GetInt16(int i) { 
            throw ADP.NotSupported();   // Oracle doesn't really have GUID values. 
        }
 
        override public int GetInt32(int i) {
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetInt32(_buffer); 
        }
 
        override public long GetInt64(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData(); 
            return _columnInfo[i].GetInt64(_buffer);
        }

        override public Object GetProviderSpecificValue(int i) { 
            return GetOracleValue(i);
        } 
 
        override public int GetProviderSpecificValues(object[] values) {
            return GetOracleValues(values); 
        }

        override public string GetString(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetString(_buffer); 
        } 

        public TimeSpan GetTimeSpan(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetTimeSpan(_buffer);
        } 

        public OracleBFile GetOracleBFile(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleBFile(_buffer); 
        }

        public OracleBinary GetOracleBinary(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleBinary(_buffer); 
        } 

        public OracleDateTime GetOracleDateTime(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleDateTime(_buffer);
        } 

        public OracleLob GetOracleLob(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleLob(_buffer); 
        }

        public OracleMonthSpan GetOracleMonthSpan(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleMonthSpan(_buffer); 
        } 

        public OracleNumber GetOracleNumber(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleNumber(_buffer);
        } 

        public OracleString GetOracleString(int i) { 
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleString(_buffer); 
        }

        public OracleTimeSpan GetOracleTimeSpan(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData();
            return _columnInfo[i].GetOracleTimeSpan(_buffer); 
        } 

        public object GetOracleValue(int i) { 
            AssertReaderIsOpen();
            AssertReaderHasData();
            return _columnInfo[i].GetOracleValue(_buffer);
        } 

        public int GetOracleValues(object[] values) { 
            if (null == values) 
                throw ADP.ArgumentNull("values");
 
            AssertReaderIsOpen();
            AssertReaderHasData();
            int copy = Math.Min(values.Length, FieldCount);
            for (int i = 0; i < copy; ++i) { 
                values[i] = GetOracleValue(i);
            } 
            return copy; 
        }
 
        private bool IsCommandBehavior(CommandBehavior condition) {
            return (condition == (condition & _commandBehavior));
        }
 
        override public bool IsDBNull(int i) {
            AssertReaderIsOpen(); 
            AssertReaderHasData(); 
            return _columnInfo[i].IsDBNull(_buffer);
        } 

        override public bool NextResult() {
            IntPtr hscp;
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                AssertReaderIsOpen("NextResult"); 
                _fieldNameLookup = null; 
                _schemaTable = null;
                return NextResultInternal(); 
            }
            finally {
                Bid.ScopeLeave(ref hscp);
            } 
        }
 
        private bool NextResultInternal() { 
            Cleanup();
 
            if (null == _refCursorDataReaders || _nextRefCursor >= _refCursorDataReaders.Length) {
                _endOfData = true; // force current result to be done.
                _hasRows = x_hasRows_False;
                return false; 
            }
 
            if (_nextRefCursor > 0) { 
                _refCursorDataReaders[_nextRefCursor-1].Dispose();
                _refCursorDataReaders[_nextRefCursor-1] = null; 
            }

            // Note that we do this first, which triggers IsClosed to return true.
            OciStatementHandle oldStatementHandle = _statementHandle; 
            _statementHandle        = _refCursorDataReaders[_nextRefCursor]._statementHandle;
            OciHandle.SafeDispose(ref oldStatementHandle); 
 
            _connection             = _refCursorDataReaders[_nextRefCursor]._connection;
            _connectionCloseCount   = _refCursorDataReaders[_nextRefCursor]._connectionCloseCount; 
            _hasRows                = _refCursorDataReaders[_nextRefCursor]._hasRows;
            _recordsAffected        = _refCursorDataReaders[_nextRefCursor]._recordsAffected;
            _columnInfo             = _refCursorDataReaders[_nextRefCursor]._columnInfo;
            _rowBufferLength        = _refCursorDataReaders[_nextRefCursor]._rowBufferLength; 
            _rowsToPrefetch         = _refCursorDataReaders[_nextRefCursor]._rowsToPrefetch;
 
            _nextRefCursor++; 
            _endOfData = false;
            _isLastBuffer = false; 
            _rowsTotal = 0;
            return true;
        }
 
        override public bool Read() {
            IntPtr hscp; 
            Bid.ScopeEnter(out hscp, " %d#\n", ObjectID); 
            try {
                AssertReaderIsOpen("Read"); 
                bool result = ReadInternal();
                if (result)
                    _hasRows = x_hasRows_True;
                return result; 
            }
            finally { 
                Bid.ScopeLeave(ref hscp); 
            }
        } 

        private bool ReadInternal() {
            if (_endOfData)
                return false; 

            int rc; 
            int columnCount = _columnInfo.Length; 
            int i;
            NativeBuffer_RowBuffer buffer = _buffer; 
            bool mustRelease = false;
            bool[] mustReleaseBindHandle = new bool[columnCount];
            SafeHandle[] bindHandle = new SafeHandle[columnCount];
 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                // Define each of the column buffers to Oracle, but only if it hasn't 
                // been defined before.
                if (null == buffer) { 
                    int templen = (_rowsToPrefetch > 1) ? _rowBufferLength : 0;  // Only tell oracle about the buffer length if we intend to fetch more rows

                    buffer = new NativeBuffer_RowBuffer(_rowBufferLength, _rowsToPrefetch);
 
                    buffer.DangerousAddRef(ref mustRelease);
 
                    for (i = 0; i < columnCount; ++i) 
                        _columnInfo[i].Bind(_statementHandle, buffer, ErrorHandle, templen);
 
                    _buffer = buffer;
                }
                else {
                    buffer.DangerousAddRef(ref mustRelease); 
                }
 
                // If we still have more data in the buffers we've pre-fetched, then 
                // we'll use it; we don't want to go to the server more than we absolutely
                // have to. 
                if (buffer.MoveNext())
                    return true;

                // If we've read the last buffer, and we've exhausted it, then we're 
                // really at the end of the data.
                if ( _isLastBuffer ) { 
                    _endOfData = true; 
                    return false;
                } 

                // Reset the buffer back to the beginning.
                buffer.MoveFirst();
 
                // For LONG and LOB data, we have to do work to prepare for each row (that's
                // why we don't prefetch rows that have these data types) 
                if (1 == _rowsToPrefetch) { 
                    for (i = 0; i < columnCount; ++i)
                        _columnInfo[i].Rebind(_connection, ref mustReleaseBindHandle[i], ref bindHandle[i]); 
                }

                // Now fetch the rows required.
                Debug.Assert(0 < _rowsToPrefetch, "fetching 0 rows will cancel the cursor"); 
                rc = TracedNativeMethods.OCIStmtFetch(
                                        _statementHandle,           // stmtp 
                                        ErrorHandle,                // errhp 
                                        _rowsToPrefetch,            // crows
                                        OCI.FETCH.OCI_FETCH_NEXT,   // orientation 
                                        OCI.MODE.OCI_DEFAULT        // mode
                                        );

                // Keep track of how many rows we actually fetched so far. 
                int previousRowsTotal = _rowsTotal;
                _statementHandle.GetAttribute(OCI.ATTR.OCI_ATTR_ROW_COUNT, out _rowsTotal, ErrorHandle); 
 
                if (0 == rc)
                    return true; 

                if ((int)OCI.RETURNCODE.OCI_SUCCESS_WITH_INFO == rc) {
                    _connection.CheckError(ErrorHandle, rc);
                    return true; 
                }
                if ((int)OCI.RETURNCODE.OCI_NO_DATA == rc) { 
                    int rowsFetched = _rowsTotal - previousRowsTotal; 

                    if (0 == rowsFetched) { 
                        if (0 == _rowsTotal)
                            _hasRows = x_hasRows_False;

                        _endOfData = true; 
                        return false;
                    } 
 
                    buffer.NumberOfRows = rowsFetched;
                    _isLastBuffer = true; 
                    return true;
                }

                _endOfData = true; 
                _connection.CheckError(ErrorHandle, rc);
                return false; 
            } 
            finally {
                if (1 == _rowsToPrefetch) { 
                    for (i = 0; i < columnCount; ++i) {
                        if (mustReleaseBindHandle[i]) {
                            bindHandle[i].DangerousRelease();
                        } 
                    }
                } 
                if (mustRelease) { 
                    buffer.DangerousRelease();
                } 
            }
        }
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK