Integrated Index Example

The following code performs the same function as the code example in "Index Example," 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:

  1. Initializes the database and creates a session (not shown).

  2. Sets properties to request IRowsetIndex, which tells the rowset to use integrated indexes.

  3. Opens the Employees table with the Emp_LastName_Index index and obtains interfaces for the rowset.

  4. Gets information about the key columns in the Emp_LastName_Index.

  5. Establishes bindings for the index columns and creates an accessor for the key column.

  6. Sets a range on the rowset.

  7. Reads rows from the rowset in the specified range.
#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;

   // Initialize the database, create a session, and obtain, from the session object, a
   // pointer pIOpenRowset to an IOpenRowset interface. Code not shown.

   // 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);

   // 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. Code not shown.

   // 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);

   // Release the rowset.
   pIRowsetIndex->Release();
   pIColumnsInfo->Release();
   pIAccessor->Release();
   pIRowset->Release();
};