MDAC 2.5 SDK - OLE DB Programmer's Reference
Chapter 11: Integrated Indexes


 

Integrated Index Example

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:

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

  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;

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