📄 icrrowsetimpl.h
字号:
if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_ABOUTTODO, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_SYNCHAFTER, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; } } } } nCurrentRow = nFetchStartPosition; // we already calculated the 'start fetch position' in the simulation stage ATLASSERT( nCurrentRow >= 0 && nCurrentRow <= cRowsInSet ); *pcRowsObtained = 0; CComHeapPtr<HROW> rghRowsAllocated; if (*prghRows == NULL) { DBROWOFFSET cHandlesToAlloc = cRowsFetched; rghRowsAllocated.Allocate(cHandlesToAlloc); if(rghRowsAllocated == NULL) return E_OUTOFMEMORY; *prghRows = rghRowsAllocated; } // now fetch the rows cRowsToFetch = cRows; while( cRowsToFetch > 0 && nCurrentRow >= 0 && nCurrentRow <= cRowsInSet ) { if( ( iStepSize == 1 && nCurrentRow == cRowsInSet ) || ( iStepSize == -1 && nCurrentRow == 0 ) ) break; DBROWOFFSET lRow = nCurrentRow; if( iStepSize > 0 ) { while(true) { RowClass* pRow = NULL; RowClass::KeyType key = lRow + 1; bool bFound = m_rgRowHandles.Lookup(key,pRow); if( bFound && pRow != NULL ) { if( pRow->m_status == DBPENDINGSTATUS_DELETED ) { lRow++; ATLASSERT( lRow < cRowsInSet ); continue; } } break; } } else { while(true) { lRow--; RowClass* pRow = NULL; RowClass::KeyType key = lRow + 1; bool bFound = m_rgRowHandles.Lookup(key,pRow); if( bFound && pRow != NULL ) { if( pRow->m_status == DBPENDINGSTATUS_DELETED ) { ATLASSERT( lRow >= 0 ); continue; } } break; } } ATLASSERT( lRow >= 0 && lRow < cRowsInSet ); hr = pT->CreateRow(lRow, *pcRowsObtained, *prghRows); if (FAILED(hr)) { RefRows(*pcRowsObtained, *prghRows, NULL, NULL, FALSE); for (ULONG iRowDel = 0; iRowDel < *pcRowsObtained; iRowDel++) *prghRows[iRowDel] = NULL; *pcRowsObtained = 0; return hr; } __if_exists(T::Fire_OnRowsetChange) { if (!m_bExternalFetch) pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_DIDEVENT, TRUE); } cRowsToFetch--; if( iStepSize > 0 ) nCurrentRow = lRow + iStepSize; else nCurrentRow = lRow; } // while // If we have multiple rows fetched, return one event, per the specification // containing all rows activated. if (*pcRowsObtained >= 1) { __if_exists(T::Fire_OnRowsetChange) { CAtlArray<HROW> rgActivated; for (size_t ulActivated = 0; ulActivated < *pcRowsObtained; ulActivated++) { // This is a bit of an assumption that all newly activated // rows would have the ref count as 1. Another way to solve this // problem would be to modify the signature of CreateRow to take // a CAtlArray<HROW> as a parameter and store the activated rows. RowClass* pActiveRow; if( m_rgRowHandles.Lookup((*prghRows)[ulActivated], pActiveRow ) && (pActiveRow != NULL && pActiveRow->m_dwRef == 1) ) { _ATLTRY { rgActivated.Add((*prghRows)[ulActivated]); } _ATLCATCH( e ) { _ATLDELETEEXCEPTION( e ); return E_OUTOFMEMORY; } } } if (rgActivated.GetCount() > 0) { pT->Fire_OnRowChange(pT, (DBCOUNTITEM)rgActivated.GetCount(), rgActivated.GetData(), DBREASON_ROW_ACTIVATE, DBEVENTPHASE_DIDEVENT, FALSE); } } } m_iRowset = nCurrentRow; if( *pcRowsObtained < (DBCOUNTITEM)cRows ) // we could not fetch the requested # of rows hr = DB_S_ENDOFROWSET; if (SUCCEEDED(hr)) rghRowsAllocated.Detach(); return hr; } STDMETHOD(GetNextRows)(HCHAPTER hReserved, DBROWOFFSET lRowsOffset, DBROWCOUNT cRows, DBCOUNTITEM *pcRowsObtained, HROW **prghRows) { if( m_bRemoveDeleted && m_bIRowsetUpdate ) return GetNextRowsSkipDeleted( hReserved, lRowsOffset, cRows, pcRowsObtained, prghRows ); DBROWOFFSET lTmpRows = lRowsOffset; ATLTRACE(atlTraceDBProvider, 2, _T("ICRRowsetImpl::GetNextRows\n")); T* pT = (T*) this; __if_exists(T::Fire_OnRowChange) { // Check to see if someone is in an event handler. If we do, then // we should return DB_E_NOTREENTRANT. if (!pT->IncrementMutex()) { // Note, we can't set this above this block because we may // inadvertantly reset somebody else's pcRowsObtained if (pcRowsObtained != NULL) *pcRowsObtained = 0; return DB_E_NOTREENTRANT; } else pT->DecrementMutex(); } if (pcRowsObtained != NULL) *pcRowsObtained = 0; if (prghRows == NULL || pcRowsObtained == NULL) return E_INVALIDARG; if (cRows == 0) return S_OK; HRESULT hr = S_OK; T::ObjectLock cab(pT); if (lRowsOffset < 0 && !m_bCanScrollBack) return DB_E_CANTSCROLLBACKWARDS; if (cRows < 0 && !m_bCanFetchBack) return DB_E_CANTFETCHBACKWARDS; // Calculate # of rows in set and the base fetch position. If the rowset // is at its head position, then lRowOffset < 0 means moving from the BACK // of the rowset and not the front. DBROWOFFSET cRowsInSet = (DBROWOFFSET)pT->m_rgRowData.GetCount(); if (((lRowsOffset == MINLONG_PTR) && (cRowsInSet != MINLONG_PTR)) || AbsVal(lRowsOffset) > cRowsInSet || ( AbsVal(lRowsOffset) == cRowsInSet && lRowsOffset < 0 && cRows < 0 ) || ( AbsVal(lRowsOffset) == cRowsInSet && lRowsOffset > 0 && cRows > 0 )) return DB_S_ENDOFROWSET; // In the case where the user is moving backwards after moving forwards, // we do not wrap around to the end of the rowset. if ((m_iRowset == 0 && !m_bReset && cRows < 0) || ((m_iRowset + lRowsOffset) > cRowsInSet) || (m_iRowset == cRowsInSet && lRowsOffset >= 0 && cRows > 0)) return DB_S_ENDOFROWSET; // Fire events for OKTODO and ABOUTTODO after all validation has taken // place but before any permanent changes to the rowset state take place __if_exists(T::Fire_OnRowsetChange) { // Only fire these events if we're not being called by a bookmark // operation (which is why m_bExternalFetch would be set to true) if(!m_bExternalFetch) { HRESULT hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_OKTODO, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_ABOUTTODO, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_SYNCHAFTER, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; } } } } // Note, if m_bReset, m_iRowset must be 0 if (lRowsOffset < 0 && m_bReset) m_iRowset = cRowsInSet; int iStepSize = cRows >= 0 ? 1 : -1; // If cRows == MINLONG_PTR, we can't use ABS on it. Therefore, we reset it // to a value just greater than cRowsInSet if (cRows == MINLONG_PTR && cRowsInSet != MINLONG_PTR) cRows = cRowsInSet + 2; // set the value to something we can deal with else cRows = AbsVal(cRows); if (iStepSize < 0 && m_iRowset == 0 && m_bReset && lRowsOffset <= 0) m_iRowset = cRowsInSet; lRowsOffset += m_iRowset; *pcRowsObtained = 0; CComHeapPtr<HROW> rghRowsAllocated; if (*prghRows == NULL) { DBROWOFFSET cHandlesToAlloc = __min(cRowsInSet, cRows); if (iStepSize == 1 && (cRowsInSet - lRowsOffset) < cHandlesToAlloc) cHandlesToAlloc = cRowsInSet - lRowsOffset; if (iStepSize == -1 && lRowsOffset < cHandlesToAlloc) cHandlesToAlloc = lRowsOffset; rghRowsAllocated.Allocate(cHandlesToAlloc); if(rghRowsAllocated == NULL) return E_OUTOFMEMORY; *prghRows = rghRowsAllocated; } while ((lRowsOffset >= 0 && cRows != 0) && ((lRowsOffset < cRowsInSet) || (lRowsOffset <= cRowsInSet && iStepSize < 0))) { // cRows > cRowsInSet && iStepSize < 0 if (lRowsOffset == 0 && cRows > 0 && iStepSize < 0) break; // in the case where we have iStepSize < 0, move the row back // further because we want the previous row DBROWOFFSET lRow = lRowsOffset; if ((lRowsOffset == 0) && (lTmpRows == 0) && (iStepSize < 0)) lRow = cRowsInSet; if (iStepSize < 0) lRow += iStepSize; hr = pT->CreateRow(lRow, *pcRowsObtained, *prghRows); if (FAILED(hr)) { RefRows(*pcRowsObtained, *prghRows, NULL, NULL, FALSE); for (ULONG iRowDel = 0; iRowDel < *pcRowsObtained; iRowDel++) *prghRows[iRowDel] = NULL; *pcRowsObtained = 0; return hr; } __if_exists(T::Fire_OnRowsetChange) { if (!m_bExternalFetch) pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_DIDEVENT, TRUE); } cRows--; lRowsOffset += iStepSize; } // If we have multiple rows fetched, return one event, per the specification // containing all rows activated. if (*pcRowsObtained >= 1) { __if_exists(T::Fire_OnRowsetChange) { CAtlArray<HROW> rgActivated; for (size_t ulActivated = 0; ulActivated < *pcRowsObtained; ulActivated++) { // This is a bit of an assumption that all newly activated // rows would have the ref count as 1. Another way to solve this // problem would be to modify the signature of CreateRow to take // a CAtlArray<HROW> as a parameter and store the activated rows. RowClass* pActiveRow; if( m_rgRowHandles.Lookup((*prghRows)[ulActivated], pActiveRow ) && (pActiveRow != NULL && pActiveRow->m_dwRef == 1) ) { _ATLTRY { rgActivated.Add((*prghRows)[ulActivated]); } _ATLCATCH( e ) { _ATLDELETEEXCEPTION( e ); return E_OUTOFMEMORY; } } } if (rgActivated.GetCount() > 0) { pT->Fire_OnRowChange(pT, (DBCOUNTITEM)rgActivated.GetCount(), rgActivated.GetData(), DBREASON_ROW_ACTIVATE, DBEVENTPHASE_DIDEVENT, FALSE); } } } m_iRowset = lRowsOffset; if ((lRowsOffset >= cRowsInSet && cRows) || (lRowsOffset < 0 && cRows) || (lRowsOffset == 0 && cRows > 0 && iStepSize < 0)) hr = DB_S_ENDOFROWSET; if (SUCCEEDED(hr)) rghRowsAllocated.Detach(); return hr; } STDMETHOD(ReleaseRows)(DBCOUNTITEM cRows, const HROW rghRows[], DBROWOPTIONS rgRowOptions[], DBREFCOUNT rgRefCounts[], DBROWSTATUS rgRowStatus[]) { ATLTRACE(atlTraceDBProvider, 2, _T("ICRRowsetImpl::ReleaseRows\n")); __if_exists(T::Fire_OnRowChange) { T* pT = (T*) this; // Check to see if someone is in an event handler. If we do, then // we should return DB_E_NOTREENTRANT. if (!pT->IncrementMutex()) return DB_E_NOTREENTRANT; else pT->DecrementMutex(); } if (cRows == 0) return S_OK; rgRowOptions; return RefRows(cRows, rghRows, rgRefCounts, rgRowStatus, FALSE); } STDMETHOD(RestartPosition)(HCHAPTER /*hReserved*/) { ATLTRACE(atlTraceDBProvider, 2, _T("ICRRowsetImpl::RestartPosition\n")); T* pT = (T*) this; __if_exists(T::Fire_OnRowsetChange) { // Check to see if someone is in an event handler. If we do, then // we should return DB_E_NOTREENTRANT. if (!pT->IncrementMutex()) return DB_E_NOTREENTRANT; else pT->DecrementMutex(); bool bNeedEvents = ((m_iRowset != 0 || !m_bReset)) ? true : false; // Only fire the events iff. we are actually causing a reset if (bNeedEvents) { HRESULT hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_OKTODO, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_ABOUTTODO, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; else { hrNotify = pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_SYNCHAFTER, FALSE); if (hrNotify == S_FALSE) return DB_E_CANCELED; } } } } // Check to see if DBPROP_CANHOLDROWS is set to false. In this case, // return a DB_E_ROWSNOTRELEASED. CComVariant varHoldRows; HRESULT hr = pT->GetPropValue(&DBPROPSET_ROWSET, DBPROP_CANHOLDROWS, &varHoldRows); if (FAILED(hr) || varHoldRows.boolVal == ATL_VARIANT_FALSE) { if (m_rgRowHandles.GetCount() > 0) { RowClass* pRow = NULL; POSITION pos = pT->m_rgRowHandles.GetStartPosition(); while (pos != NULL) { MapClass::CPair* pPair = pT->m_rgRowHandles.GetNext(pos); ATLASSERT( pPair != NULL ); HROW hRow = pPair->m_key; bool bFound = pT->m_rgRowHandles.Lookup(hRow, pRow); if (bFound && pRow != NULL && pRow->m_status != DBPENDINGSTATUS_UNCHANGED) { __if_exists(T::Fire_OnRowsetChange) { if (bNeedEvents) { pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_FAILEDTODO, TRUE); } } return DB_E_ROWSNOTRELEASED; } } } } m_iRowset = 0; m_bReset = true; __if_exists(T::Fire_OnRowsetChange) { // listener must comply so blow off ret val. if (bNeedEvents) pT->Fire_OnRowsetChange(pT, DBREASON_ROWSET_FETCHPOSITIONCHANGE, DBEVENTPHASE_DIDEVENT, TRUE); } return S_OK; } MapClass m_rgRowHandles; DBROWOFFSET m_iRowset; // cursor unsigned m_bCanScrollBack:1; unsigned m_bCanFetchBack:1; unsigned m_bRemoveDeleted:1; // DBPROP_REMOVEDELETED unsigned m_bIRowsetUpdate:1; // DBPROP_IRowsetUpdate unsigned m_bReset:1; unsigned m_bExternalFetch:1;};#endif // ifndef _ICRRowsetImpl_INCLUDED
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -