IRowset::GetNextRows

Fetches rows sequentially, remembering the previous position.

Syntax

HRESULT GetNextRows (
   HCHAPTER       hChapter,
   DBROWOFFSET    lRowsOffset,
   DBROWCOUNT     cRows,
   DBCOUNTITEM   *pcRowsObtained,
   HROW         **prghRows);

Parameters

  • hChapter
    [in] The chapter handle designating the rows to fetch. For nonchaptered rowsets, the caller must set hChapter to DB_NULL_HCHAPTER. For chaptered rowsets, DB_NULL_HCHAPTER designates the entire rowset.

  • 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 either to IRowset::GetNextRows or to IRowsetFind::FindNextRow with a null pBookmark value, 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, 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. A negative value means skipping the rows in a backward direction. There is no guarantee that skipping rows is done efficiently on a sequential rowset. If the data store 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, the provider sets *pcRowsObtained to zero and performs no further processing, returning immediately from the method invocation. No rows are fetched, the fetch direction and the next fetch position are unchanged, and lRowsOffset is ignored.

    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, IRowset::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 consumer-allocated memory large enough to return the handles of the requested number of rows. If the consumer-allocated memory is larger than needed, the provider fills in as many row handles as specified by pcRowsObtained; the contents of the remaining memory are undefined.

    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
    IRowset::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, as reported by DBPROP_MAXOPENROWS. The number of rows that were actually fetched is returned in *pcRowsObtained.

  • 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 provider called a method from IRowsetNotify in the consumer that had not yet returned, and the provider does not support reentrancy in this method.

  • 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

IRowset::GetNextRows fetches a sequence of rows. The provider maintains a next fetch position that is used in subsequent calls to either IRowset::GetNextRows or IRowsetFind::FindNextRow. The next fetch position is changed either by calling IRowset::GetNextRows or by calling IRowsetFind::FindNextRow with a null pBookmark value. Calling IRowsetFind::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, 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 IRowset::GetNextRows or by IRowsetFind::FindNextRow with a null pBookmark value.

For any rowset except a newly created rowset (or an existing rowset on which IRowset::RestartPosition has been called and before the consumer has fetched any rows), IRowset::GetNextRows or IRowsetFind::FindNextRow may adjust the next fetch position, until the end of the rowset (or the beginning, if DBPROP_CANSCROLLBACKWARDS is VARIANT_TRUE) is reached. After the end of the rowset is reached, calls to IRowset::GetNextRows or IRowsetFind::FindNextRow return DB_S_ENDOFROWSET. (Earlier 1.x providers may return DB_E_BADSTARTPOSITION.)

IRowset::RestartPosition is used to reset the next fetch position to its initial state ? that is, its state when the rowset was first created.

For a newly created rowset (or a rowset on which IRowset::RestartPosition has been called and before the consumer has fetched any rows), 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

Value of cRows

Initial next fetch position

lRowsOffset > 0

cRows is not zero

After lRowsOffset

lRowsOffset < 0

cRows is not zero

After N ? abs(lRowsOffset)

lRowsOffset = 0

cRows > 0

Before first row

lRowsOffset = 0

cRows < 0

After last row

The following table shows the row fetched and the resulting next fetch position when IRowset::GetNextRows is called with various positive and negative values of lRowsOffset and cRows. Assume the rowset contains five rows.

Note

For each IRowset::GetNextRows call in the first column, the second and third columns show the result when the call is made to a newly created rowset (or a rowset on which IRowset::RestartPosition has been called and before the consumer has fetched any rows).

If the first call to IRowset::GetNextRows is:

Row fetched

Resulting next fetch position

GetNextRows(hReserved, 2, 1,
   pcRowsObtained,
   prghRows);

3rd row

After 3rd row

GetNextRows(hReserved, 2, -1,
   pcRowsObtained,
   prghRows);

2nd row

Before 2nd row

GetNextRows(hReserved, -2, 1,
   pcRowsObtained,
   prghRows);

4th row

After 4th row

GetNextRows(hReserved, -2, -1,
   pcRowsObtained,
   prghRows);

3rd row

Before 3rd row

GetNextRows(hReserved, 0, 1,
   pcRowsObtained,
   prghRows);

1st row

After 1st row

GetNextRows(hReserved, 0, -1,
   pcRowsObtained,
   prghRows);

5th row

Before 5th row

The following example shows how the next fetch position is affected by a series of consecutive calls to IRowset::GetNextRows, beginning with a newly created rowset (or a rowset on which IRowset::RestartPosition has been called and before the consumer has fetched any rows) that contains six rows and has DBPROP_CANSCROLLBACKWARDS set to VARIANT_TRUE.

Note

An error will occur if the row fetched or next fetch position specified is beyond the range of the rowset.

Series of IRowset::GetNextRows calls

Row(s) fetched

New next

fetch position

GetNextRows(hReserved, 0, 1,
   pcRowsObtained,
   prghRows);

1st row

After 1st row

GetNextRows(hReserved, 1, 3,
   pcRowsObtained,
   prghRows);

3rd, 4th, and 5th rows

After 5th row

GetNextRows(hReserved, -2, -1,
   pcRowsObtained,
   prghRows);

3rd row

Before 3rd row

GetNextRows(hReserved, 0, -1,
   pcRowsObtained,
   prghRows);

2nd row

Before 2nd row

GetNextRows(hReserved, -1, 2,
   pcRowsObtained,
   prghRows);

1st and 2nd rows

After 2nd row

GetNextRows(hReserved, 4, -1,
   pcRowsObtained,
   prghRows);

6th row

Before 6th row

GetNextRows(hReserved, -2, 1,
   pcRowsObtained,
   prghRows);

4th row

After 4th 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 IRowset::RestartPosition resets the next fetch position to the same position as when the rowset is first created.

IRowset::GetNextRows increments, by 1, the reference count of each row for which it returns a handle. Therefore, if a handle is returned for a row that has already been fetched, the reference count of that row will be greater than 1. IRowset::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 ? IRowset::GetNextRows fetches the row normally, returns the row handle, and returns S_OK. However, when the consumer calls IRowset::GetData for the row, the provider returns DBSTATUS_E_CANTCONVERTVALUE as the status for the offending column.

Before changing the next fetch position, IRowset::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. 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 usually calls IRowset::RestartPosition to return it to a known position.

Whether a provider returns DB_S_ENDOFROWSET, DB_S_ROWLIMITEXCEEDED, or DB_S_STOPLIMITREACHED generally depends on which limit is encountered first. If the maximum number of row handles is obtained before trying to read past the rowset or beyond a resource limit, DB_S_ROWLIMITEXCEEDED is returned. If a resource limitation is reached when there are still row handles available and before attempting to read past the rowset, DB_S_STOPLIMITREACHED is returned. If the provider comes to the end of the rowset before using all of the available row handles and before reaching a resource limitation, DB_S_ENDOFROWSET is returned.

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

See Also

Reference

IRowset::GetData

IRowsetLocate::GetRowsAt

IRowsetLocate::GetRowsByBookmark

IRowsetScroll::GetRowsAtRatio