Methods such as IRowset::GetNextRows, IRowsetLocate::GetRowsAt, IRowsetLocate::GetRowsByBookmarks, and IRowsetScroll::GetRowsAtRatio can fetch rows. These methods enable the consumer to get multiple row handles with a single call.
The provider manages its row buffers on behalf of the consumer. When a row is fetched, the provider stores it in a buffer local to the provider. It is probably stored in a native format, although how this is done is provider specific. The consumer does not have direct access to the provider's row buffer, except through reference accessors. Instead, the consumer uses IRowset::GetData to get a copy of the data and IRowsetChange::SetData to make changes to the data. For more information, see Chapter 6, "Getting and Setting Data."
In most cases, rows are processed in parallel. Subject to limitations of the command or to limits upon resources, the consumer can hold and work with as many rows as it needs. There is no concept of a single current row, although there is a next fetch row for IRowset::GetNextRows, which is used for sequential read operations.
If the rowset supports IRowsetLocate, then any pattern of rows can be held. In a sequential rowset (that is, a rowset that does not support IRowsetLocate), a rule may require rows to be released from prior GetNextRows calls before a new GetNextRows call can be made.
Individual row handles have associated reference counts. Methods that return row handles increment the reference counts of the returned row handles. The provider holds the rows until the consumer releases them with IRowset::ReleaseRows. The consumer must call ReleaseRows for the row once for each time it was fetched or IRowset::AddRefRows was called for it.
Rows are implicitly released only when the consumer calls IRowset::Release. Deleting a row does not release the row handle; whether the deletion is done by calling IRowsetChange::DeleteRows, calling IRowsetUpdate::Update on a row with a pending deletion, or calling IRowsetUpdate::Undo on a row with a pending insert, the consumer must call ReleaseRows to release the row.
The OLE DB provider keeps track of the next fetch position so that a sequence of calls to GetNextRows (with no skips, changes of direction, or intervening calls to FindNextRow, Seek, or RestartPosition) reads the entire rowset without skipping or repeating any row. The next fetch position is changed either by calling IRowset::GetNextRows, IRowset::RestartPosition, or IRowsetIndex::Seek, 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 rowset supports reversible fetch direction, and the fetch direction is reversed from the previous call to GetNextRows or FindNextRow with a null pBookmark value, then the next fetch position for GetNextRows or FindNextRow 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 either GetNextRows or FindNextRow with a null pBookmark value.
Rowsets can take a negative count of requested rows. This means that the absolute count of rows beginning with the first specified row and then moving backward will be returned. For example, the next fetch row in GetNextRows or the bookmarked row in IRowsetLocate::GetRowsAt is the specified row and those preceding it up to the absolute count will be returned. This behavior is independent of skip (offset) counts, which also can be negative.