📄 coledb.cpp
字号:
m_spRowset.Release();
}
BOOL COledbRecordset::IsOpen() const
{
return m_spRowset != NULL;
}
DWORD COledbRecordset::GetRowCount() const
{
return m_nRowsAffected;
}
BOOL COledbRecordset::GetField(short iIndex, long& Data)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_I1:
case DBTYPE_UI1:
Data = * (char*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
case DBTYPE_I2:
case DBTYPE_UI2:
Data = * (SHORT*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
case DBTYPE_I4:
case DBTYPE_UI4:
Data = * (LONG*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
BOOL COledbRecordset::GetField(short iIndex, float& Data)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
Data = (float) atof( (LPSTR) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) );
return TRUE;
case DBTYPE_R4:
Data = * (float*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
BOOL COledbRecordset::GetField(short iIndex, double& Data)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
Data = atof( (LPSTR) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) );
return TRUE;
case DBTYPE_R8:
Data = * (double*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
BOOL COledbRecordset::GetField(short iIndex, bool& Data)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_BOOL:
// TODO: Verify size of bool
Data = * (bool*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
BOOL COledbRecordset::GetField(short iIndex, TCHAR* pData, UINT cchMax)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
// NOTE: We should never be forced to convert between MBCS/UNICODE because
// the column binding sets up the desired TCHAR type.
USES_CONVERSION;
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
::lstrcpyn(pData, A2CT( (char*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) ), cchMax);
return TRUE;
case DBTYPE_WSTR:
::lstrcpyn(pData, W2CT( (WCHAR*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) ), cchMax);
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
BOOL COledbRecordset::GetField(short iIndex, SYSTEMTIME& Data)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
// NOTE: Not tested
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_DATE:
{
DATE date = * (DATE*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
::VariantTimeToSystemTime(date, &Data);
}
return TRUE;
case DBTYPE_DBDATE:
{
DBDATE date = * (DBDATE*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
Data.wYear = date.year;
Data.wMonth = date.month;
Data.wDay = date.day;
}
return TRUE;
case DBTYPE_DBTIME:
{
DBTIME time = * (DBTIME*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
Data.wHour = time.hour;
Data.wMinute = time.minute;
Data.wSecond = time.second;
}
return TRUE;
case DBTYPE_DBTIMESTAMP:
{
DBTIMESTAMP ts = * (DBTIMESTAMP*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
Data.wYear = ts.year;
Data.wMonth = ts.month;
Data.wDay = ts.day;
Data.wHour = ts.hour;
Data.wMinute = ts.minute;
Data.wSecond = ts.second;
}
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
#if defined(__ATLSTR_H__) || defined(_WTL_USE_CSTRING)
BOOL COledbRecordset::GetField(short iIndex, CString& pData)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
// NOTE: We should never be forced to convert between MBCS/UNICODE because
// the column binding sets up the desired TCHAR type.
USES_CONVERSION;
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
pData = A2CT( (char*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) );
return TRUE;
case DBTYPE_WSTR:
pData = W2CT( (WCHAR*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) );
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
#endif // __ATLSTR_H__
#if defined(_STRING_)
BOOL COledbRecordset::GetField(short iIndex, std::string& pData)
{
_ASSERTE(IsOpen());
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
USES_CONVERSION;
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
pData = (char*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue);
return TRUE;
case DBTYPE_WSTR:
pData = W2CA( (WCHAR*) ((LPBYTE) m_pData + m_rgBindings[iIndex].obValue) );
return TRUE;
default:
_ASSERTE(false);
return FALSE;
}
}
#endif // __ATLSTR_H__
short COledbRecordset::GetColumnCount() const
{
if( !IsOpen() ) return 0;
return m_nCols - m_iAdjustIndex;
}
DWORD COledbRecordset::GetColumnSize(short iIndex)
{
_ASSERTE(IsOpen());
return m_rgBindings[iIndex + m_iAdjustIndex].cbMaxLen;
}
short COledbRecordset::GetColumnType(short iIndex)
{
_ASSERTE(IsOpen());
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
iIndex += m_iAdjustIndex;
switch( m_rgBindings[iIndex].wType ) {
case DBTYPE_STR:
case DBTYPE_WSTR:
return DB_TYPE_CHAR;
case DBTYPE_I1:
case DBTYPE_UI1:
case DBTYPE_I2:
case DBTYPE_UI2:
case DBTYPE_I4:
case DBTYPE_UI4:
return DB_TYPE_INTEGER;
case DBTYPE_BOOL:
return DB_TYPE_BOOLEAN;
case DBTYPE_DATE:
case DBTYPE_DBDATE:
return DB_TYPE_DATE;
case DBTYPE_DBTIME:
return DB_TYPE_TIME;
case DBTYPE_DBTIMESTAMP:
return DB_TYPE_TIMESTAMP;
case DBTYPE_R4:
return DB_TYPE_REAL;
case DBTYPE_DECIMAL:
case DBTYPE_NUMERIC:
case DBTYPE_R8:
return DB_TYPE_DOUBLE;
default:
return DB_TYPE_UNKNOWN;
}
}
BOOL COledbRecordset::GetColumnName(short iIndex, TCHAR* pstrName, UINT cchMax)
{
_ASSERTE(IsOpen());
_ASSERTE(cchMax>0);
_ASSERTE(!::IsBadWritePtr(pstrName, cchMax));
iIndex += m_iAdjustIndex;
_ASSERTE(iIndex>=0 && iIndex<m_nCols);
// Find entry in the NULL-terminated string buffer
LPCWSTR pwstr = m_pwstrNameBuffer;
if( pwstr == NULL ) return FALSE;
while( iIndex > 0 ) {
pwstr += ::lstrlenW(pwstr) + 1;
iIndex--;
}
// Copy name
USES_CONVERSION;
::lstrcpyn(pstrName, W2CT(pwstr), cchMax);
return TRUE;
}
short COledbRecordset::GetColumnIndex(LPCTSTR pstrName) const
{
_ASSERTE(IsOpen());
_ASSERTE(!::IsBadStringPtr(pstrName,-1));
USES_CONVERSION;
LPCWSTR pwstrName = T2CW(pstrName);
LPCWSTR pwstr = m_pwstrNameBuffer;
if( pwstr == NULL ) return FALSE;
for( short i = 0; i < m_nCols; i++ ) {
if( ::lstrcmpiW(pwstrName, pwstr) == 0 ) return i - m_iAdjustIndex;;
pwstr += ::lstrlenW(pwstr) + 1;
}
return -1;
}
BOOL COledbRecordset::IsEOF() const
{
if( !IsOpen() ) return TRUE;
return m_fEOF;
}
BOOL COledbRecordset::MoveNext()
{
return MoveCursor(0, 1);
}
BOOL COledbRecordset::MovePrev()
{
return MoveCursor(-2, 1);
}
BOOL COledbRecordset::MoveTop()
{
_ASSERTE(IsOpen());
m_spRowset->RestartPosition(DB_NULL_HCHAPTER);
return MoveCursor(0, 1);
}
BOOL COledbRecordset::MoveBottom()
{
_ASSERTE(IsOpen());
// Restart and then move backwards...
m_spRowset->RestartPosition(DB_NULL_HCHAPTER);
return MoveCursor(-1, 1);
}
BOOL COledbRecordset::MoveAbs(DWORD dwPos)
{
_ASSERTE(IsOpen());
m_spRowset->RestartPosition(DB_NULL_HCHAPTER);
return MoveCursor(dwPos, 1);
}
DWORD COledbRecordset::GetRowNumber()
{
_ASSERTE(IsOpen());
// BUG: Not working because we do not require IRowsetScroll support
CComQIPtr<IRowsetScroll> spScroll = m_spRowset;
if( spScroll == NULL ) return 0;
DBCOUNTITEM nRows;
BYTE cBookmark = DBBMK_LAST;
HRESULT Hr = spScroll->GetApproximatePosition(DB_NULL_HCHAPTER, NULL, &cBookmark, NULL, &nRows);
if( FAILED(Hr) ) return 0;
return (DWORD)nRows;
}
BOOL COledbRecordset::NextResultset()
{
_ASSERTE(IsOpen());
return FALSE;
}
BOOL COledbRecordset::MoveCursor(LONG lSkip, LONG lAmount)
{
_ASSERTE(IsOpen());
HRESULT Hr;
::ZeroMemory(m_pData, m_dwBufferSize);
// Move the cursor and get some data
HROW* rghRows = NULL;
ULONG nRecevied;
Hr = m_spRowset->GetNextRows(DB_NULL_HCHAPTER, lSkip, lAmount, &nRecevied, &rghRows);
// Update EOF marker (HRESULT can be anything but S_OK)
m_fEOF = Hr != S_OK;
if( Hr != S_OK ) return TRUE; // Error or reached bottom
// Get field values
Hr = m_spRowset->GetData(*rghRows, m_hAccessor, m_pData);
// Before we check the result, release the rows
m_spRowset->ReleaseRows(nRecevied, rghRows, NULL, NULL, NULL);
// Finally, check GetData() result...
if( FAILED(Hr) ) return _Error(Hr);
return TRUE;
}
BOOL COledbRecordset::Attach(IRowset* pRowset)
{
Close();
m_spRowset = pRowset;
if( !_BindColumns() ) return TRUE; // In case of UPDATE/INSERT without a result
// then there are no columns
return MoveNext();
}
BOOL COledbRecordset::_Error(HRESULT Hr)
{
if( m_pDb == NULL ) return FALSE;
return m_pDb->_Error(Hr);
}
BOOL COledbRecordset::_BindColumns()
{
_ASSERTE(m_rgBindings==NULL);
if( !IsOpen() ) return FALSE;
HRESULT Hr;
m_nCols = 0;
m_pwstrNameBuffer = NULL;
CComQIPtr<IColumnsInfo> spColInfo = m_spRowset;
if( spColInfo == NULL ) return FALSE;
DBCOLUMNINFO* rgColumnInfo = NULL;
ULONG nCols = 0;
Hr = spColInfo->GetColumnInfo(&nCols, &rgColumnInfo, &m_pwstrNameBuffer);
if( FAILED(Hr) ) return _Error(Hr);
// Allocate memory for the bindings array; there is a one-to-one
// mapping between the columns returned from GetColumnInfo() and our
// bindings.
long cbAlloc = nCols * sizeof(DBBINDING);
m_rgBindings = (DBBINDING*) ::CoTaskMemAlloc(cbAlloc);
if( m_rgBindings == NULL ) return FALSE;
::ZeroMemory(m_rgBindings, cbAlloc);
m_iAdjustIndex = 0;
// Construct the binding array element for each column.
ULONG dwOffset = 0;
for( ULONG iCol = 0; iCol < nCols; iCol++ ) {
DBBINDING& b = m_rgBindings[iCol];
b.iOrdinal = rgColumnInfo[iCol].iOrdinal;
b.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
b.obStatus = dwOffset;
b.obLength = dwOffset + sizeof(DBSTATUS);
b.obValue = dwOffset + sizeof(DBSTATUS) + sizeof(ULONG);
b.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
b.eParamIO = DBPARAMIO_NOTPARAM;
b.bPrecision = rgColumnInfo[iCol].bPrecision;
b.bScale = rgColumnInfo[iCol].bScale;
// Ignore bookmark column
if( (rgColumnInfo[iCol].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK) != 0 ) m_iAdjustIndex++;
WORD wType = rgColumnInfo[iCol].wType;
switch( wType ) {
case DBTYPE_CY:
case DBTYPE_DECIMAL:
case DBTYPE_NUMERIC:
b.wType = DBTYPE_STR;
b.cbMaxLen = 50; // Allow 50 characters for conversion
break;
case DBTYPE_STR:
case DBTYPE_WSTR:
#ifdef _UNICODE
b.wType = DBTYPE_WSTR;
#else
b.wType = DBTYPE_STR;
#endif
b.cbMaxLen = max(min((rgColumnInfo[iCol].ulColumnSize + 1UL) * sizeof(TCHAR), 1024UL), 0UL);
break;
default:
b.wType = wType;
b.cbMaxLen = max(min(rgColumnInfo[iCol].ulColumnSize, 1024UL), 0UL);
}
// ROUNDUP on all platforms pointers must be aligned properly
#define ROUNDUP_AMOUNT 8
#define ROUNDUP_(size,amount) (((ULONG)(size)+((amount)-1))&~((amount)-1))
#define ROUNDUP(size) ROUNDUP_(size, ROUNDUP_AMOUNT)
// Update the offset past the end of this column's data
dwOffset = b.cbMaxLen + b.obValue;
dwOffset = ROUNDUP(dwOffset);
}
m_nCols = (short) nCols;
m_dwBufferSize = dwOffset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -