📄 atldbcli.h
字号:
}
void Close()
{
if (m_pColumnInfo != NULL)
{
CoTaskMemFree(m_pColumnInfo);
m_pColumnInfo = NULL;
}
// Free the memory for the string buffer returned by IColumnsInfo::GetColumnInfo,
// if necessary
if (m_pStringsBuffer != NULL)
{
CoTaskMemFree(m_pStringsBuffer);
m_pStringsBuffer = NULL;
}
delete [] m_pBuffer;
m_pBuffer = NULL;
m_nColumns = 0;
CAccessorBase::Close();
}
bool GetColumnType(ULONG nColumn, DBTYPE* pType) const
{
if (TranslateColumnNo(nColumn))
{
*pType = m_pColumnInfo[nColumn].wType;
return true;
}
else
return false;
}
bool GetColumnFlags(ULONG nColumn, DBCOLUMNFLAGS* pFlags) const
{
if (TranslateColumnNo(nColumn))
{
*pFlags = m_pColumnInfo[nColumn].dwFlags;
return true;
}
else
return false;
}
bool GetOrdinal(TCHAR* pColumnName, ULONG* pOrdinal) const
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
*pOrdinal = m_pColumnInfo[nColumn].iOrdinal;
return true;
}
else
return false;
}
void* GetValue(ULONG nColumn) const
{
if (TranslateColumnNo(nColumn))
return _GetDataPtr(nColumn);
else
return NULL;
}
void* GetValue(TCHAR* pColumnName) const
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
return _GetDataPtr(nColumn);
else
return NULL; // Not Found
}
template <class ctype>
void _GetValue(ULONG nColumn, ctype* pData) const
{
ATLASSERT(pData != NULL);
ATLASSERT(m_pColumnInfo[nColumn].ulColumnSize == sizeof(ctype));
ctype* pBuffer = (ctype*)_GetDataPtr(nColumn);
*pData = *pBuffer;
}
template <class ctype>
void _SetValue(ULONG nColumn, const ctype& data)
{
ATLASSERT(m_pColumnInfo[nColumn].ulColumnSize == sizeof(ctype));
ctype* pBuffer = (ctype*)_GetDataPtr(nColumn);
*pBuffer = (ctype)data;
}
template <class ctype>
bool GetValue(ULONG nColumn, ctype* pData) const
{
if (TranslateColumnNo(nColumn))
{
_GetValue(nColumn, pData);
return true;
}
return false;
}
template <class ctype>
bool SetValue(ULONG nColumn, const ctype& data)
{
if (TranslateColumnNo(nColumn))
{
_SetValue(nColumn, data);
return true;
}
return false;
}
template <class ctype>
bool GetValue(TCHAR *pColumnName, ctype* pData) const
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
_GetValue(nColumn, pData);
return true;
}
return false;
}
template <class ctype>
bool SetValue(TCHAR *pColumnName, const ctype& data)
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
_SetValue(nColumn, data);
return true;
}
return false;
}
bool GetLength(ULONG nColumn, ULONG* pLength) const
{
ATLASSERT(pLength != NULL);
if (TranslateColumnNo(nColumn))
{
*pLength = *(ULONG*)(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize));
return true;
}
else
return false;
}
bool SetLength(ULONG nColumn, ULONG nLength)
{
if (TranslateColumnNo(nColumn))
{
*(ULONG*)(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize)) = nLength;
return true;
}
else
return false;
}
bool GetLength(TCHAR* pColumnName, ULONG* pLength) const
{
ATLASSERT(pColumnName != NULL);
ATLASSERT(pLength != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
*pLength = *(ULONG*)(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize));
return true;
}
else
return false;
}
bool SetLength(TCHAR* pColumnName, ULONG nLength)
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
*(ULONG*)(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize)) = nLength;
return true;
}
else
return false;
}
bool GetStatus(ULONG nColumn, DBSTATUS* pStatus) const
{
ATLASSERT(pStatus != NULL);
if (TranslateColumnNo(nColumn))
{
*pStatus = *(ULONG*)(AddOffset(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize), sizeof(ULONG)));
return true;
}
else
return false;
}
bool SetStatus(ULONG nColumn, DBSTATUS status)
{
if (TranslateColumnNo(nColumn))
{
*(ULONG*)(AddOffset(AddOffset((ULONG)_GetDataPtr(nColumn), m_pColumnInfo[nColumn].ulColumnSize), sizeof(ULONG))) = status;
return true;
}
else
return false;
}
bool GetStatus(TCHAR* pColumnName, DBSTATUS* pStatus) const
{
ATLASSERT(pColumnName != NULL);
ATLASSERT(pStatus != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
*pStatus = *(ULONG*)((BYTE*)_GetDataPtr(nColumn) + m_pColumnInfo[nColumn].ulColumnSize + sizeof(ULONG));
return true;
}
else
return false;
}
bool SetStatus(TCHAR* pColumnName, DBSTATUS status)
{
ATLASSERT(pColumnName != NULL);
ULONG nColumn;
if (GetInternalColumnNo(pColumnName, &nColumn))
{
*(ULONG*)((BYTE*)_GetDataPtr(nColumn) + m_pColumnInfo[nColumn].ulColumnSize + sizeof(ULONG)) = status;
return true;
}
else
return false;
}
// Returns true if a bookmark is available
HRESULT GetBookmark(CBookmark<>* pBookmark) const
{
HRESULT hr;
if (m_pColumnInfo->iOrdinal == 0)
hr = pBookmark->SetBookmark(m_pColumnInfo->ulColumnSize, (BYTE*)_GetDataPtr(0));
else
hr = E_FAIL;
return hr;
}
ULONG GetColumnCount() const
{
return m_nColumns;
}
LPOLESTR GetColumnName(ULONG nColumn) const
{
if (TranslateColumnNo(nColumn))
return m_pColumnInfo[nColumn].pwszName;
else
return NULL;
}
HRESULT GetColumnInfo(IRowset* pRowset, ULONG* pColumns, DBCOLUMNINFO** ppColumnInfo)
{
CComPtr<IColumnsInfo> spColumnsInfo;
HRESULT hr = pRowset->QueryInterface(&spColumnsInfo);
if (SUCCEEDED(hr))
hr = spColumnsInfo->GetColumnInfo(pColumns, ppColumnInfo, &m_pStringsBuffer);
return hr;
}
HRESULT AddBindEntry(const DBCOLUMNINFO& info)
{
m_pColumnInfo = (DBCOLUMNINFO*)CoTaskMemRealloc(m_pColumnInfo, (m_nColumns + 1) * sizeof(DBCOLUMNINFO));
if (m_pColumnInfo == NULL)
return E_OUTOFMEMORY;
m_pColumnInfo[m_nColumns] = info;
m_nColumns++;
return S_OK;
}
// Implementation
// Free's any columns in the current record that need to be freed.
// E.g. Calls SysFreeString on any BSTR's and Release on any interfaces.
void FreeRecordMemory(IRowset* pRowset)
{
ULONG i;
for (i = 0; i < m_nColumns; i++)
CAccessorBase::FreeType(m_pColumnInfo[i].wType, (BYTE*)_GetDataPtr(i), pRowset);
}
void* _GetDataPtr(ULONG nColumn) const
{
return m_pBuffer + (ULONG)m_pColumnInfo[nColumn].pTypeInfo;
}
bool GetInternalColumnNo(TCHAR* pColumnName, ULONG* pColumn) const
{
ATLASSERT(pColumnName != NULL);
ATLASSERT(pColumn != NULL);
USES_CONVERSION;
ULONG i;
ULONG nSize = (lstrlen(pColumnName) + 1) * sizeof(OLECHAR);
OLECHAR* pOleColumnName = T2OLE(pColumnName);
// Search through the columns trying to find a match
for (i = 0; i < m_nColumns; i++)
{
if (m_pColumnInfo[i].pwszName != NULL &&
memcmp(m_pColumnInfo[i].pwszName, pOleColumnName, nSize) == 0)
break;
}
if (i < m_nColumns)
{
*pColumn = i;
return true;
}
else
return false; // Not Found
}
HRESULT BindColumns(IUnknown* pUnk)
{
ATLASSERT(pUnk != NULL);
CComPtr<IAccessor> spAccessor;
HRESULT hr = pUnk->QueryInterface(&spAccessor);
if (FAILED(hr))
return hr;
ULONG i;
ULONG nOffset = 0, nLengthOffset, nStatusOffset;
// If the user hasn't specifed the column information to bind by calling AddBindEntry then
// we get it ourselves
if (m_pColumnInfo == NULL)
{
CComPtr<IColumnsInfo> spColumnsInfo;
hr = pUnk->QueryInterface(&spColumnsInfo);
if (FAILED(hr))
return hr;
hr = spColumnsInfo->GetColumnInfo(&m_nColumns, &m_pColumnInfo, &m_pStringsBuffer);
if (FAILED(hr))
return hr;
m_bOverride = false;
}
else
m_bOverride = true;
DBBINDING* pBinding = NULL;
ATLTRY(pBinding= new DBBINDING[m_nColumns]);
if (pBinding == NULL)
return E_OUTOFMEMORY;
DBBINDING* pCurrent = pBinding;
DBOBJECT* pObject;
for (i = 0; i < m_nColumns; i++)
{
// If it's a BLOB or the column size is large enough for us to treat it as
// a BLOB then we also need to set up the DBOBJECT structure.
if (m_pColumnInfo[i].ulColumnSize > 1024 || m_pColumnInfo[i].wType == DBTYPE_IUNKNOWN)
{
pObject = NULL;
ATLTRY(pObject = new DBOBJECT);
if (pObject == NULL)
return E_OUTOFMEMORY;
pObject->dwFlags = STGM_READ;
pObject->iid = IID_ISequentialStream;
m_pColumnInfo[i].wType = DBTYPE_IUNKNOWN;
m_pColumnInfo[i].ulColumnSize = sizeof(IUnknown*);
}
else
pObject = NULL;
// If column is of type STR or WSTR increase length by 1
// to accommodate the NULL terminator.
if (m_pColumnInfo[i].wType == DBTYPE_STR ||
m_pColumnInfo[i].wType == DBTYPE_WSTR)
m_pColumnInfo[i].ulColumnSize += 1;
nLengthOffset = AddOffset(nOffset, m_pColumnInfo[i].ulColumnSize);
nStatusOffset = AddOffset(nLengthOffset, sizeof(ULONG));
Bind(pCurrent, m_pColumnInfo[i].iOrdinal, m_pColumnInfo[i].wType,
m_pColumnInfo[i].ulColumnSize, m_pColumnInfo[i].bPrecision, m_pColumnInfo[i].bScale,
DBPARAMIO_NOTPARAM, nOffset,
nLengthOffset, nStatusOffset, pObject);
pCurrent++;
// Note that, as we're not using this for anything else, we're using the
// pTypeInfo element to store the offset to our data.
m_pColumnInfo[i].pTypeInfo = (ITypeInfo*)nOffset;
nOffset = AddOffset(nStatusOffset, sizeof(DBSTATUS));
}
// Allocate the accessor memory if we haven't done so yet
if (m_pAccessorInfo == NULL)
{
hr = AllocateAccessorMemory(1); // We only have one accessor
if (FAILED(hr))
{
delete [] pBinding;
return hr;
}
m_pAccessorInfo->bAutoAccessor = TRUE;
}
// Allocate enough memory for the data buffer and tell the rowset
// Note that the rowset will free the memory in its destructor.
m_pBuffer = NULL;
ATLTRY(m_pBuffer = new BYTE[nOffset]);
if (m_pBuffer == NULL)
{
delete [] pBinding;
return E_OUTOFMEMORY;
}
hr = BindEntries(pBinding, m_nColumns, &m_pAccessorInfo->hAccessor,
nOffset, spAccessor);
delete [] pBinding;
return hr;
}
static ULONG AddOffset(ULONG nCurrent, ULONG nAdd)
{
struct foobar
{
char foo;
long bar;
};
ULONG nAlign = offsetof(foobar, bar);
return nCurrent + nAdd + (nAdd % nAlign);;
}
// Translate the column number to the index into the column info array
bool TranslateColumnNo(ULONG& nColumn) const
{
ATLASSERT(m_pColumnInfo != NULL);
// If the user has overriden the binding then we need to search
// through the column info for the ordinal number
if (m_bOverride)
{
for (ULONG i = 0; i < m_nColumns; i++)
{
if (m_pColumnInfo[i].iOrdinal == nColumn)
{
nColumn = i;
return true;
}
}
return false;
}
else
{
// Note that m_pColumnInfo->iOrdinal will be zero if have bound
// a bookmark as the first entry, otherwise it will be 1.
// If the column is out of range then return false
if (nColumn > (m_nColumns - 1 + m_pColumnInfo->iOrdinal))
return false;
// otherwise translate the column to an index into our internal
// binding entries array
nColumn -= m_pColumnInfo->iOrdinal;
return true;
}
}
typedef CDynamicAccessor _OutputColumnsClass;
static bool HasOutputColumns() { return true; }
ULONG m_nColumns;
DBCOLUMNINFO* m_pColumnInfo;
OLECHAR* m_pStringsBuffer;
bool m_bOverride;
};
///////////////////////////////////////////////////////////////////////////
// class CDynamicParameterAccessor
class CDynamicParameterAccessor : public CDynamicAccessor
{
// Constructors and Destructors
public:
typedef CDynamicParameterAccessor _ParamClass;
CDynamicParameterAccessor()
{
m_pParameterEntry = NULL;
m_pParameterBuffer = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -