⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coledb.cpp

📁 remote debug and compile tools
💻 CPP
📖 第 1 页 / 共 3 页
字号:
   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 + -