MDAC 2.5 SDK - OLE DB Programmer's Reference
Chapter 11: Integrated Indexes
The following code performs the same function as the code example in "Index Example" in Chapter 10, "Index Rowsets," except that the index is integrated, not separate. It gains access to the Employees table through the Emp_LastName_Index index, using IRowsetIndex to specify and seek that range. The index has a single key column, Emp_LastName, of type DBTYPE_WSTR with a length of 30 characters.
The code sample performs the following actions:
#include <oledb.h>
#include <stddef.h>
PrintData(OLECHAR*, DWORD);
int main() {
IOpenRowset * pIOpenRowset = NULL;
DBID IndexId, TableId;
IRowsetIndex * pIRowsetIndex = NULL;
IRowset * pIRowset = NULL;
IColumnsInfo * pIColumnsInfo = NULL;
IAccessor * pIAccessor = NULL;
ULONG cColumns, cKeyCols, cProperties;
DBCOLUMNINFO * rgInfo;
OLECHAR * pStringsBuffer;
DBINDEXCOLUMNDESC * rgIndexColDesc;
DBPROPSET * rgProperties;
HACCESSOR hIndexAccessor = DB_NULL_HACCESSOR;
HRESULT hr;
// Code not shown. Initialize the database, create a session,
// and obtain, from the session object, a pointer pIOpenRowset
// to an IOpenRowset interface.
// Set the DBIDs for the table and the index.
TableId.eKind = DBKIND_NAME;
TableId.uName.pwszName = OLESTR("Employees");
IndexId.eKind = DBKIND_NAME;
IndexId.uName.pwszName = OLESTR("Emp_LastName_Index");
// Set properties to request IRowsetIndex.
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
rgPropSet[0].rgProperties = rgProp;
rgPropSet[0].cProperties = 1;
rgPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
rgProp[0].dwPropertyID = DBPROP_IRowsetIndex;
rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgProp[0].dwStatus = DBPROPSTATUS_OK;
rgProp[0].colid = DB_NULLID;
V_VT(&(rgProp[0].vValue)) = VT_BOOL;
V_BOOL(&(rgProp[0].vValue)) = VARIANT_TRUE;
// Use IOpenRowset::OpenRowset to open the table with the
// Emp_LastName_Index index and get a pointer to IRowsetIndex.
// Call QueryInterface to get pointers to IRowset, IAccessor,
// and IColumnsInfo. Note that all of these interfaces are on
// the base table rowset.
pIOpenRowset->OpenRowset(NULL, &TableId, &IndexId, IID_IRowsetIndex,
1, rgPropSet, (IUnknown**) &pIRowsetIndex);
pIRowsetIndex->QueryInterface(IID_IRowset, (LPVOID FAR*) &pIRowset);
pIRowsetIndex->QueryInterface(IID_IAccessor, (LPVOID FAR*)
&pIAccessor);
pIRowsetIndex->QueryInterface(IID_IColumnsInfo, (LPVOID FAR*)
&pIColumnsInfo);
// Get information about the rowset columns and information
// about the index.
pIColumnsInfo->GetColumnInfo(&cColumns, &rgInfo, &pStringsBuffer);
pIRowsetIndex->GetIndexInfo(&cKeyCols, &rgIndexColDesc, &cProperties,
rgProperties);
// Code not shown. Explore the DBINDEXCOLUMNDESC and DBCOLUMNINFO
// structures to determine which columns are key columns and
// what their metadata is. For each key column, call
// IColumnsInfo::MapColumnIds to determine the ordinal of
// the column. Suppose that these structures show that there
// is a single key column (column 1) that contains a 30-byte
// string. Free the structures allocated by the methods.
// Create an accessor to use when setting the index range
// and seeking for values.
typedef struct tagNameStruct {
DWORD dwStatus;
OLECHAR szLastName[30];
} NameStruct;
DBBINDSTATUS rgStatus[1];
static DBBINDING rgIndexBinding[1] = {
{
1, // Ordinal of key column
offsetof(NameStruct, szLastName), // Offset to value
0, // No length--assume
// null-termination
offsetof(NameStruct, dwStatus), // Offset to status
NULL, // No TypeInfo
NULL, // No object
NULL, // No binding extensions
DBPART_VALUE | DBPART_STATUS, // Bind value and status
DBMEMOWNER_CLIENTOWNED, // Client-owned memory
DBPARAMIO_NOTPARAM, // Not a parameter
30, // cbMaxLen
0, // Flags ignored
DBTYPE_WSTR, // Bind as fixed-length
// string
0, // No scale
0 // No precision
}
};
pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, rgIndexBinding, 0,
&hIndexAccessor, rgStatus);
// Set the range LastName LIKE "Smith*", and position the
// next fetch position to the start of this range.
NameStruct nsNameStruct;
nsNameStruct.szLastName = OLESTR("Smith");
nsNameStruct.dwStatus = DBSTATUS_S_OK;
pIRowsetIndex->SetRange(hIndexAccessor, 1, &nsNameStruct, 0, NULL,
DBRANGE_PREFIX);
// Traverse the Employees table within the range, and print
// each name found.
ULONG cRows = 0;
HROW * rghRows = NULL;
DBROWSTATUS rgRowStatus[1];
while(SUCCEEDED(hr=pIRowset->GetNextRows(0, 0, 1, &cRows, &rghRows))
&& cRows > 0) {
// Reuse the same accessor to get the name from the row
// and print it.
pIRowset->GetData(rghRows[0], hIndexAccessor, &nsNameStruct);
PrintData(nsNameStruct.szLastName, nsNameStruct.dwStatus);
// Release the row.
pIRowset->ReleaseRows(cRows, rghRows, NULL, NULL, rgRowStatus);
};
// Release the accessor.
pIAccessor->ReleaseAccessor(hIndexAccessor, NULL);
// Release the rowset.
pIRowsetIndex->Release();
pIColumnsInfo->Release();
pIAccessor->Release();
pIRowset->Release();
};