You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1300 lines
31 KiB
C++

// XTPReportDataManager.cpp : implementation of the CXTPReportDataManager class.
//
// This file is a part of the XTREME REPORTCONTROL MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPCustomHeap.h"
#include "Common/XTPSystemHelpers.h"
#include "Common/XTPSmartPtrInternalT.h"
#include "XTPReportDefines.h"
#include "XTPReportADO.h"
#include "XTPReportDataManager.h"
#include "XTPReportControl.h"
#include "XTPReportRecordItem.h"
#include "ItemTypes/XTPReportRecordItemVariant.h"
#include "XTPReportRecord.h"
#include "XTPReportRecords.h"
#include "XTPReportColumn.h"
#include "XTPReportColumns.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////////////////////////////////////////////////
// CRstEvent
CRstEvent::CRstEvent(CXTPReportDataManager* pDataManager)
{
m_cRef = 0;
m_pDataManager = pDataManager;
}
CRstEvent::~CRstEvent()
{
ASSERT(m_adReasonStack.GetSize() == 0);
}
HRESULT __stdcall CRstEvent::QueryInterface(REFIID riid, void ** ppv)
{
*ppv = NULL;
if (riid == __uuidof(IUnknown) || riid == __uuidof(XTPREPORTADODB::RecordsetEventsVt))
*ppv = this;
if (*ppv == NULL)
return ResultFromScode(E_NOINTERFACE);
AddRef();
return NOERROR;
}
ULONG __stdcall CRstEvent::AddRef()
{
return ++m_cRef;
}
ULONG __stdcall CRstEvent::Release()
{
if (--m_cRef != 0)
return m_cRef;
delete this;
return 0;
}
HRESULT __stdcall CRstEvent::raw_WillChangeField(
long ,//cFields,
VARIANT ,//Fields,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_FieldChangeComplete(
long ,//cFields,
VARIANT ,//Fields,
struct XTPREPORTADODB::Error* ,//pError,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* //pRecordset
)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_WillChangeRecord(
enum XTPREPORTADODB::EventReasonEnum adReason,
long ,//cRecords,
enum XTPREPORTADODB::EventStatusEnum* ,//adStatus,
struct XTPREPORTADODB::_Recordset* pRecordset)
{
if (m_pDataManager->m_bLocalUpdate)
return S_OK;
switch (adReason)
{
case XTPREPORTADODB::adRsnUpdate :
case XTPREPORTADODB::adRsnResynch :
break;
case XTPREPORTADODB::adRsnDelete :
m_adReasonStack.Add(adReason);
m_pDataManager->PrepareDeleteReportRecords(pRecordset);
break;
default :
m_adReasonStack.Add(adReason);
break;
}
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_RecordChangeComplete(
enum XTPREPORTADODB::EventReasonEnum adReason,
long ,//cRecords,
struct XTPREPORTADODB::Error* /*pError*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* pRecordset)
{
if (*adStatus == XTPREPORTADODB::adStatusErrorsOccurred)
{
/* if (pError != NULL)
{
BSTR bstrDesc;
pError->get_Description(&bstrDesc);
CString strErr(bstrDesc);
::SysFreeString(bstrDesc);
AfxMessageBox(strErr);
}*/
if (m_adReasonStack.GetSize() > 0)
m_adReasonStack.RemoveAt(m_adReasonStack.GetSize() - 1);
return S_OK;
}
if (m_pDataManager->m_bLocalUpdate)
return S_OK;
if (adReason == XTPREPORTADODB::adRsnUpdate)
{
int adPushedReason = 0;
if (m_adReasonStack.GetSize() > 0)
{
adPushedReason = m_adReasonStack.GetAt(m_adReasonStack.GetSize() - 1);
m_adReasonStack.RemoveAt(m_adReasonStack.GetSize() - 1);
}
switch (adPushedReason)
{
// case 0 :
case XTPREPORTADODB::adRsnUpdate :
m_pDataManager->UpdateReportRecords(pRecordset);
break;
case XTPREPORTADODB::adRsnAddNew :
m_pDataManager->AddReportRecords(pRecordset, TRUE);
break;
case XTPREPORTADODB::adRsnDelete :
m_pDataManager->DeleteReportRecords();
break;
case XTPREPORTADODB::adRsnUndoDelete :
// m_pDataManager->AddReportRecords(pRecordset, TRUE);
m_pDataManager->ClearDeleteReportRecords();
break;
}
}
else if (adReason == XTPREPORTADODB::adRsnResynch)
{
m_pDataManager->UpdateReportRecords(pRecordset);
}
else
{
// if (!m_adReasonStack.empty())
// m_adReasonStack.pop();
}
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_WillChangeRecordset(
enum XTPREPORTADODB::EventReasonEnum ,//adReason,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* //pRecordset
)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_RecordsetChangeComplete(
enum XTPREPORTADODB::EventReasonEnum adReason,
struct XTPREPORTADODB::Error* /*pError*/,
enum XTPREPORTADODB::EventStatusEnum* /*adStatus*/,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
switch (adReason)
{
case XTPREPORTADODB::adRsnClose :
m_pDataManager->ClearReportControl();
break;
// case XTPREPORTADODB::adRsnOpen :
// m_pDataManager->AddReportRecords(pRecordset);
// break;
}
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_WillMove(
enum XTPREPORTADODB::EventReasonEnum /*adReason*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_MoveComplete(
enum XTPREPORTADODB::EventReasonEnum /*adReason*/,
struct XTPREPORTADODB::Error* /*pError*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_EndOfRecordset(
VARIANT_BOOL* /*fMoreData*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_FetchProgress(
long /*Progress*/,
long /*MaxProgress*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
HRESULT __stdcall CRstEvent::raw_FetchComplete(
struct XTPREPORTADODB::Error* /*pError*/,
enum XTPREPORTADODB::EventStatusEnum* adStatus,
struct XTPREPORTADODB::_Recordset* /*pRecordset*/)
{
*adStatus = XTPREPORTADODB::adStatusUnwantedEvent;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////
// CXTPReportDataManager
CXTPReportDataManager::CXTPReportDataManager(CXTPReportControl* pReportControl):
m_pReportControl(pReportControl),
m_pConnection(NULL),
m_pDataSource(NULL),
m_pRstEvent(NULL),
m_dwRstEvent(0),
m_pDeleteRecords(NULL),
m_bLocalUpdate(FALSE)
{
}
CXTPReportDataManager::~CXTPReportDataManager()
{
for (int i = 0; i < m_LastComError.GetSize(); i++)
{
XTP_REPORTDATAMANAGER_COM_ERROR* pError = m_LastComError.GetAt(i);
if (pError)
delete pError;
}
m_LastComError.RemoveAll();
if (m_pDeleteRecords)
{
m_pDeleteRecords->RemoveAll();
delete m_pDeleteRecords;
}
RemoveDataSource();
}
void AFX_CDECL CXTPReportDataManager::TRACE_ComError(_com_error &e)
{
LPCWSTR bstrSource(e.Source());
// Print COM errors.
TRACE(_T("COM_ERROR: HRESULT = %08lx, Code meaning = %s, Source = %ls\n"),
e.Error(), (LPCTSTR)e.ErrorMessage(), (LPCWSTR)bstrSource);
// Save last COM error.
XTP_REPORTDATAMANAGER_COM_ERROR* pError = NULL;
if (m_LastComError.GetSize() >= XTP_REPORTDATAMANAGER_MAX_LAST_COM_ERRORS)
{
pError = m_LastComError.GetAt(m_LastComError.GetSize() - 1);
m_LastComError.RemoveAt(m_LastComError.GetSize() - 1);
}
if (!pError)
pError = new XTP_REPORTDATAMANAGER_COM_ERROR;
if (!pError)
return;
pError->hResult = e.Error();
pError->strMessage = e.ErrorMessage();
pError->strSource.Format(_T("%ls"), (LPCWSTR)bstrSource);
m_LastComError.Add(pError);
}
void AFX_CDECL CXTPReportDataManager::TRACE_ProviderError(XTPREPORTADODB::_Connection* pConnDB)
{
// Print Provider Errors from Connection object.
ASSERT(pConnDB);
if (!pConnDB)
return;
if (pConnDB->Errors->Count > 0)
{
long nCount = pConnDB->Errors->Count;
TRACE(_T("DB ERROR(s): "));
for (long i = 0; i < nCount; i++)
{
XTPREPORTADODB::ErrorPtr ptrErr = pConnDB->Errors->GetItem(i);
TRACE(_T(" (Error- %x, '%ls'); "), ptrErr->Number, (LPCWSTR)ptrErr->Description);
}
TRACE(_T(" \n"));
}
}
void CXTPReportDataManager::RemoveDataSource()
{
try
{
// unadvise events
if (m_pRstEvent)
{
IConnectionPointContainer *pCPC = NULL;
IConnectionPoint *pCP = NULL;
HRESULT hr = m_pDataSource->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
if (SUCCEEDED(hr))
{
hr = pCPC->FindConnectionPoint(__uuidof(XTPREPORTADODB::RecordsetEvents), &pCP);
pCPC->Release();
if (SUCCEEDED(hr))
{
hr = pCP->Unadvise(m_dwRstEvent);
pCP->Release();
}
}
//delete m_pRstEvent;
m_pRstEvent->Release();
m_pRstEvent = NULL;
}
// set data source pointer to NULL
m_pDataSource = NULL;
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
}
catch(...)
{
TRACE(_T("Unknown error in RemoveDataSource()\n"));
}
}
void CXTPReportDataManager::ClearReportControl()
{
m_pReportControl->GetColumns()->Clear();
m_pReportControl->ResetContent();
}
void CXTPReportDataManager::SetDataSource(XTPREPORTADODB::_RecordsetPtr pDataSource)
{
// remove data source first
if (m_pDataSource)
RemoveDataSource();
// set new data source
if (pDataSource)
m_pDataSource = pDataSource;
}
BOOL CXTPReportDataManager::DataBind()
{
HRESULT hr = E_FAIL;
try
{
if (m_pDataSource == NULL)
return FALSE;
m_pConnection = NULL;
// get connection
_variant_t vtConnection;
if (SUCCEEDED(hr = m_pDataSource->get_ActiveConnection(&vtConnection)) && vtConnection.pdispVal)
{
m_pConnection = vtConnection;
}
// clear report control
ClearReportControl();
// create columns
if (FAILED(hr = CreateColumns()))
return FALSE;
// create records
if (FAILED(hr = AddReportRecords(m_pDataSource, FALSE)))
return FALSE;
m_pReportControl->Populate();
// advise events
m_pRstEvent = new CRstEvent(this);
if (!m_pRstEvent)
return FALSE;
IUnknown *pUnk = NULL;
hr = m_pRstEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
if (FAILED(hr))
return FALSE;
IConnectionPointContainer *pCPC = NULL;
IConnectionPoint *pCP = NULL;
hr = m_pDataSource->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC);
if (FAILED(hr))
return FALSE;
hr = pCPC->FindConnectionPoint(__uuidof(XTPREPORTADODB::RecordsetEvents), &pCP);
pCPC->Release();
if (FAILED(hr))
return FALSE;
hr = pCP->Advise(pUnk, &m_dwRstEvent);
pCP->Release();
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in DataBind()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? FALSE : TRUE;
}
HRESULT CXTPReportDataManager::CreateColumns()
{
HRESULT hr = E_FAIL;
try
{
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = m_pDataSource->get_Fields(&pFields)) || pFields == NULL)
return hr;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
return hr;
VARIANT vtIdx;
vtIdx.vt = VT_I4;
for (int i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
/* XTPREPORTADODB::DataTypeEnum dteType;
if (FAILED(hr = pField->get_Type(&dteType)))
break;
if (dteType == XTPREPORTADODB::adLongVarBinary)
continue;*/
BSTR bstrName;
pField->get_Name(&bstrName);
CString strName(bstrName);
::SysFreeString(bstrName);
CXTPReportColumn* pColumn = new CXTPReportColumn(i, strName, 100);
if (!pColumn)
break;
long lAttrs;
if (SUCCEEDED(hr = pField->get_Attributes(&lAttrs)) && (lAttrs & XTPREPORTADODB::adFldUpdatable))
pColumn->SetEditable(TRUE);
m_pReportControl->AddColumn(pColumn);
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in CreateColumns()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
HRESULT CXTPReportDataManager::UpdateReportRecords(XTPREPORTADODB::_RecordsetPtr pRecordset)
{
HRESULT hr = E_FAIL;
try
{
CXTPReportRecords* pRecords = m_pReportControl->GetRecords();
if (!(pRecordset != NULL && pRecords))
return E_FAIL;
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = pRecordset->get_Fields(&pFields)) || pFields == NULL)
return hr;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
return hr;
long lRecords;
if (FAILED(hr = pRecordset->get_RecordCount(&lRecords)))
return hr;
if (lRecords <= 0)
return E_FAIL;
pRecordset->MoveFirst();
VARIANT_BOOL vtRecordsEof;
pRecordset->get_bEOF(&vtRecordsEof);
while (!vtRecordsEof)
{
// get record bookmark
VARIANT vtBookmark;
if (FAILED(hr = pRecordset->get_Bookmark(&vtBookmark)))
break;
CXTPReportRecord* pRecord = pRecords->FindRecordByBookmark(vtBookmark, TRUE);
if (pRecord)
{
// get field values
VARIANT vtIdx;
vtIdx.vt = VT_I4;
for (int i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
VARIANT vtValue;
if (FAILED(hr = pField->get_Value(&vtValue)))
break;
CXTPReportRecordItemVariant* pItem = (CXTPReportRecordItemVariant*)pRecord->GetItem(i);
if (!pItem)
break;
pItem->SetValue(COleVariant(vtValue));
}
m_pReportControl->UpdateRecord(pRecord, TRUE);
}
pRecordset->MoveNext();
pRecordset->get_bEOF(&vtRecordsEof);
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in UpdateReportRecords()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
HRESULT CXTPReportDataManager::AddReportRecords(XTPREPORTADODB::_RecordsetPtr pRecordset, BOOL bAddNow)
{
HRESULT hr = E_FAIL;
try
{
if (pRecordset == NULL)
return E_FAIL;
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = pRecordset->get_Fields(&pFields)) || pFields == NULL)
return hr;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
return hr;
long lRecords;
if (FAILED(hr = pRecordset->get_RecordCount(&lRecords)))
return hr;
if (lRecords <= 0)
return E_FAIL;
pRecordset->MoveFirst();
VARIANT_BOOL vtRecordsEof;
pRecordset->get_bEOF(&vtRecordsEof);
while (!vtRecordsEof)
{
// create record
CXTPReportRecord* pRecord = new CXTPReportRecord;
if (!pRecord)
break;
// get field values
VARIANT vtIdx;
vtIdx.vt = VT_I4;
for (int i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
VARIANT vtValue;
if (FAILED(hr = pField->get_Value(&vtValue)))
break;
CXTPReportRecordItemVariant* pItem = new CXTPReportRecordItemVariant(vtValue);
if (!pItem)
break;
pRecord->AddItem(pItem);
}
// bind report record to data source record by bookmark
VARIANT vtBookmark;
if (FAILED(hr = pRecordset->get_Bookmark(&vtBookmark)))
break;
pRecord->SetBookmark(vtBookmark);
// add record to report records collection
if (bAddNow)
m_pReportControl->AddRecordEx(pRecord);
else
m_pReportControl->AddRecord(pRecord);
if (FAILED(hr))
break;
pRecordset->MoveNext();
pRecordset->get_bEOF(&vtRecordsEof);
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in AddReportRecords()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
HRESULT CXTPReportDataManager::PrepareDeleteReportRecords(XTPREPORTADODB::_RecordsetPtr pRecordset)
{
HRESULT hr = E_FAIL;
try
{
if (m_pDeleteRecords)
m_pDeleteRecords->RemoveAll();
else
m_pDeleteRecords = new CXTPReportRecords(TRUE);
if (!m_pDeleteRecords)
return E_FAIL;
CXTPReportRecords* pRecords = m_pReportControl->GetRecords();
if (!(pRecordset != NULL && pRecords))
return E_FAIL;
long lRecords;
if (FAILED(hr = pRecordset->get_RecordCount(&lRecords)))
return hr;
if (lRecords <= 0)
return E_FAIL;
pRecordset->MoveFirst();
VARIANT_BOOL vtRecordsEof;
pRecordset->get_bEOF(&vtRecordsEof);
while (!vtRecordsEof)
{
// get record bookmark
VARIANT vtBookmark;
if (FAILED(hr = pRecordset->get_Bookmark(&vtBookmark)))
break;
CXTPReportRecord* pRecord = pRecords->FindRecordByBookmark(vtBookmark, TRUE);
if (pRecord)
m_pDeleteRecords->Add(pRecord);
pRecordset->MoveNext();
pRecordset->get_bEOF(&vtRecordsEof);
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in PrepareDeleteReportRecords()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
void CXTPReportDataManager::ClearDeleteReportRecords()
{
if (m_pDeleteRecords)
m_pDeleteRecords->RemoveAll();
}
HRESULT CXTPReportDataManager::DeleteReportRecords()
{
if (!m_pDeleteRecords)
return E_FAIL;
for (int i = 0; i < m_pDeleteRecords->GetCount(); i++)
{
m_pReportControl->RemoveRecordEx(m_pDeleteRecords->GetAt(i));
}
m_pDeleteRecords->RemoveAll();
return S_OK;
}
HRESULT CXTPReportDataManager::DeleteReportRecords(XTPREPORTADODB::_RecordsetPtr pRecordset)
{
HRESULT hr = E_FAIL;
try
{
CXTPReportRecords* pRecords = m_pReportControl->GetRecords();
if (!(pRecordset != NULL && pRecords))
return E_FAIL;
long lRecords;
if (FAILED(hr = pRecordset->get_RecordCount(&lRecords)))
return hr;
if (lRecords <= 0)
return E_FAIL;
pRecordset->MoveFirst();
VARIANT_BOOL vtRecordsEof;
pRecordset->get_bEOF(&vtRecordsEof);
while (!vtRecordsEof)
{
// get record bookmark
VARIANT vtBookmark;
if (FAILED(hr = pRecordset->get_Bookmark(&vtBookmark)))
break;
CXTPReportRecord* pRecord = pRecords->FindRecordByBookmark(vtBookmark, TRUE);
if (pRecord)
m_pReportControl->RemoveRecordEx(pRecord);
pRecordset->MoveNext();
pRecordset->get_bEOF(&vtRecordsEof);
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in DeleteReportRecords()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
HRESULT CXTPReportDataManager::UpdateField(CXTPReportRecordItemVariant* pItem)
{
BOOL bOk = FALSE;
HRESULT hr = E_FAIL;
m_bLocalUpdate = TRUE;
try
{
while (TRUE)
{
if (!pItem)
break;
CXTPReportRecord* pRecord = pItem->GetRecord();
if (!pRecord)
break;
// get data source record bookmark
VARIANT vtBookmark = pRecord->GetBookmark();
if (vtBookmark.vt == VT_EMPTY)
break;
// move to specified record
if (FAILED(hr = m_pDataSource->put_Bookmark(vtBookmark)))
break;
// update item
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = m_pDataSource->get_Fields(&pFields)) || pFields == NULL)
break;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0 || pItem->GetIndex() >= lFields)
break;
VARIANT vtIdx;
vtIdx.vt = VT_I4;
vtIdx.lVal = pItem->GetIndex();
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
long lAttrs;
if (FAILED(hr = pField->get_Attributes(&lAttrs)))
break;
if (!(lAttrs & (XTPREPORTADODB::adFldUpdatable | XTPREPORTADODB::adFldUnknownUpdatable)))
break;
XTPREPORTADODB::DataTypeEnum dteType;
if (FAILED(hr = pField->get_Type(&dteType)))
break;
if (dteType == XTPREPORTADODB::adLongVarBinary)
break;
VARIANT vtValue = pItem->GetValue();
if (FAILED(hr = pField->put_Value(vtValue)))
break;
if (FAILED(hr = m_pDataSource->Update()))
{
m_pDataSource->CancelUpdate();
break;
}
bOk = TRUE;
break;
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in UpdateField()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
m_bLocalUpdate = FALSE;
return FAILED(hr) ? hr : bOk ? S_OK : E_FAIL;
}
HRESULT CXTPReportDataManager::UpdateRecord(CXTPReportRecord* pRecord, CXTPReportRecordItem* pItemChanged /* = NULL */)
{
BOOL bOk = FALSE;
HRESULT hr = E_FAIL;
m_bLocalUpdate = TRUE;
try
{
while (TRUE)
{
if (!pRecord)
break;
// get data source record bookmark
VARIANT vtBookmark = pRecord->GetBookmark();
if (vtBookmark.vt == VT_EMPTY)
break;
// move to specified record
if (FAILED(hr = m_pDataSource->put_Bookmark(vtBookmark)))
break;
// update record
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = m_pDataSource->get_Fields(&pFields)) || pFields == NULL)
break;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
break;
VARIANT vtIdx;
vtIdx.vt = VT_I4;
int i;
for (i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
long lAttrs;
if (FAILED(hr = pField->get_Attributes(&lAttrs)))
break;
if (!(lAttrs & (XTPREPORTADODB::adFldUpdatable | XTPREPORTADODB::adFldUnknownUpdatable)))
continue;
XTPREPORTADODB::DataTypeEnum dteType;
if (FAILED(hr = pField->get_Type(&dteType)))
break;
if (dteType == XTPREPORTADODB::adLongVarBinary)
continue;
CXTPReportRecordItemVariant* pItem = (CXTPReportRecordItemVariant*)pRecord->GetItem(i);
if (!pItem)
break;
if (pItemChanged != NULL && pItemChanged != pItem)
continue;
VARIANT vtValue = pItem->GetValue();
if (FAILED(hr = pField->put_Value(vtValue)))
continue;//break;
}
if (FAILED(hr) || i < lFields)
{
m_pDataSource->CancelUpdate();
break;
}
if (FAILED(hr = m_pDataSource->Update()))
{
m_pDataSource->CancelUpdate();
return hr;
}
bOk = TRUE;
break;
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
m_pDataSource->CancelUpdate();
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in UpdateRecord()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
m_bLocalUpdate = FALSE;
return FAILED(hr) ? hr : bOk ? S_OK : E_FAIL;
}
HRESULT CXTPReportDataManager::AddRecord(CXTPReportRecord* pRecord, BOOL bAddToReport)
{
BOOL bOk = FALSE;
HRESULT hr = E_FAIL;
m_bLocalUpdate = TRUE;
try
{
while (TRUE)
{
if (!pRecord)
break;
// add record without field list
if (FAILED(hr = m_pDataSource->raw_AddNew()))
break;
// update fields
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = m_pDataSource->get_Fields(&pFields)) || pFields == NULL)
break;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
break;
VARIANT vtIdx;
vtIdx.vt = VT_I4;
int i;
for (i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
long lAttrs;
if (FAILED(hr = pField->get_Attributes(&lAttrs)))
break;
if (!(lAttrs & (XTPREPORTADODB::adFldUpdatable | XTPREPORTADODB::adFldUnknownUpdatable)))
continue;
CXTPReportRecordItemVariant* pItem = (CXTPReportRecordItemVariant*)pRecord->GetItem(i);
if (!pItem)
break;
VARIANT vtValue = pItem->GetValue();
//if (FAILED(hr = pField->put_Value(vtValue))) // DEBUG comment
// break;
pField->put_Value(vtValue);
}
if (FAILED(hr) || i < lFields)
{
m_pDataSource->CancelUpdate();
break;
}
// bind report record to data source record by bookmark
VARIANT vtBookmark;
VariantInit(&vtBookmark);
if (FAILED(hr = m_pDataSource->get_Bookmark(&vtBookmark)))
break;
pRecord->SetBookmark(vtBookmark);
// update recordset
if (FAILED(hr = m_pDataSource->Update()))
{
m_pDataSource->CancelUpdate();
pRecord->SetBookmark(COleVariant());
break;
}
// add report record if required
if (bAddToReport)
m_pReportControl->AddRecordEx(pRecord);
bOk = TRUE;
break;
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
m_pDataSource->CancelUpdate();
pRecord->SetBookmark(COleVariant());
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in AddRecord()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
m_bLocalUpdate = FALSE;
return FAILED(hr) ? hr : bOk ? S_OK : E_FAIL;
}
HRESULT CXTPReportDataManager::CreateEmptyRecord(CXTPReportRecord** ppRecord)
{
BOOL bOk = FALSE;
HRESULT hr = E_FAIL;
CXTPReportRecord* pRecord = NULL;
try
{
while (TRUE)
{
if (m_pDataSource == NULL || !ppRecord)
break;
// create empty record
pRecord = new CXTPReportRecord;
if (!pRecord)
break;
XTPREPORTADODB::FieldsPtr pFields;
if (FAILED(hr = m_pDataSource->get_Fields(&pFields)) || pFields == NULL)
break;
long lFields;
if (FAILED(hr = pFields->get_Count(&lFields)) || lFields == 0)
break;
long lRecords;
if (FAILED(hr = m_pDataSource->get_RecordCount(&lRecords)))
break;
if (lRecords > 0)
{
m_pDataSource->MoveFirst();
VARIANT_BOOL vtRecordsEof;
if (FAILED(hr = m_pDataSource->get_bEOF(&vtRecordsEof)))
break;
if (vtRecordsEof)
break;
}
VARIANT vtIdx;
vtIdx.vt = VT_I4;
int i;
for (i = 0; i < lFields; i++)
{
vtIdx.lVal = i;
XTPREPORTADODB::FieldPtr pField;
if (FAILED(hr = pFields->get_Item(vtIdx, &pField)) || pField == NULL)
break;
VARIANT vtValue;
if (lRecords == 0)
{
XTPREPORTADODB::DataTypeEnum dt;
if (FAILED(hr = pField->get_Type(&dt)))
break;
if (dt == XTPREPORTADODB::adInteger || dt == XTPREPORTADODB::adTinyInt || dt == XTPREPORTADODB::adSmallInt || dt == XTPREPORTADODB::adBigInt ||
dt == XTPREPORTADODB::adUnsignedTinyInt || dt == XTPREPORTADODB::adUnsignedSmallInt || dt == XTPREPORTADODB::adUnsignedInt || dt == XTPREPORTADODB::adUnsignedBigInt)
vtValue.vt = VT_I4;
else if (dt == XTPREPORTADODB::adBoolean)
vtValue.vt = VT_BOOL;
else if (dt == XTPREPORTADODB::adDate)
vtValue.vt = VT_DATE;
else if (dt == XTPREPORTADODB::adDouble)
vtValue.vt = VT_R8;
else if (dt == XTPREPORTADODB::adSingle)
vtValue.vt = VT_R4;
else if (dt == XTPREPORTADODB::adCurrency)
vtValue.vt = VT_CY;
else
vtValue.vt = VT_BSTR;
}
else
{
if (FAILED(hr = pField->get_Value(&vtValue)))
break;
}
vtValue.lVal = 0;
CXTPReportRecordItemVariant* pItem = new CXTPReportRecordItemVariant(vtValue);
if (!pItem)
break;
pRecord->AddItem(pItem);
}
if (FAILED(hr) || i < lFields)
break;
*ppRecord = pRecord;
bOk = TRUE;
break;
}
}
catch(_com_error &e)
{
if (pRecord)
delete pRecord;
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
if (pRecord)
delete pRecord;
TRACE(_T("Unknown error in CreateEmptyRecord()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
if (!bOk && pRecord)
delete pRecord;
return FAILED(hr) ? hr : bOk ? S_OK : E_FAIL;
}
HRESULT CXTPReportDataManager::DeleteRecord(CXTPReportRecord* pRecord)
{
HRESULT hr = E_FAIL;
try
{
if (!pRecord)
return E_FAIL;
// get data source record bookmark
VARIANT vtBookmark = pRecord->GetBookmark();
if (vtBookmark.vt == VT_EMPTY)
return E_FAIL;
// move to specified record
if (FAILED(hr = m_pDataSource->put_Bookmark(vtBookmark)))
return hr;
// delete record
if (FAILED(hr = m_pDataSource->Delete(XTPREPORTADODB::adAffectCurrent)))
{
m_pDataSource->CancelUpdate();
return hr;
}
}
catch(_com_error &e)
{
TRACE_ProviderError(m_pConnection);
TRACE_ComError(e);
m_pDataSource->CancelUpdate();
hr = FAILED(hr) ? hr : E_FAIL;
}
catch(...)
{
TRACE(_T("Unknown error in CreateEmptyRecord()\n"));
hr = FAILED(hr) ? hr : E_FAIL;
}
return FAILED(hr) ? hr : S_OK;
}
XTP_REPORTDATAMANAGER_COM_ERROR CXTPReportDataManager::GetLastComError()
{
XTP_REPORTDATAMANAGER_COM_ERROR Error;
if (m_LastComError.GetSize() > 0)
{
XTP_REPORTDATAMANAGER_COM_ERROR* pError = m_LastComError.GetAt(m_LastComError.GetSize() - 1);
m_LastComError.RemoveAt(m_LastComError.GetSize() - 1);
if (pError)
{
Error = *pError;
delete pError;
}
}
return Error;
}
/////////////////////////////////////////////////////////////////////////////
// CXTPReportDataManager diagnostics
#ifdef _DEBUG
void CXTPReportDataManager::AssertValid() const
{
CXTPCmdTarget::AssertValid();
ASSERT(m_pReportControl);
}
void CXTPReportDataManager::Dump(CDumpContext& dc) const
{
// The overridden Dump usually calls the Dump
// function of its base class before printing
// data members unique to the derived class.
CXTPCmdTarget::Dump(dc);
if (m_pConnection)
{
try
{
dc << _T("Connection String: ") << (LPCTSTR)m_pConnection->GetConnectionString() << _T("\n");
dc << _T("Connection State: ");
switch (m_pConnection->GetState())
{
case XTPREPORTADODB::adStateClosed:
dc << _T("Closed");
break;
case XTPREPORTADODB::adStateOpen:
dc << _T("Open");
break;
case XTPREPORTADODB::adStateConnecting:
dc << _T("Connecting");
break;
case XTPREPORTADODB::adStateExecuting:
dc << _T("Executing");
break;
case XTPREPORTADODB::adStateFetching:
dc << _T("Fetching");
break;
default:
dc << _T("Unknown");
}
}
catch (_com_error &e)
{
UNREFERENCED_PARAMETER(e);
}
dc << _T("\n");
}
if (m_pDataSource)
{
try
{
dc << _T("Recordset State: ");
switch (m_pDataSource->GetState())
{
case XTPREPORTADODB::adStateClosed:
dc << _T("Closed");
break;
case XTPREPORTADODB::adStateOpen:
dc << _T("Open");
break;
case XTPREPORTADODB::adStateConnecting:
dc << _T("Connecting");
break;
case XTPREPORTADODB::adStateExecuting:
dc << _T("Executing");
break;
case XTPREPORTADODB::adStateFetching:
dc << _T("Fetching");
break;
default:
dc << _T("Unknown");
}
dc << _T("\n");
dc << _T("Record Count: ") << (LONG)m_pDataSource->GetRecordCount();
}
catch (_com_error &e)
{
UNREFERENCED_PARAMETER(e);
}
dc << _T("\n");
}
}
CDumpContext& AFXAPI operator<<(CDumpContext& dc, const CXTPReportDataManager& obj)
{
obj.Dump(dc);
return dc;
}
#endif //_DEBUG