Searching for Records

Use the CeSeekDatabase function to search for a record in a database. The CeSeekDatabase function always uses the current sort order as specified in the call to CeOpenDatabase. If the CEDB_AUTOINCREMENT flag was specified, each read operation on the database will automatically increment the seek pointer from the current position to the next position.

The CeSeekDatabase function can perform different types of seek operations. When calling the function, you specify a flag that indicates the type of seek operation, and a value whose meaning depends on the specified flag. For example, to find a particular record, you specify the CEDB_SEEK_CEOID flag and the object identifier of the desired record. When CeSeekDatabase finds a record, the seek pointer is positioned at that record. Any subsequent read operation takes place at the location of the seek pointer.

Note A seek can only be performed on a sorted property value.

Seek operations are affected by the sort order associated with the open database handle. For example, suppose the Contacts database was opened using a sort on the name property. If you specify the CEDB_SEEK_VALUEFIRSTEQUAL flag and a value of "Joe Smith," the CeSeekDatabase function will search from the beginning of the database looking only at the name property of each record, stopping when, and if, a matching property is found.

You can change the sort order that was set when the database was created by using the CeSetDatabaseInfo function, but this is not usually advised. The system maintains a set of indexes and other information that it uses to optimize database searches for the specified sort orders. When new sort orders are specified, the system must revise all of that internal information, which can take several minutes for large databases. The following code example demonstrates a call to CeSeekDatabase.

CEOID oid, oidSeek;      // Object identifier of record sought/returned
DWORD dwIndex;           // Index of record seeked to

// set value of oidSeek appropriately...
// actual set operation omitted from this fragment
// Perform the seek
oid = CeSeekDatabase(hDb,
               CEDB_SEEK_CEOID, // request a seek operation
               oidSeek, // specifies the record to seek
               &dwIndex); // on success, index to the record
if (!oid)
      // error handling goes here; omitted from this fragment...
// Continues at this point only if record found 
// After finding the record, read it and get its data
oid = CeReadRecordProps(hDb, CEDB_ALLOWREALLOC, 
            &wCount, NULL, &lpBuffer, &wSize);

The following code example shows how to find a record in a database and read its properties into a buffer. The function GetAddressData takes two parameters: the object identifier of a record and a pointer to an application-defined ADDRESSDATA structure that receives the record's property data. First, the GetAddressData function allocates a temporary buffer for the property data, and then it calls the CeSeekDatabase function to find the record that has the given object identifier. If the record is found, the CeReadRecordProps function reads the property data into the temporary buffer. Finally, the property data is copied from the temporary buffer into the application-defined ADDRESSDATA structure.

// GetAddressData - Retrieves the contents of an address record
// Returns a code that indicates the result of the function
// pAddressData - Pointer to an application-defined ADDRESSDATA 
//    structure that receives the data from the address record
//
// Global variable:
//    g_hAddressDatabase - Open handle to the address database

ECODE GetAddressData(CEOID oidSeek, PADDRESSDATA pAddressData)
{
   LPBYTE lpBuffer;         // Buffer for address record
   WORD wSize = 1024;       // Size of buffer
   CEOID oid;               // Object identifier of record found or read
   DWORD dwIndex;           // Index of record seeked to
   WORD wCount;             // Number of properties in record
   int i;                   // Loop counter
   CEPROPID propid;         // Property identifier
   WORD wLength;            // String length
   ECODE ec = EC_SUCCESS;   // Error/success code

   lpBuffer = (LPBYTE) LocalAlloc(LMEM_FIXED, wSize);
   if (!lpBuffer) 
      return EC_OUTOFMEMORY;
    
   oid = CeSeekDatabase(g_hAddressDatabase, CEDB_SEEK_CEOID, 
      oidSeek, &dwIndex);
   if (!oid) 
      return EC_SEEK_FAILURE;
    
   oid = CeReadRecordProps(g_hAddressDatabase, CEDB_ALLOWREALLOC, 
      &wCount, NULL, &lpBuffer, &wSize);
   if (!oid) 
      return EC_READ_FAILURE;
    
   for (i = 0; i < wCount; i++ ) 
      {
      propid = ((CEPROPVAL*) lpBuffer)[i].propid;
        
      switch (propid) 
         {
         case HHPR_NAME:
         {
                            // Copy the addressee's name.
            TCHAR* pData;
         
            wLength = 
               lstrlen(((CEPROPVAL*) lpBuffer)[i].val.lpwstr);
            pData = (TCHAR*) LocalAlloc(LMEM_FIXED, 
               wLength * sizeof(TCHAR) + 1);
            If (pData) 
            {
               lstrcpy(pData, 
                  ((CEPROPVAL*) lpBuffer)[i].val.lpwstr);
               pAddressData->pwszName = pData;
            } 
            else 
            {
               ec = EC_OUTOFMEMORY;
            }
         }
         break;
                
         case HHPR_STREET:
         { 

                            // Copy the addressee's street address.
            TCHAR* pData;

            wLength = 
               lstrlen(((CEPROPVAL*)lpBuffer)[i].val.lpwstr);
            pData = (TCHAR*) LocalAlloc(LMEM_FIXED, 
               wLength * sizeof(TCHAR) + 1, FALSE);
            if (pData) 
            {
               lstrcpy(pData, 
                  ((CEPROPVAL*) lpBuffer)[i].val.lpwstr);
               pTaskData->pwszDescription = pData;
            }
            else 
            {
               ec = EC_OUTOFMEMORY;
            }
         }
         break;

            .
            .               // Copy the remaining record properties to 
            .               // the ADDRESSDATA structure.
            

         default:
            break;
      }

      if (ec != EC_SUCCESS)
         break;
   }
    
   if (lpBuffer) 
      LocalFree(lpBuffer);

   return ec;
}