IRowsetLocate::GetRowsAt

Fetches rows starting with the row specified by an offset from a bookmark.

HRESULT GetRowsAt (
   HWATCHREGION   hReserved1,
   HCHAPTER            hChapter
   ULONG               cbBookmark,
   const BYTE *            pBookmark,
   LONG                  lRowsOffset,
   LONG                  cRows,
   ULONG *               pcRowsObtained,
   HROW **               prghRows);

Parameters

hReserved1

[in]
Reserved for future use. Providers ignore this parameter.

hChapter

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

cbBookmark

[in]
The length in bytes of the bookmark. This must not be zero.

pBookmark

[in]
A pointer to a bookmark that identifies the base row to be used. This can be a pointer to DBBMK_FIRST or DBBMK_LAST. If lRowsOffset is zero, then the provider fetches this row first; otherwise the provider skips this and subsequent rows up to the count specified in the offset, then fetches the following rows.

lRowsOffset

[in]
The signed count of rows from the origin bookmark to the target row. Deleted rows that the provider has removed from the rowset are not counted in the skip. The first row fetched is determined by the bookmark and this offset. For example, if lRowsOffset is zero, the first row fetched is the bookmarked row; if lRowsOffset is 1, the first row fetched is the row after the bookmarked row; if lRowsOffset is –1, the first row fetched is the row before the bookmarked row.

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

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.

See the Comments section for a full description of the semantics of lRowsOffset and cRows parameters.

pcRowsObtained

[out]
A pointer to memory in which to return the actual number of fetched rows. If the consumer has insufficient permission to fetch all rows, GetRowsAt 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

[in/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 was 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_BOOKMARKSKIPPED
The following behavior is only supported on rowsets that set the DBPROP_BOOKMARKSKIPPED property to VARIANT_TRUE. If this property is VARIANT_FALSE, this return code is never returned.

lRowsOffset was zero and the row specified by *pBookmark was deleted or is no longer a member of the rowset, or the row specified by the combination of *pBookmark and lRowsOffset is a row to which the consumer does not have access rights. GetRowsAt skipped that row. The full count of actual rows (cRows) will be met if there are enough rows available. The array of returned row handles does not have gaps for missing rows; the returned count is the number of rows actually fetched.

If a row is skipped, it is counted as one of the rows to be skipped for lRowsOffset. For example, if an offset of 1 is requested and the bookmark points to a row which is now missing, the offset is decremented by 1 and the provider begins by fetching the next row.

If this condition occurs along with another warning condition, the method returns the code for the other warning condition. Thus, whenever a consumer receives the return code for another warning condition, it should check to see whether this condition occurred.

DB_S_ENDOFROWSET
GetRowsAt reached the start or the end of the rowset or chapter and could not fetch all of the requested rows because the count extended beyond the end. 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
cbBookmark was zero or pBookmark was a null pointer.

pcRowsObtained or prghRows was a null pointer.

E_OUTOFMEMORY
The provider was unable to allocate sufficient memory in which to instantiate the rows or return the row handles.

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

DB_E_BADBOOKMARK
*pBookmark was invalid, incorrectly formed, or DBBMK_INVALID.

*pBookmark did not match any rows in the rowset. This includes the case when the row corresponding to the bookmark has been deleted and DBPROP_BOOKMARKSKIPPED was VARIANT_FALSE.

Note   Consumers should only attempt to use bookmarks that they have received from the provider. The provider is guaranteed only to handle bookmarks it gives out in a predictable manner. Attempting to use a random value as a bookmark is undefined; the provider may return DB_E_BADBOOKMARK, may return an unexpected row, or may terminate abnormally.

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

Given values for a bookmark, offset, and number of rows to fetch:

The following table defines the behavior of GetRowsAt for all combinations of these parameters.

Variable Description
N Total rows in the rowset.
B Row in the rowset specified by the bookmark parameters cbBookmark and pBookmark. Assume 1 ≤ B ≤ N, DBBMK_FIRST is equivalent to B = 1, and DBBMK_LAST is equivalent to B = N.
F lRowsOffset
r cRows

B + F r cRowsObtained Return code
B + F < 1 or
B + F > N
N/A 0 DB_E_BADSTARTPOSITION
1 ≤ B + F ≤ N 0 0 S_OK
1 ≤ B + F ≤ N 1 ≤ r ≤ N  – B  – F + 1 r S_OK
1 ≤ B + F ≤ N r > N  – B  – F + 1 N  – B  – F+1 DB_S_ENDOFROWSET
1 ≤ B + F ≤ N r < 0 and
abs(r) ≤ B + F
abs(r) S_OK
1 ≤ B + F ≤ N r < 0 and
abs(r) > B + F
B + F DB_S_ENDOFROWSET

Consumers that want to fetch forward, for example, 20 rows at a time, can use the call GetRowsAt( ..., B, 1, 20, ...) which allows for an easy check when reaching the end of the rowset. Similarly, consumers that want to fetch backward can use the call GetRowsAt(..., B, – 1, – 20, ...) to facilitate the detection of the beginning of the rowset. In the latter case, DBPROP_CANFETCHBACKWARDS must be set to VARIANT_TRUE.

The DBPROP_BOOKMARKSKIPPED property defines the behavior for cases in which there is no exact match for the bookmark pointed to by pBookmark. If this property is set to VARIANT_FALSE, then DB_E_BADBOOKMARK will be returned because the corresponding position is not well-defined. The behavior when this property is set to VARIANT_TRUE is as follows:

If the provider encounters a problem fetching a row — for example, data stored in a text file contains a letter in a numeric column — GetRowsAt 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.

For information about what GetRowsAt 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 GetRowsAt can detect changes made to rows in the rowset, see "Visibility of Changes" in Chapter 5.

GetRowsAt 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.

In order to use GetRowsAt several times in sequence to obtain successive rows, the consumer should obtain the bookmark of the last row of the previous set and use that, with a skip of 1, to position for fetching the next rows.

See Also

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