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