IRowset::GetNextRows

Fetches rows sequentially, remembering the previous position.

HRESULT GetNextRows (
   HCHAPTER   hChapter,
   LONG         lRowsOffset,
   LONG         cRows,
   ULONG *      pcRowsObtained,
   HROW **      prghRows);

Parameters

hChapter

[in]
The chapter handle. For nonchaptered rowsets, hChapter is ignored.

lRowsOffset

[in]
The signed count of rows to skip before fetching rows. Deleted rows that the provider has removed from the rowset are not counted in the skip. If this value is zero and cRows continues in the same direction as the previous call to either GetNextRows, or FindNextRow with a null pBookmark value, then the first row fetched will be the next row after the last one fetched in the previous call. If this value is zero and cRows reverses direction, then the first row fetched will be the last one fetched in the previous call.

lRowsOffset can be a negative number only if the value of the DBPROP_CANSCROLLBACKWARDS property is VARIANT_TRUE.

There is no guarantee that skipping rows is done efficiently on a sequential rowset. If the data source resides on a remote server, there may be remote support for skipping without transferring the intervening records across the network, but this is not guaranteed. For information about how the provider implements skipping, see the documentation for the provider.

cRows

[in]
The number of rows to fetch. A negative number means to fetch backward. cRows can be a negative number only if the value of the DBPROP_CANFETCHBACKWARDS property is VARIANT_TRUE.

If cRows is zero, no rows are fetched; the fetch direction and the next fetch position are unchanged, and the provider performs no processing, returning immediately from the method invocation. Specifically, lRowsOffset is ignored in this situation.

If the provider does not discover any other errors, the method returns S_OK; whether the provider checks for any other errors is provider-specific.

pcRowsObtained

[out]
A pointer to memory in which to return the actual number of fetched rows. If a warning condition occurs, this number may be less than the number of rows available or requested, and is the number of rows actually fetched before the warning condition occurred. If the consumer has insufficient permission to fetch all rows, GetNextRows fetches all rows for which the consumer has sufficient permission and skips all other rows. If the method fails, *pcRowsObtained is
set to zero.

prghRows

[out]
A pointer to memory in which to return an array of handles of the fetched rows. If *prghRows is not a null pointer on input, it must be a pointer to memory large enough to return the handles of the requested number of rows. If *prghRows is a null pointer on input, the rowset allocates memory for the row handles and returns the address to this memory; the consumer releases this memory with IMalloc::Free after it releases the row handles. If *prghRows is a null pointer on input and *pcRowsObtained is zero on output or if the method fails, the provider does not allocate any memory and ensures that *prghRows is a null pointer on output.

Return Code

S_OK
The method succeeded.

DB_S_ENDOFROWSET
GetNextRows reached the start or the end of the rowset or chapter or the start or end of the range on an index rowset and could not fetch all requested rows because the count extended beyond the end. The next fetch position is before the start or after the end of the rowset. The number of rows actually fetched is returned in *pcRowsObtained; this will be less than cRows.

The rowset is being populated asynchronously and no additional rows are available at this time. To determine whether additional rows may be available, the consumer should call IDBAsynchStatus::GetStatus or listen for the IDBAsynchNotify::OnStop notification.

lRowsOffset indicated a position either more than one row before the first row of the rowset or more than one row after the last row, and the provider was a version 2.0 or greater provider. *pcRowsObtained is set to zero and no rows are returned.

DB_S_ROWLIMITEXCEEDED
Fetching the number of rows specified in cRows would have exceeded the total number of active rows supported by the rowset. The number of rows that were actually fetched is returned in *pcRowsObtained. This condition can occur only when there are more rows available than can be handled by the rowset. Thus, this condition never conflicts with those described in DB_S_ENDOFROWSET and DB_S_STOPLIMITREACHED, both of which imply that no more rows were available.

DB_S_STOPLIMITREACHED
Fetching rows required further execution of the command, such as when the rowset uses a server-side cursor. Execution has been stopped because a resource limit has been reached. The number of rows that were actually fetched is returned in *pcRowsObtained.

E_FAIL
A provider-specific error occurred.

E_INVALIDARG
pcRowsObtained or prghRows was a null pointer.

E_OUTOFMEMORY
The provider was unable to allocate sufficient memory to complete the request.

E_UNEXPECTED
ITransaction::Commit or ITransaction::Abort was called and the object is in a zombie state.

DB_E_BADCHAPTER
The rowset was chaptered and hChapter was invalid.

The rowset was single-chaptered and the specified chapter was not the currently open chapter. The consumer must use the currently open chapter or release the currently open chapter before specifying a new chapter.

DB_E_BADSTARTPOSITION
lRowsOffset indicated a position either more than one row before the first row of the rowset or more than one row after the last row, and the provider was a 1.x provider,

DB_E_CANCELED
Fetching rows was canceled during notification. No rows were fetched.

DB_E_CANTFETCHBACKWARDS
cRows was negative and the rowset cannot fetch backward.

DB_E_CANTSCROLLBACKWARDS
lRowsOffset was negative and the rowset cannot scroll backward.

DB_E_NOTREENTRANT
The consumer called this method while it was processing a notification, and it is an error to call this method while processing the specified DBREASON value.

DB_E_ROWSNOTRELEASED
The provider requires release of existing rows before new ones can be fetched. For more information, see DBPROP_CANHOLDROWS in "Rowset Properties" in Appendix C.

DB_SEC_E_PERMISSIONDENIED
The consumer did not have sufficient permission to fetch any of the rows; no rows were fetched.

Comments

GetNextRows fetches a sequence of rows. The provider maintains a next fetch position that is used in subsequent calls to either GetNextRows or FindNextRow. The next fetch position is changed either by calling GetNextRows, or by calling FindNextRow with a null pBookmark value. Calling FindNextRow with a non-null pBookmark value has no effect on the next fetch position. If the fetch direction is reversed from the previous call, then the next fetch position in the new direction is the last row that was fetched in the previous direction, otherwise the next fetch position is the row following the last row fetched by GetNextRows, or by FindNextRow with a null pBookmark value.

For a newly created rowset, or any time the next fetch position is prior to the first row of the rowset, the next fetch position is computed as follows, where N is the number of rows in the rowset. lRowsOffset can be less than zero only if DBPROP_CANSCROLLBACKWARDS is VARIANT_TRUE.

Value of lRowsOffset Next fetch position
lRowsOffset > 0 After lRowsOffset
lRowsOffset < 0 After N – abs(lRowsOffset)
lRowsOffset = 0 Before first row if cRows > 0, after last row if cRows < 0

For example:

GetNextRows call Row fetched New next fetch position
GetNextRows(hReserved, 2, 1,
    pcRowsObtained,
    prghRows);
3rd row After 3rd row
GetNextRows(hReserved, 2, -1,
    pcRowsObtained,
    prghRows);
2nd row After 1st row
GetNextRows(hReserved, -2, 1,
    pcRowsObtained,
    prghRows);
N – 1st row After N – 1st row
 GetNextRows(hReserved, -2, -1,
    pcRowsObtained,
    prghRows);
N – 2nd row After N – 3rd row

None of the other methods that fetch rows, except for IRowsetFind::FindNextRow with a null pBookmark value, has any effect on the next fetch position. However, IRowsetIndex::Seek sets the next fetch position to the row specified in the seek criteria, and RestartPosition resets the next fetch position to the same position as when the rowset is first created.

GetNextRows increments the reference count of each row for which it returns a handle by 1. Thus, if a handle is returned for a row that has already been fetched, the reference count of that row will be greater than 1. ReleaseRows must be called once for each time the handle to a row has been returned.

If the provider encounters a problem fetching a row—for example, data stored in a text file contains a letter in a numeric column—GetNextRows fetches the row normally, returns the row handle, and returns S_OK. However, when the consumer calls GetData for the row, the provider returns DBSTATUS_E_CANTCONVERTVALUE as the status for the offending column.

GetNextRows must always check for the conditions that cause E_INVALIDARG, E_UNEXPECTED, DB_E_CANTFETCHBACKWARDS, DB_E_CANTSCROLLBACKWARDS, DB_E_NOTREENTRANT, and DB_E_ROWSNOTRELEASED before changing the next fetch position. If it returns any other error besides these, the next fetch position is unknown. For example, the provider might have to perform actions that change the next fetch position in order to determine that the error DB_E_BADSTARTPOSITION occurred. When the next fetch position is unknown, the consumer generally calls RestartPosition to return it to a known position.

For information about what GetNextRows does when it fetches a row that it already has in its internal buffers, see "Uniqueness of Rows in the Rowset" in Chapter 4. For information about whether GetNextRows can detect changes made to rows in the rowset, see "Visibility of Changes" in Chapter 5.

See Also

IRowset::GetData, IRowsetLocate::GetRowsAt, IRowsetLocate::GetRowsByBookmark, IRowsetScroll::GetRowsAtRatio