OLE DB Programmer's Reference |
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(); };
1998-2001 Microsoft Corporation. All rights reserved.