MDAC 2.5 SDK - OLE DB Programmer's Reference
Chapter 10: Index Rowsets
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);
//
};