The optimal way to compare bookmarks is by a direct memory comparison. However, some rowsets may include hints within the bookmark that depend on time or rowset generation. This might cause binary comparisons between two bookmarks for the same row to fail. If the provider does put hints in the bookmarks, they must expose IRowsetLocate, which has methods to compare two bookmarks and to return a stable hash value for a bookmark. If the provider does put hints in the bookmarks, it must be able to support IRowsetLocate, if requested, in order to compare two bookmarks and return a stable hash value for a bookmark.
If the DBPROP_LITERALBOOKMARKS property is VARIANT_TRUE, then consumers can do the comparison themselves. The method used depends on the scalar type of the bookmark. For example, if the bookmark was defined as a sequence of DBTYPE_BYTES, then the comparison is of unsigned bytes, with the most-significant byte in position 0.
Bookmarks can be compared only if they belong to the same rowset and are used within the lifetime of that rowset. The results of comparing bookmarks from different rowsets, or outside the lifetime of the rowset to which they belong, are undefined.
A consumer does not need an ordered query to have ordered bookmarks. In particular, it does not need an SQL ORDER BY clause. If a consumer requests SELECT * FROM <table-name> and the smart query processor delivers the scan in the least-cost physical seek order (meaningless ordering in terms of content), then the consumer may still be given a rowset with ordered bookmarks. To guarantee ordered bookmarks, the consumer specifies the DBPROP_ORDEREDBOOKMARKS property as VARIANT_TRUE in ICommandProperties::SetProperties. For some providers, bookmarks are always ordered.
If DBPROP_ORDEREDBOOKMARKS is VARIANT_TRUE, the order of the bookmarks reflects the order of delivery. That is, if the consumer has bookmark i < j, then it calls IRowsetLocate::GetRowsAt for bookmark i and keeps scanning. It is guaranteed to find j unless it is deleted; and if it is deleted, the consumer can see the gap in order as it passes it by. Conversely, if the consumer starts at j and scans forward, it never sees i. It just reaches the end of the rowset.