The code in this example 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 bytes 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 will perform 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; // Code not shown. Initialize the database, create a session, and // obtain, from the session object, a pointer pIOpenRowset to an // IOpenRowset interface. // 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); // Code not shown: 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 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, &Bookmark, 0, NULL, DBRANGE_PREFIX); pIndex->Seek(hIndexAccBmk, 1, &Bookmark, 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, NULL); // };