Decrementing the Reference Count on Row Handles

IRowset::ReleaseRows decrements the reference count on the rows specified in the rghRows array. A consumer must call ReleaseRows once for each time a row was fetched or each time the row had its reference count incremented by AddRefRow. When the reference count reaches zero, the row is released if the rowset is in immediate update mode.

In providers that implement IRowsetUpdate, rows are released unless there are pending changes on the row; the sample provider always performs rowset updates in immediate mode, which means that changes are immediately applied to the underlying data source. Therefore, the sample provider does not recognize any changes as pending. The source code for IRowset::ReleaseRows follows.

// CImpIRowset::ReleaseRows ---------------------------------------
//
// @mfunc Releases row handles
//
// @rdesc   Returns one of the following values:
//          @flag S_OK                   | success
//          @flag DB_S_ERRORSOCCURRED      | some elements of rghRows were invalid
//          @flag DB_E_ERRORSOCCURRED      | all elements of rghRows were invalid
//          @flag E_INVALIDARG             | rghRows was a NULL pointer and crow > 0
//
STDMETHODIMP CImpIRowset::ReleaseRows
    (
    DBCOUNTITEM      cRows,          //@parm IN | Number of rows to release
    const HROW      rghRows[],      //@parm IN | Array of handles of rows to be released
   DBROWOPTIONS   rgRowOptions[],   //@parm IN | Additional Options
   DBREFCOUNT      rgRefCounts[],   //@parm OUT | array of ref counts of released rows
   DBROWSTATUS      rgRowStatus[]   //@parm OUT | status array of for input rows
    )
{
    HRESULT hr           = S_OK;
    DBCOUNTITEM chRow     = 0L;
    DBCOUNTITEM   cErrors     = 0L;
    ROWBUFF     *pRowBuff = NULL;

    // check params
    if ( cRows && !rghRows )
        return ResultFromScode( E_INVALIDARG );

    while ( chRow < cRows )
   {
        // check the row handle
      hr = (m_pObj->m_prowbitsIBuffer)->IsSlotSet((ULONG) rghRows[chRow]);
        if ( (hr == S_OK) && (m_pObj->m_ulRowRefCount) &&
          (pRowBuff=m_pObj->GetRowBuff((DBCOUNTITEM) rghRows[chRow], TRUE)) && 
          (pRowBuff->ulRefCount) )
      {
            // Found valid row, so decrement reference counts.
            // (Internal error for refcount to be 0 here, since slot set.)
            --pRowBuff->ulRefCount;
            --m_pObj->m_ulRowRefCount;

         // stuff new refcount into caller's array
         if ( rgRefCounts )
            rgRefCounts[chRow] = pRowBuff->ulRefCount;

         if ( rgRowStatus )
            rgRowStatus[chRow] = DBROWSTATUS_S_OK;

            if ( pRowBuff->ulRefCount == 0 )
                ReleaseSlots( m_pObj->m_pIBuffer, (ULONG) rghRows[chRow], 1 );
      }
        else
      {
            // It is an error for client to try to release a row
            // for which "IsSetSlot" is false.  Client gave us an invalid handle.
            // Ignore it (we can't release it...) and report error when done.
         if ( rgRefCounts )
            rgRefCounts[chRow] = 0;

         if ( rgRowStatus )
            rgRowStatus[chRow] = DBROWSTATUS_E_INVALID;

            ++ cErrors;
      }

      chRow++;
   }

   // If everything went OK except errors in rows use DB_S_ERRORSOCCURRED.
   return cErrors ? ( cErrors < cRows ) ? 
         ResultFromScode( DB_S_ERRORSOCCURRED ) : 
          ResultFromScode( DB_E_ERRORSOCCURRED ) : 
          ResultFromScode( S_OK );
} 

See Also

Tasks

Writing an OLE DB Provider: An Introduction