📄 ifrowsetimpl.h
字号:
/****************************************************************************** * $Id: IFRowsetImpl.h,v 1.1 2002/08/09 21:36:39 warmerda Exp $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: RowsetInterface implementation used for main features rowset. * Only used by CSFRowsetImpl in SFRS.h. * Author: Frank Warmerdam <warmerdam@pobox.com> * * This code is closely derived from the code in ATLDB.H for IRowsetImpl. * It basically modifies the CRowsetImpl to check overall status from * the row fetching mechanism (which comes from CVirtualArray). This is * all based on the fact that we don't know the rowset size in advance, and * so must avoid calling CVirtualArray.GetSize(). * * Note: also contains some fixes mentioned in ICRRowsetImpl.h from which it * was directly derived. * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** * * $Log: IFRowsetImpl.h,v $ * Revision 1.1 2002/08/09 21:36:39 warmerda * New * * Revision 1.2 2002/02/05 20:42:46 warmerda * use CheckRows() in GetNextRows() to check availability * * Revision 1.1 2002/01/31 16:47:24 warmerda * New * */#ifndef _IFRowsetImpl_INCLUDED#define _IFRowsetImpl_INCLUDEDtemplate <class T, class RowClass, class MapClass>HRESULT SFTransferData(T* pT, bool bReading, void* pData, RowClass* pRow, MapClass* /*pMap*/, HACCESSOR hAccessor){ ATLTRACE(atlTraceDBProvider, 2, _T("SFTransferData\n")); bool bFailed = false; bool bSucceeded = false; HRESULT hr = S_OK; __if_exists(T::Fire_OnFieldChange) { CAtlArray<DBORDINAL> rgColumns; HROW hNotifyRow = NULL; //HROW hNotifyRow = pT->m_rgRowHandles.ReverseLookup(pRow); { POSITION pos = pT->m_rgRowHandles.GetStartPosition(); while( pos != NULL ) { MapClass::CPair* pPair = pT->m_rgRowHandles.GetNext( pos ); ATLASSERT( pPair != NULL ); if( pPair->m_value == pRow ) { hNotifyRow = pPair->m_key; break; } } } } __if_exists(T::Fire_OnRowChange) { // We need to send the DBREASON_ROW_FIRSTCHANGE notification's // SYNCHAFTER phase in this function. IFF. we're deferred and // we have a newly changed row. CComVariant varDeferred; bool bDeferred; hr = pT->GetPropValue(&DBPROPSET_ROWSET, DBPROP_IRowsetUpdate, &varDeferred); (FAILED(hr) || varDeferred.boolVal == ATL_VARIANT_FALSE) ? bDeferred = false : bDeferred = true; } int cAvailableRows; cAvailableRows = pT->m_rgRowData.CheckRows(pRow->m_iRowset, 1 ); // Check for a deleted row if( cAvailableRows < 1 ) { __if_exists(T::Fire_OnFieldChange) { if( !bReading ) { SendRowsFirstChangeFailureNotification( pT, pRow, &hNotifyRow, bDeferred ); } } return DB_E_DELETEDROW; } // NOTE: This was checking against DBPENDINGSTATUS_DELETED. Instead, it // should check for DBPENDINGSTATUS_INVALIDROW (means a forced deleted // row). if (pRow->m_status == DBPENDINGSTATUS_INVALIDROW) { __if_exists(T::Fire_OnFieldChange) { if( !bReading ) { SendRowsFirstChangeFailureNotification( pT, pRow, &hNotifyRow, bDeferred ); } } return DB_E_DELETEDROW; } T::_BindType* pBinding; bool bFound = pT->m_rgBindings.Lookup((INT_PTR)hAccessor, pBinding); if (!bFound || pBinding == NULL) { __if_exists(T::Fire_OnFieldChange) { if( !bReading ) { SendRowsFirstChangeFailureNotification( pT, pRow, &hNotifyRow, bDeferred ); } } return DB_E_BADACCESSORHANDLE; } if (pData == NULL && pBinding->cBindings != 0) { __if_exists(T::Fire_OnFieldChange) { if( !bReading ) { SendRowsFirstChangeFailureNotification( pT, pRow, &hNotifyRow, bDeferred ); } } return E_INVALIDARG; } void* pDstData; void* pSrcData; if (bReading) { pDstData = pData; pSrcData = (void*) pT->m_rgRowData.GetRow( (int)pRow->m_iRowset, hr ); if( pSrcData == NULL || hr != S_OK ) return hr; } else { pSrcData = pData; pDstData = (void*) pT->m_rgRowData.GetRow( (int)pRow->m_iRowset, hr ); if( pDstData == NULL || hr != S_OK ) return hr; } if (!bReading) { // Send the OKTODO notification __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { HRESULT hrNotify; for (DBORDINAL l=0; l<pBinding->cBindings; l++) { _ATLTRY { rgColumns.Add(pBinding->pBindings[l].iOrdinal); } _ATLCATCH( e ) { _ATLDELETEEXCEPTION( e ); return E_FAIL; } } hrNotify = pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_OKTODO, FALSE); if ((hrNotify != S_OK) && (hrNotify != E_FAIL)) { __if_exists(T::Fire_OnRowChange) { if (bDeferred) pT->Fire_OnRowChange(pT, 1, &hNotifyRow, DBREASON_ROW_FIRSTCHANGE, DBEVENTPHASE_FAILEDTODO, TRUE); return DB_E_CANCELED; } } hrNotify = pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_ABOUTTODO, FALSE); if ((hrNotify != S_OK) && (hrNotify != E_FAIL)) { __if_exists(T::Fire_OnRowChange) { if (bDeferred) pT->Fire_OnRowChange(pT, 1, &hNotifyRow, DBREASON_ROW_FIRSTCHANGE, DBEVENTPHASE_FAILEDTODO, TRUE); return DB_E_CANCELED; } } hrNotify = pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_SYNCHAFTER, FALSE); if ((hrNotify != S_OK) && (hrNotify != E_FAIL)) { __if_exists(T::Fire_OnRowChange) { if (bDeferred) pT->Fire_OnRowChange(pT, 1, &hNotifyRow, DBREASON_ROW_FIRSTCHANGE, DBEVENTPHASE_FAILEDTODO, TRUE); return DB_E_CANCELED; } } } } __if_exists(T::Fire_OnRowChange) { if(bDeferred && pRow->m_status != DBPENDINGSTATUS_CHANGED && pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { HRESULT hrNotify = pT->Fire_OnRowChange(pT, 1, &hNotifyRow, DBREASON_ROW_FIRSTCHANGE, DBEVENTPHASE_SYNCHAFTER, FALSE); if ((hrNotify != S_OK) && (hrNotify != E_FAIL)) { __if_exists(T::Fire_OnFieldChange) { pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_FAILEDTODO, TRUE); } return DB_E_CANCELED; } } } } DBORDINAL cCols; ATLCOLUMNINFO* pColInfo = T::GetColumnInfo(pT, &cCols); for (DBORDINAL iBind =0; iBind < pBinding->cBindings; iBind++) { DBBINDING* pBindCur = &(pBinding->pBindings[iBind]); DBORDINAL iColInfo; for (iColInfo = 0; iColInfo < cCols && pBindCur->iOrdinal != pColInfo[iColInfo].iOrdinal; iColInfo++); if (iColInfo == cCols) { __if_exists(T::Fire_OnFieldChange) { if( !bReading ) { SendColumnSetFailureNotification( pT, hNotifyRow, pBinding, rgColumns ); SendRowsFirstChangeFailureNotification( pT, pRow, &hNotifyRow, bDeferred ); } } return DB_E_BADORDINAL; } ATLCOLUMNINFO* pColCur = &(pColInfo[iColInfo]); // Ordinal found at iColInfo BYTE* pSrcTemp = (bReading) ? (BYTE*)pSrcData + pColCur->cbOffset : (BYTE*)pSrcData + pBindCur->obValue; BYTE* pDstTemp = NULL; if (pBindCur->dwPart & DBPART_VALUE) pDstTemp = (bReading) ? (BYTE*)pDstData + pBindCur->obValue : (BYTE*)pDstData + pColCur->cbOffset; if (!bReading) { // Check to see that the appropriate data parts are available if ((pBindCur->dwPart & DBPART_LENGTH) && !(pBindCur->dwPart & DBPART_VALUE) && !(pBindCur->dwPart & DBPART_STATUS)) { __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_FAILEDTODO, TRUE); } } // Not sure why you would want to run SetData here! bFailed = true; continue; } } // Handle the the status for any consumer issues DBSTATUS dbStat = DBSTATUS_S_OK; if (bReading) { dbStat = pT->GetDBStatus(pRow, pColCur); if (dbStat == DBSTATUS_S_ISNULL) { if (pBindCur->dwPart & DBPART_STATUS) *((DBSTATUS*)((BYTE*)(pDstData) + pBindCur->obStatus)) = dbStat; // Set the length to 0 as reqiured by the spec. if (pBindCur->dwPart & DBPART_LENGTH) *((DBLENGTH*)((BYTE*)(pDstData) + pBindCur->obLength)) = 0; // Set the destination value to NULL if (pBindCur->dwPart & DBPART_VALUE) *pDstTemp = NULL; continue; } } else { // Allow the provider to do checking for DBSTATUS_S_ISNULL if (pBindCur->dwPart & DBPART_STATUS) { dbStat = *((DBSTATUS*)((BYTE*)(pSrcData) + pBindCur->obStatus)); // Return DBSTATUS_E_UNAVAILABLE if the status is DBSTATUS_S_OK // and either the value part is not bound or the length part is // bound and the type is DBTYPE_BYTES. // There was another entry of code here with LENGTH, NO VALUE, // and status was not DBSTATUS_S_ISNULL. May need to regenerate that if (dbStat == DBSTATUS_S_OK) { if (!(pBindCur->dwPart & DBPART_VALUE) || ((pBindCur->dwPart & DBPART_LENGTH) && (pBindCur->wType == DBTYPE_BYTES))) { // Can't set non-null columns w/o a value part __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_FAILEDTODO, TRUE); } } bFailed = true; *((DBSTATUS*)((BYTE*)(pSrcData) + pBindCur->obStatus)) = DBSTATUS_E_UNAVAILABLE; continue; } } switch (dbStat) { case DBSTATUS_S_ISNULL: if (!(pColCur->dwFlags & DBCOLUMNFLAGS_ISNULLABLE) || FAILED(pT->SetDBStatus(&dbStat, pRow, pColCur))) { __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_FAILEDTODO, TRUE); } } // Special processing for attempting to write, read-only columns if (!(pColCur->dwFlags & DBCOLUMNFLAGS_ISNULLABLE)) *((DBSTATUS*)((BYTE*)(pSrcData) + pBindCur->obStatus)) = DBSTATUS_E_INTEGRITYVIOLATION; bFailed = true; } else { __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { pT->Fire_OnFieldChange(pT, hNotifyRow, 1, &iBind, DBREASON_COLUMN_SET, DBEVENTPHASE_DIDEVENT, TRUE); } } bSucceeded = true; dbStat = DBSTATUS_S_OK; if (pBindCur->dwPart & DBPART_VALUE) *pDstTemp = NULL; } continue; break; case DBSTATUS_S_DEFAULT: case DBSTATUS_S_IGNORE: { HRESULT hrStatus = pT->SetDBStatus(&dbStat, pRow, pColCur); *((DBSTATUS*)((BYTE*)(pSrcData) + pBindCur->obStatus)) = dbStat; if (FAILED(hrStatus)) { __if_exists(T::Fire_OnFieldChange) { if (/* pRow->m_status != DBPENDINGSTATUS_NEW && */ pRow->m_status != (DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED)) { pT->Fire_OnFieldChange(pT, hNotifyRow, pBinding->cBindings, rgColumns.GetData(), DBREASON_COLUMN_SET, DBEVENTPHASE_FAILEDTODO, TRUE); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -