Пример #1
0
        private bool ReadInternal()
        {
            if (_endOfData)
            {
                return(false);
            }

            int rc;
            int columnCount = _columnInfo.Length;
            int i;

            // 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

                NativeBuffer buffer = new NativeBuffer_RowBuffer(_rowBufferLength);
                buffer.NumberOfRows = _rowsToPrefetch;

                for (i = 0; i < columnCount; ++i)
                {
                    _columnInfo[i].Bind(_statementHandle, buffer, ErrorHandle, templen);
                }

                _buffer = buffer;
            }

            // 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);
                }
            }

            // 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);
        }