📄 atldbcli.h
字号:
{
pBinding->dwPart |= DBPART_STATUS;
pBinding->obStatus = nStatusOffset;
}
}
// Free memory if appropriate
static inline void FreeType(DBTYPE wType, BYTE* pValue, IRowset* pRowset = NULL)
{
switch (wType)
{
case DBTYPE_BSTR:
SysFreeString(*((BSTR*)pValue));
break;
case DBTYPE_VARIANT:
VariantClear((VARIANT*)pValue);
break;
case DBTYPE_IUNKNOWN:
case DBTYPE_IDISPATCH:
(*(IUnknown**)pValue)->Release();
break;
case DBTYPE_ARRAY:
SafeArrayDestroy((SAFEARRAY*)pValue);
break;
case DBTYPE_HCHAPTER:
CComQIPtr<IChapteredRowset> spChapteredRowset = pRowset;
if (spChapteredRowset != NULL)
spChapteredRowset->ReleaseChapter(*(HCHAPTER*)pValue, NULL);
break;
}
if ((wType & DBTYPE_VECTOR) && ~(wType & DBTYPE_BYREF))
CoTaskMemFree(((DBVECTOR*)pValue)->ptr);
}
_ATL_ACCESSOR_INFO* m_pAccessorInfo;
ULONG m_nAccessors;
BYTE* m_pBuffer;
};
///////////////////////////////////////////////////////////////////////////
// class CRowset
class CRowset
{
// Constructors and Destructors
public:
CRowset()
{
m_pAccessor = NULL;
m_hRow = NULL;
}
CRowset(IRowset* pRowset)
{
m_spRowset = pRowset;
CRowset();
}
~CRowset()
{
Close();
}
// Release any retrieved row handles and then release the rowset
void Close()
{
if (m_spRowset != NULL)
{
ReleaseRows();
m_spRowset.Release();
m_spRowsetChange.Release();
}
}
// Addref the current row
HRESULT AddRefRows()
{
ATLASSERT(m_spRowset != NULL);
return m_spRowset->AddRefRows(1, &m_hRow, NULL, NULL);
}
// Release the current row
HRESULT ReleaseRows()
{
ATLASSERT(m_spRowset != NULL);
HRESULT hr = S_OK;
if (m_hRow != NULL)
{
hr = m_spRowset->ReleaseRows(1, &m_hRow, NULL, NULL, NULL);
m_hRow = NULL;
}
return hr;
}
// Compare two bookmarks with each other
HRESULT Compare(const CBookmarkBase& bookmark1, const CBookmarkBase& bookmark2,
DBCOMPARE* pComparison) const
{
ATLASSERT(m_spRowset != NULL);
CComPtr<IRowsetLocate> spLocate;
HRESULT hr = m_spRowset.QueryInterface(&spLocate);
if (FAILED(hr))
return hr;
return spLocate->Compare(NULL, bookmark1.GetSize(), bookmark1.GetBuffer(),
bookmark2.GetSize(), bookmark2.GetBuffer(), pComparison);
}
// Compare the passed hRow with the current row
HRESULT IsSameRow(HROW hRow) const
{
ATLASSERT(m_spRowset != NULL);
CComPtr<IRowsetIdentity> spRowsetIdentity;
HRESULT hr = m_spRowset.QueryInterface(&spRowsetIdentity);
if (FAILED(hr))
return hr;
return spRowsetIdentity->IsSameRow(m_hRow, hRow);
}
// Move to the previous record
HRESULT MovePrev()
{
return MoveNext(-2, true);
}
// Move to the next record
HRESULT MoveNext()
{
return MoveNext(0, true);
}
// Move lSkip records forward or backward
HRESULT MoveNext(LONG lSkip, bool bForward)
{
HRESULT hr;
ULONG ulRowsFetched = 0;
// Check the data was opened successfully and the accessor
// has been set.
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
// Release a row if one is already around
ReleaseRows();
// Get the row handle
HROW* phRow = &m_hRow;
hr = m_spRowset->GetNextRows(NULL, lSkip, (bForward) ? 1 : -1, &ulRowsFetched, &phRow);
if (hr != S_OK)
return hr;
// Get the data
hr = GetData();
if (FAILED(hr))
{
ATLTRACE2(atlTraceDBClient, 0, _T("GetData failed - HRESULT = 0x%X\n"),hr);
ReleaseRows();
}
return hr;
}
// Move to the first record
HRESULT MoveFirst()
{
HRESULT hr;
// Check the data was opened successfully and the accessor
// has been set.
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
// Release a row if one is already around
ReleaseRows();
hr = m_spRowset->RestartPosition(NULL);
if (FAILED(hr))
return hr;
// Get the data
return MoveNext();
}
// Move to the last record
HRESULT MoveLast()
{
// Check the data was opened successfully and the accessor
// has been set.
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
// Release a row if one is already around
ReleaseRows();
HRESULT hr;
ULONG ulRowsFetched = 0;
HROW* phRow = &m_hRow;
// Restart the rowset position and then move backwards
m_spRowset->RestartPosition(NULL);
hr = m_spRowset->GetNextRows(NULL, -1, 1, &ulRowsFetched, &phRow);
if (hr != S_OK)
return hr;
// Get the data
hr = GetData();
if (FAILED(hr))
{
ATLTRACE2(atlTraceDBClient, 0, _T("GetData from MoveLast failed - HRESULT = 0x%X\n"),hr);
ReleaseRows();
}
return S_OK;
}
// Move to the passed bookmark
HRESULT MoveToBookmark(const CBookmarkBase& bookmark, LONG lSkip = 0)
{
// Check the data was opened successfully and the accessor
// has been set.
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
CComPtr<IRowsetLocate> spLocate;
HRESULT hr = m_spRowset.QueryInterface(&spLocate);
if (FAILED(hr))
return hr;
// Release a row if one is already around
ReleaseRows();
ULONG ulRowsFetched = 0;
HROW* phRow = &m_hRow;
hr = spLocate->GetRowsAt(NULL, NULL, bookmark.GetSize(), bookmark.GetBuffer(),
lSkip, 1, &ulRowsFetched, &phRow);
// Note we're not using SUCCEEDED here, because we could get DB_S_ENDOFROWSET
if (hr != S_OK)
return hr;
// Get the data
hr = GetData();
if (FAILED(hr))
{
ATLTRACE2(atlTraceDBClient, 0, _T("GetData from Bookmark failed - HRESULT = 0x%X\n"),hr);
ReleaseRows();
}
return S_OK;
}
// Get the data for the current record
HRESULT GetData()
{
HRESULT hr = S_OK;
ATLASSERT(m_pAccessor != NULL);
ULONG nAccessors = m_pAccessor->GetNumAccessors();
for (ULONG i=0; i<nAccessors; i++)
{
if (m_pAccessor->IsAutoAccessor(i))
{
hr = GetData(i);
if (FAILED(hr))
return hr;
}
}
return hr;
}
// Get the data for the passed accessor. Use for a non-auto accessor
HRESULT GetData(int nAccessor)
{
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
ATLASSERT(m_hRow != NULL);
// Note that we are using the specified buffer if it has been set,
// otherwise we use the accessor for the data.
return m_spRowset->GetData(m_hRow, m_pAccessor->GetHAccessor(nAccessor), m_pAccessor->GetBuffer());
}
// Get the data for the passed accessor. Use for a non-auto accessor
HRESULT GetDataHere(int nAccessor, void* pBuffer)
{
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
ATLASSERT(m_hRow != NULL);
// Note that we are using the specified buffer if it has been set,
// otherwise we use the accessor for the data.
return m_spRowset->GetData(m_hRow, m_pAccessor->GetHAccessor(nAccessor), pBuffer);
}
HRESULT GetDataHere(void* pBuffer)
{
HRESULT hr = S_OK;
ULONG nAccessors = m_pAccessor->GetNumAccessors();
for (ULONG i=0; i<nAccessors; i++)
{
hr = GetDataHere(i, pBuffer);
if (FAILED(hr))
return hr;
}
return hr;
}
// Insert the current record
HRESULT Insert(int nAccessor = 0, bool bGetHRow = false)
{
ATLASSERT(m_pAccessor != NULL);
HRESULT hr;
if (m_spRowsetChange != NULL)
{
HROW* pHRow;
if (bGetHRow)
{
ReleaseRows();
pHRow = &m_hRow;
}
else
pHRow = NULL;
hr = m_spRowsetChange->InsertRow(NULL, m_pAccessor->GetHAccessor(nAccessor),
m_pAccessor->GetBuffer(), pHRow);
}
else
hr = E_NOINTERFACE;
return hr;
}
// Delete the current record
HRESULT Delete() const
{
ATLASSERT(m_pAccessor != NULL);
HRESULT hr;
if (m_spRowsetChange != NULL)
hr = m_spRowsetChange->DeleteRows(NULL, 1, &m_hRow, NULL);
else
hr = E_NOINTERFACE;
return hr;
}
// Update the current record
HRESULT SetData() const
{
ATLASSERT(m_pAccessor != NULL);
HRESULT hr = S_OK;
ULONG nAccessors = m_pAccessor->GetNumAccessors();
for (ULONG i=0; i<nAccessors; i++)
{
hr = SetData(i);
if (FAILED(hr))
return hr;
}
return hr;
}
// Update the current record with the data in the passed accessor
HRESULT SetData(int nAccessor) const
{
ATLASSERT(m_pAccessor != NULL);
HRESULT hr;
if (m_spRowsetChange != NULL)
{
hr = m_spRowsetChange->SetData(m_hRow, m_pAccessor->GetHAccessor(nAccessor),
m_pAccessor->GetBuffer());
}
else
hr = E_NOINTERFACE;
return hr;
}
// Get the data most recently fetched from or transmitted to the data source.
// Does not get values based on pending changes.
HRESULT GetOriginalData()
{
ATLASSERT(m_spRowset != NULL);
ATLASSERT(m_pAccessor != NULL);
HRESULT hr = S_OK;
CComPtr<IRowsetUpdate> spRowsetUpdate;
hr = m_spRowset->QueryInterface(&spRowsetUpdate);
if (FAILED(hr))
return hr;
ULONG nAccessors = m_pAccessor->GetNumAccessors();
for (ULONG i = 0; i < nAccessors; i++)
{
hr = spRowsetUpdate->GetOriginalData(m_hRow, m_pAccessor->GetHAccessor(i), m_pAccessor->GetBuffer());
if (FAILED(hr))
return hr;
}
return hr;
}
// Get the status of the current row
HRESULT GetRowStatus(DBPENDINGSTATUS* pStatus) const
{
ATLASSERT(m_spRowset != NULL);
ATLASSERT(pStatus != NULL);
CComPtr<IRowsetUpdate> spRowsetUpdate;
HRESULT hr = m_spRowset->QueryInterface(&spRowsetUpdate);
if (FAILED(hr))
return hr;
return spRowsetUpdate->GetRowStatus(NULL, 1, &m_hRow, pStatus);
}
// Undo any changes made to the current row since it was last fetched or Update
// was called for it
HRESULT Undo(ULONG* pcRows = NULL, HROW* phRow = NULL, DBROWSTATUS* pStatus = NULL)
{
ATLASSERT(m_spRowset != NULL);
CComPtr<IRowsetUpdate> spRowsetUpdate;
HRESULT hr = m_spRowset->QueryInterface(&spRowsetUpdate);
if (FAILED(hr))
return hr;
HROW* prgRows;
DBROWSTATUS* pRowStatus;
if (phRow != NULL)
hr = spRowsetUpdate->Undo(NULL, 1, &m_hRow, pcRows, &prgRows, &pRowStatus);
else
hr = spRowsetUpdate->Undo(NULL, 1, &m_hRow, pcRows, NULL, &pRowStatus);
if (FAILED(hr))
return hr;
if (phRow != NULL)
{
*phRow = *prgRows;
CoTaskMemFree(prgRows);
}
if (pStatus != NULL)
*pStatus = *pRowStatus;
CoTaskMemFree(pRowStatus);
return hr;
}
// Transmits any pending changes made to a row since it was last fetched or Update was
// called for it. Also see SetData.
HRESULT Update(ULONG* pcRows = NULL, HROW* phRow = NULL, DBROWSTATUS* pStatus = NULL)
{
ATLASSERT(m_spRowset != NULL);
CComPtr<IRowsetUpdate> spRowsetUpdate;
HRESULT hr = m_spRowset->QueryInterface(&spRowsetUpdate);
if (FAILED(hr))
return hr;
HROW* prgRows;
DBROWSTATUS* pRowStatus;
if (phRow != NULL)
hr = spRowsetUpdate->Update(NULL, 1, &m_hRow, pcRows, &prgRows, &pRowStatus);
else
hr = spRowsetUpdate->Update(NULL, 1, &m_hRow, pcRows, NULL, &pRowStatus);
if (FAILED(hr))
return hr;
if (phRow != NULL)
{
*phRow = *prgRows;
CoTaskMemFree(prgRows);
}
if (pStatus != NULL)
*pStatus = *pRowStatus;
CoTaskMemFree(pRowStatus);
return hr;
}
// Get the approximate position of the row corresponding to the passed bookmark
HRESULT GetApproximatePosition(const CBookmarkBase* pBookmark, ULONG* pPosition, ULONG* pcRows)
{
ATLASSERT(m_spRowset != NULL);
CComPtr<IRowsetScroll> spRowsetScroll;
HRESULT hr = m_spRowset->QueryInterface(&spRowsetScroll);
if (SUCCEEDED(hr))
{
if (pBookmark != NULL)
hr = spRowsetScroll->GetApproximatePosition(NULL, pBookmark->GetSize(), pBookmark->GetBuffer(),
pPosition, pcRows);
else
hr = spRowsetScroll->GetApproximatePosition(NULL, 0, NULL, pPosition, pcRows);
}
return hr;
}
// Move to a fractional position in the rowset
HRESULT MoveToRatio(ULONG nNumerator, ULONG nDenominator, bool bForward = true)
{
ATLASSERT(m_spRowset != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -