The following code accesses the Employees table through the Emp_LastName_Index index, using IRowsetIndex for the index and IRowsetLocate for the table.
The index has two columns. The first column, Emp_LastName, is of type DBTYPE_WSTR with a length of 30 characters and is the key column. The second column is of type DBTYPE_BYTES with a length of 4 characters and contains the bookmark for the Employees table. In the information returned by IColumnsInfo::GetColumnInfo for this column, the DBCOLUMNFLAGS_ISBOOKMARK is set.
The code sample performs the following actions:
#include<oledb.h>
#include<stddef.h>
GetTableRowsetLocate(IOpenRowset* , BSTR, IRowsetLocate**);
PrintData(OLECHAR*, ULONG, HROW*);
IMalloc * pMalloc; // pMalloc is the default memory allocator
HRESULT hr;
int main() {
IOpenRowset *pIOpenRowset = NULL;
DBID IndxId;
IRowsetIndex *pIndex = NULL;
IRowset *pIndexRows = NULL;
IRowsetLocate *pIRSLocate =NULL;
ULONG *pColumns = NULL;
DBCOLUMNINFO **prgInfo;
OLECHAR **ppStringsBuffer;
IColumnsInfo *pIndxColsInfo = NULL;
IAccessor *pIndxAccsr = NULL;
HACCESSOR hIndexAccBmk = DB_INVALID_HACCESSOR;
// Initialize the database, create a session, and obtain, from the session object, a
// pointer pIOpenRowset to an IOpenRowset interface. Code not shown.
// Use IOpenRowset::OpenRowset to obtain a pointer to IRowsetIndex.
// Set the Index's DBID
IndxId.eKind = DBKIND_NAME;
IndxId.uName.pwszName = OLESTR("Emp_LastName_Index");
// Open the Index with default properties and default interfaces. (IRowsetIndex,
// IAccessor, IRowset, IColumnsInfo, IRowsetInfo).
pIOpenRowset->OpenRowset(NULL, NULL, &IndxId, IID_IRowsetIndex, 0, NULL,
(IUnknown**) &pIndex);
// Get a rowset for the table using a helper function.
GetTableRowsetLocate(pIOpenRowset, OLESTR("Employees"), &pIRSLocate);
// Get an accessor for the index.
pIndex->QueryInterface(IID_IAccessor, (void**) &pIndxAccsr);
// Get a rowset for index traversal.
pIndex->QueryInterface(IID_IRowset, (void**) &pIndexRows);
// Get a pointer to IColumnsInfo on the index and get information about the columns
// of the index.
pIndex->QueryInterface(IID_IColumnsInfo, (void**) &pIndxColsInfo);
pIndxColsInfo->GetColumnInfo(pColumns, prgInfo, ppStringsBuffer);
// Explore the DBCOLUMNINFO structures. The structure not corresponding to column
// 0 and with a flag DBCOLUMNFLAGS_ISBOOKMARK set is the bookmark to the base
// table. Suppose that the IColumnsInfo says that there are two columns, that
// column 1 (which corresponds to the key) contains a string, and that the base
// table bookmark is in column 2 and that it needs 4 bytes. Code not shown.
// Create index and table bindings and corresponding accessors.
typedef struct tagBmk{
OLECHAR * Name;
ULONG cBookmark;
BYTE vBookmark[4];
} Bmk;
DBBINDSTATUS rgStatus[2];
static DBBINDING IndxBinds[2]= {
{
1, // Ordinal of key column
0, // obValue
0, // No length
0, // No status
NULL, // No TypeInfo
NULL, // No Object
NULL, // No binding extensions
DBPART_VALUE, // Bind value
DBMEMOWNER_CLIENTOWNED, // Client-owned memory
DBPARAMIO_NOTPARAM,
0, // cbMaxLen ignored
0,
DBTYPE_WSTR | DBTYPE_BYREF, // DBTYPE
0, // No Scale
0 // No Precision
},
{
2, // Ordinal of base table bookmark
offsetof(Bmk, vBookmark), // Offset to value
offsetof(Bmk,cBookmark), // Offset to length
0, // No status
NULL, // No Type Info
NULL, // No object
NULL, // No binding extensions
DBPART_VALUE | DBPART_LENGTH, // Bind value and length
DBMEMOWNER_CLIENTOWNED, // Client-owned memory
DBPARAMIO_NOTPARAM,
4, // max length
0,
DBTYPE_BYTES, // DBTYPE
0, // No Scale
0 // No Precision
}
};
pIndxAccsr->CreateAccessor(DBACCESSOR_ROWDATA, 2, IndxBinds, 0, &hIndexAccBmk,
rgStatus);
//...
// Set a range Emp_LastName LIKE "Smith*". Notice that only the Name element of the
// Bmk structure is used.
Bmk Bookmark;
Bookmark.Name = OLESTR("Smith");
pIndex->SetRange(hIndexAccBmk, 1, &Bmk, 0, NULL, DBRANGE_PREFIX);
pIndex->Seek(hIndexAccBmk, 1, &Bmk, DBSEEK_GE);
// Traverse index within the range. For each matching index entry, retrieve the
// corresponding record in the Employees table.
ULONG cIdxRows = 0, cTabRows = 0;
HROW *phIdxRows = NULL, *phTabRows = NULL;
DBROWSTATUS rgRowStatus[1];
while(SUCCEEDED(hr = pIndexRows->GetNextRows(0, 0, 1, &cIdxRows, &phIdxRows)) &&
cIdxRows > 0) {
// Extract the bookmark from the index and read the table directly.
pIndexRows->GetData(*phIdxRows, hIndexAccBmk, &Bookmark);
pIRSLocate->GetRowsAt(0, NULL, Bookmark.cBookmark, &(Bookmark.vBookmark[0]), 0,
1, &cTabRows, &phTabRows);
PrintData(Bookmark.Name, cTabRows, phTabRows);
// Release memory
pMalloc->Free(Bookmark.Name);
// Release the index and table rows
pIndexRows->ReleaseRows(cIdxRows, phIdxRows, NULL, rgRowStatus, rgRowOptions);
pIRSLocate->ReleaseRows(cTabRows, phTabRows, NULL, rgRowStatus, rgRowOptions);
};
//Release the accessor
pIndxAccsr->ReleaseAccessor(hIndexAccBmk);
//...
};