📄 proxyrowsetimpl.h
字号:
const LONG numCols = GetNumColumns();
if (numCols == 0)
{
return DB_E_NOTABLE;
}
if (pcRowsAffected != NULL)
{
*pcRowsAffected = numCols;
}
return S_OK;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
STDMETHODIMP CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::GetData(
HROW hRow,
HACCESSOR hAccessor,
void *pDstData)
{
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - hRow = %d\n", hRow);
if (pDstData == NULL)
{
return E_INVALIDARG;
}
RowClass* pRow = 0;
if (hRow == NULL || (pRow = m_rgRowHandles.Lookup((RowClass::KeyType)hRow)) == NULL)
{
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Bad row handle\n");
return DB_E_BADROWHANDLE;
}
_BindType *pBinding = m_rgBindings.Lookup((int)hAccessor);
if (pBinding == NULL)
{
return DB_E_BADACCESSORHANDLE;
}
// At this point we know the bindings for the data we're accesssing...
HRESULT hr = S_OK;
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Bindings for %d columns\n", pBinding->cBindings);
for (ULONG iBind =0; SUCCEEDED(hr) && iBind < pBinding->cBindings; iBind++)
{
DBBINDING* pBindCur = &(pBinding->pBindings[iBind]);
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Binding for column ordinal %d\n", pBindCur->iOrdinal);
if (pBindCur->iOrdinal > GetNumColumns())
{
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Error - bad ordinal\n");
return DB_E_BADORDINAL;
}
BOOL bProvOwn = (pBindCur->dwMemOwner == DBMEMOWNER_PROVIDEROWNED);
if (bProvOwn)
{
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - Error - we dont support provider owned memory\n");
return E_FAIL;
}
DBSTATUS dbStat = DBSTATUS_S_OK;
ULONG cbDst = pBindCur->cbMaxLen;
BYTE *pDstTemp = (BYTE*)pDstData + pBindCur->obValue;
ULONG cbCol = 0;
void *pSrcTemp = 0;
DBTYPE colType;
bool bUpdatable;
InternalGetColumnData(pRow->m_iRowset, pBindCur->iOrdinal, colType, cbCol, pSrcTemp, bUpdatable);
if (pBindCur->dwPart & DBPART_VALUE)
{
hr = m_spConvert->DataConvert(
colType, // the column type
pBindCur->wType, // the required type
cbCol, // length of column data
&cbDst, // length of data after conversion
(BYTE*)pSrcTemp, // pointer to the column data
pDstTemp, // pointer to where to put it...
pBindCur->cbMaxLen, // max length of destination buffer
dbStat, // source status
&dbStat, // dest status
pBindCur->bPrecision, // precision
pBindCur->bScale, // scale
0); // flags - none supplied
}
if (pBindCur->dwPart & DBPART_LENGTH)
{
*((ULONG*)((BYTE*)(pDstData) + pBindCur->obLength)) = cbDst;
}
if (pBindCur->dwPart & DBPART_STATUS)
{
*((DBSTATUS*)((BYTE*)(pDstData) + pBindCur->obStatus)) = dbStat;
}
}
ATLTRACE2(atlTraceDBProvider, 0, "CProxyRowsetImpl::GetData - %s\n", (hr == S_OK ? "OK" : "FAILED"));
return hr;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::InternalGetColumnData(
size_t row,
size_t column,
DBTYPE &dbType,
ULONG &size,
void *&pData,
bool &bUpdatable)
{
if (column == 0)
{
// We handle the bookmark column.
dbType = DBTYPE_BYTES;
size = sizeof(DWORD);
static DWORD bookmark;
bookmark = row + 1; // The bookmark can't be 0, so we use the row index + 1
pData = &bookmark;
bUpdatable = false;
}
else
{
GetColumnData(row, column - 1, dbType, size, pData, bUpdatable);
}
}
///////////////////////////////////////////////////////////////////////////////
// Stuff needed because our storage object passes on the call it gets for
// column information, we own the column map.
///////////////////////////////////////////////////////////////////////////////
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
ATLCOLUMNINFO* CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::StorageProxy_GetColumnInfo(
ULONG *pcCols)
{
if (!m_pColumnInfo)
{
// If we've never been called before, build the column map...
BuildColumnInfo();
}
ULONG cCols = m_NumCols;
ATLCOLUMNINFO *pRetCols = m_pColumnInfo;
if (!BookmarksRequired())
{
// The column info map always contains the bookmark column as the first col,
// If bookmarks aren't required, pass out all but the first column info struct,
// and adjust the count to suit.
pRetCols++;
cCols--;
}
if (pcCols != NULL)
{
*pcCols = cCols;
}
return pRetCols;
}
///////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::BuildColumnInfo()
{
// columns start at 1, 0 is reserved for the bookmark column which may or may
// not be required, the actual ATLCOLUMNINFO entry for 0 is always present though
const size_t numCols = GetNumColumns();
m_NumCols = numCols + 1; // Add one for the bookmark column
m_pColumnInfo = new ATLCOLUMNINFO[m_NumCols];
ULONG ulCols = 0;
// Always add the bookmark column
// TODO: This should be called something other than "Bookmark"...
m_pColumnInfo[ulCols].pwszName = ustrdup("Bookmark");
m_pColumnInfo[ulCols].pTypeInfo = (ITypeInfo*)NULL;
m_pColumnInfo[ulCols].iOrdinal = ulCols;
m_pColumnInfo[ulCols].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK;
m_pColumnInfo[ulCols].ulColumnSize = sizeof(DWORD);
m_pColumnInfo[ulCols].wType = DBTYPE_BYTES;
m_pColumnInfo[ulCols].bPrecision = 0;
m_pColumnInfo[ulCols].bScale = 0;
m_pColumnInfo[ulCols].cbOffset = 0;
memset(&(m_pColumnInfo[ulCols].columnid), 0, sizeof(DBID));
m_pColumnInfo[ulCols].columnid.uName.pwszName = m_pColumnInfo[ulCols].pwszName;
ulCols++;
ULONG offset = sizeof(DWORD);
for (size_t i = 0; i < numCols; i++)
{
// Next set the other columns up.
DBTYPE dbType;
ULONG size;
std::string columnName;
DWORD flags = DBCOLUMNFLAGS_ISFIXEDLENGTH | DBCOLUMNFLAGS_WRITE;
GetColumnInformation(i, dbType, size, columnName, flags);
m_pColumnInfo[ulCols].pwszName = ustrdup(columnName.c_str());
m_pColumnInfo[ulCols].pTypeInfo = (ITypeInfo*)NULL;
m_pColumnInfo[ulCols].iOrdinal = ulCols;
m_pColumnInfo[ulCols].dwFlags = flags;
m_pColumnInfo[ulCols].ulColumnSize = size;
m_pColumnInfo[ulCols].wType = dbType;
m_pColumnInfo[ulCols].bPrecision = 0xFF;
m_pColumnInfo[ulCols].bScale = 0xFF;
m_pColumnInfo[ulCols].cbOffset = offset;
memset(&(m_pColumnInfo[ulCols].columnid), 0, sizeof(DBID));
m_pColumnInfo[ulCols].columnid.uName.pwszName = m_pColumnInfo[ulCols].pwszName;
offset += size; // offset isn't used by us.
ulCols++;
}
}
///////////////////////////////////////////////////////////////////////////////
// Stuff needed because our ArrayType is just a proxy that forwards all
// significant requests on to us. We own the data that our recordset represents!
///////////////////////////////////////////////////////////////////////////////
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
int CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_GetSize() const
{
return GetNumRows();
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
unsigned char &CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_IndexOperator(
int nIndex) const
{
ATLASSERT(true);
// This should never be called. We dont access the ArrayType using [], but the standard
// templates do and even though we're not using the code that does use [] we have to
// have one because VC doesnt quite conform to how templates are supposed to work (It
// should only require a function if we actually use it, we dont use it, so it shouldnt
// require it...)
// As such we assert, but we also have to return something or the compiler gets upset...
static unsigned char bugger = 'c';
return bugger;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
BOOL CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_Add(
Storage &/*storage*/)
{
// The standard ATL OLE DB Provider templates add a new row by creating an instance of
// the rowset class's Storage object and calling Add() on the ArrayType object...
// Our Storage and ArrayType objects are just thin proxies that pass all calls on to
// the Rowset, so we ignore the Storage that's passed in (it's meaningless to us) and
// assume that the Rowset knows how to add a row when we call AddRow()
return AddRow();
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
BOOL CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_RemoveAt(
int nIndex)
{
// The standard ATL OLE DB Provider templates use an array class as their ArrayType,
// removing a row (which isn't actually done in the standard provider...) can be achieved
// simply by calling RemoveAt(). Our ArrayType is a proxy that passes the call on to us,
// we call RemoveRow() on the derived Rowset and leave it up to it how or if it does the
// job.
return RemoveRow(nIndex);
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ArrayProxy_RemoveAll()
{
// The standard ATL OLE DB Provider templates use an array class as their ArrayType,
// RemoveAllRows() is called when the ArrayType object is destroyed, Our ArrayType is
// a proxy that passes the call on to us, we call RemoveAllRows() on the derived Rowset
// and leave it up to it how or if it does the job.
RemoveAllRows();
}
///////////////////////////////////////////////////////////////////////////////
// Default implementations of AddRow(), RemoveRow() and RemoveAllRows() so that
// if the derived Rowset doesnt need them it doesnt have to provide these empty
// implementations....
///////////////////////////////////////////////////////////////////////////////
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::AddRow()
{
// By default do nothing
return E_NOTIMPL;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::RemoveRow(
int nIndex)
{
// By default do nothing
return E_NOTIMPL;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::RemoveAllRows()
{
// By default do nothing
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
wchar_t *CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::ustrdup(const char *pIn)
{
size_t length = strlen(pIn) + 1;
wchar_t *pOut = new wchar_t[length];
if (pOut)
{
mbstowcs(pOut, pIn, length);
}
return pOut;
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::Execute(DBPARAMS * pParams, LONG* pcRowsAffected)
{
// This should never be used
return E_NOTIMPL;
}
#endif // __PROXY_ROWSET_IMPL__INCLUDED__
///////////////////////////////////////////////////////////////////////////////
// End of file...
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -