Index Example

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:

  1. Initialize the database and create a session (not shown).

  2. Obtain interfaces for the table and index. (Only the latter is shown.)

  3. Get information about the column types of the index rowset (not shown).

  4. Establish bindings for the table and index columns. (Only the latter is shown.)

  5. Create accessors for the table and index rowsets. (Only the latter is shown.)

  6. Read the index rowset and retrieve the corresponding row from the table rowset.

#include <oledb.h>
#include <stddef.h>

GetTableRowsetLocate(IOpenRowset* , BSTR, IRowsetLocate**);
IMalloc * pMalloc;         // pMalloc is the default memory allocator

int main() {
   IOpenRowset *      pIOpenRowset       = NULL;
   DBID               IndxId;
   IRowsetIndex *     pIndex             = NULL;
   IRowset *          pIndexRows         = NULL;
   IRowsetLocate *    pIRSLocate         = NULL;
   DBORDINAL *        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
      0,                              // cbMaxLen ignored
      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
      4,                              // max length
      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.
   DBCOUNTITEM      cIdxRows = 0, cTabRows = 0;
   HROW *           phIdxRows = NULL, *phTabRows = NULL;
   DBROWSTATUS      rgRowStatus[1];
   DBREFCOUNT       rgRefCount[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.

      // Release the index and table rows.
      pIndexRows->ReleaseRows(cIdxRows, phIdxRows, NULL, rgRefCount,
      pIRSLocate->ReleaseRows(cTabRows, phTabRows, NULL, rgRefCount,

   // Release the accessor.
   pIndxAccsr->ReleaseAccessor(hIndexAccBmk, NULL);

   return 0;

This topic is a part of: