Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / DataOracleClient / System / Data / OracleClient / OracleDataReader.cs / 1 / 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SemanticResultValue.cs
- InfocardInteractiveChannelInitializer.cs
- XmlDocument.cs
- EqualityComparer.cs
- SByteStorage.cs
- StdValidatorsAndConverters.cs
- DataGridViewRowConverter.cs
- ReadOnlyHierarchicalDataSourceView.cs
- InvalidContentTypeException.cs
- FontStyles.cs
- FunctionDescription.cs
- TypeRefElement.cs
- CompoundFileDeflateTransform.cs
- WebUtil.cs
- HebrewNumber.cs
- ClipboardProcessor.cs
- DynamicRenderer.cs
- CheckableControlBaseAdapter.cs
- _ListenerResponseStream.cs
- OpenFileDialog.cs
- UpdateEventArgs.cs
- ThreadStartException.cs
- ToolbarAUtomationPeer.cs
- SecurityDescriptor.cs
- Thread.cs
- _HeaderInfo.cs
- ChangeProcessor.cs
- AsmxEndpointPickerExtension.cs
- DataGrid.cs
- NameHandler.cs
- FileSystemEnumerable.cs
- SelectionEditor.cs
- FragmentNavigationEventArgs.cs
- MessagingDescriptionAttribute.cs
- InkCanvasInnerCanvas.cs
- PolicyManager.cs
- Size.cs
- OleDbCommandBuilder.cs
- GlobalAllocSafeHandle.cs
- ValueOfAction.cs
- Item.cs
- UnsafeNativeMethods.cs
- ObjectDataSourceFilteringEventArgs.cs
- HostingMessageProperty.cs
- GlyphInfoList.cs
- WebPartDisplayModeCancelEventArgs.cs
- ZipIOEndOfCentralDirectoryBlock.cs
- Normalization.cs
- LogRecordSequence.cs
- ObjectDataSource.cs
- Geometry3D.cs
- FixedSOMGroup.cs
- Evaluator.cs
- NavigationCommands.cs
- X509ScopedServiceCertificateElement.cs
- OverflowException.cs
- SelectionProcessor.cs
- WorkflowFileItem.cs
- MachineKeySection.cs
- DelegatedStream.cs
- VectorAnimationBase.cs
- MessageAction.cs
- SrgsElementFactoryCompiler.cs
- DictionaryContent.cs
- PropertyCondition.cs
- DropTarget.cs
- ApplicationSettingsBase.cs
- HwndSourceParameters.cs
- OutputCacheModule.cs
- UrlPropertyAttribute.cs
- OpenFileDialog.cs
- SyndicationSerializer.cs
- SystemUdpStatistics.cs
- CallbackValidatorAttribute.cs
- XPathBinder.cs
- NodeLabelEditEvent.cs
- CodeMemberField.cs
- RecognizeCompletedEventArgs.cs
- RegexCompilationInfo.cs
- FormattedText.cs
- ConfigurationPermission.cs
- RenderOptions.cs
- SqlSelectClauseBuilder.cs
- DiscoveryService.cs
- versioninfo.cs
- FormsAuthenticationEventArgs.cs
- QueryStringParameter.cs
- Duration.cs
- EdmItemCollection.cs
- FormCollection.cs
- HeaderedItemsControl.cs
- MatrixStack.cs
- XmlParserContext.cs
- SQLInt32.cs
- AnnotationObservableCollection.cs
- BamlTreeNode.cs
- CommandID.cs
- TextAction.cs
- RegexCompilationInfo.cs
- KnownTypesHelper.cs