ODBCRecordset.h
00001 00002 #ifndef __ODBCRECORDSET_H__ 00003 #define __ODBCRECORDSET_H__ 00004 00005 #if _MSC_VER > 1000 00006 #pragma once 00007 #endif // _MSC_VER > 1000 00008 00009 #include <vector> 00010 using std::vector; 00011 00012 #include <afxdb.h> 00013 #include <afxtempl.h> 00014 #include <afxdtctl.h> 00015 00016 #define BINARY_FIELD_MAX_SIZE 7000 // DB에 사용할 Binary필드의 최대 크기(최대크기는 8000). 00017 #define BINARY_CHUNK_SIZE 7000 // Binary필드에 데이터를 전송할때 BINARY_CHUNK_SIZE보다 크면 나누어 보냄. 00018 #define RESERVE_SIZE 100 // CDBBinary클래스 vector자료구조를 위해서 사용. 00019 00020 00021 class CSimpleDBBinary 00022 { 00023 public : 00024 CSimpleDBBinary() : m_UsedSize( 0 ) {} 00025 ~CSimpleDBBinary() {} 00026 00027 int GetUsedSize() { return m_UsedSize; } 00028 00029 void SetUsedSize( const int iSize ) 00030 { 00031 m_UsedSize = iSize; 00032 } 00033 00034 int GetData( char* pOutBuf, const int nOutBufSize ) 00035 { 00036 if( (0 == pOutBuf) || 00037 (m_UsedSize > nOutBufSize) || 00038 (0 >= nOutBufSize) ) 00039 return -1; 00040 00041 memcpy( pOutBuf, m_Data, m_UsedSize ); 00042 00043 return m_UsedSize; 00044 } 00045 00046 int SetData( const char* pData, const int nInDataSize ) 00047 { 00048 if( (0 == pData) || 00049 (BINARY_FIELD_MAX_SIZE < nInDataSize) || 00050 (0 >= nInDataSize) ) 00051 return -1; 00052 00053 m_UsedSize = nInDataSize; 00054 00055 memcpy( m_Data, pData, nInDataSize ); 00056 00057 return m_UsedSize; 00058 } 00059 00060 private : 00061 char m_Data[ BINARY_FIELD_MAX_SIZE ]; 00062 int m_UsedSize; 00063 00064 public : 00065 int test; 00066 }; 00067 00068 00069 00070 class CDBBinary 00071 { 00072 public : 00073 CDBBinary( const int iFieldNum = RESERVE_SIZE, const int iReserveSize = RESERVE_SIZE ) : 00074 m_iIndex( 0 ), m_iCurrentUsedSize( 0 ), m_ReserveSize( iReserveSize ) 00075 { 00076 Reserve( iFieldNum ); 00077 } 00078 00079 ~CDBBinary() 00080 { 00081 m_vBinary.clear(); 00082 } 00083 00084 typedef int BinaryLength; 00085 typedef vector< CSimpleDBBinary > BinaryDataVec; 00086 typedef BinaryDataVec::iterator BinaryDataIter; 00087 00088 void Begin() 00089 { 00090 m_iIndex = 0; 00091 } 00092 00093 void Clear() { m_vBinary.clear(); } 00094 00095 int GetCurUsedSize() { return m_iCurrentUsedSize; } 00096 int GetCurIndex() { return m_iIndex; } 00097 int GetReserverSize() { return m_ReserveSize; } 00098 00099 void SetCurUsedSize( const int iCurUsedSize ) { m_iCurrentUsedSize = iCurUsedSize; } 00100 00101 void SetReserveSize( const int nReserveSize ) 00102 { 00103 if( 0 > nReserveSize ) 00104 { 00105 ASSERT( 0 ); 00106 return; 00107 } 00108 00109 m_ReserveSize = nReserveSize; 00110 } 00111 00112 int GetNextData( char* pOutputBuf, const int nDestBufSize ) 00113 { 00114 if( m_iIndex > m_iCurrentUsedSize ) 00115 return -1; 00116 00117 if( -1 == m_vBinary[m_iIndex].GetData(pOutputBuf, nDestBufSize) ) 00118 return -1; 00119 00120 return m_vBinary[ m_iIndex++ ].GetUsedSize(); 00121 } 00122 00123 int InsertData( const char* pData, const int nSrcDataSize ) 00124 { 00125 // 현제까지 할당된 공간이 충분한지 검사. 00126 if( m_iIndex >= static_cast<int>(m_vBinary.capacity()) ) 00127 { 00128 // 공간이 부족하면 추가적인 공간 할당을 함. 00129 if( !Reserve(m_ReserveSize) ) 00130 return -1; 00131 } 00132 00133 ++m_iIndex; 00134 m_iCurrentUsedSize = m_iIndex; 00135 00136 CSimpleDBBinary sbn; 00137 00138 // test 00139 sbn.test = m_iIndex; 00140 00141 // Insert작업이 끝난후의 데이터가 원본 데이터의 크기와 같은지 비교. 00142 if( nSrcDataSize != sbn.SetData(pData, nSrcDataSize) ) 00143 { 00144 --m_iIndex; 00145 --m_iCurrentUsedSize; 00146 00147 return -1; 00148 } 00149 00150 m_vBinary.push_back( sbn ); 00151 00152 return sbn.GetUsedSize(); 00153 } 00154 00155 private : 00156 bool Reserve( const int iExtSize ) 00157 { 00158 if( 0 > iExtSize ) 00159 { 00160 ASSERT( 0 ); 00161 return false; 00162 } 00163 00164 // 공간 확보. 공간 확보 실패시를 대비해서. 00165 try 00166 { 00167 m_vBinary.reserve( iExtSize + m_vBinary.size() ); 00168 } 00169 catch( ... ) 00170 { 00171 // 실패하면 크기 관련된 데이터를 -1로 설정. 00172 m_iCurrentUsedSize = -1; 00173 m_iIndex = -1; 00174 00175 return false; 00176 } 00177 00178 return true; 00179 } 00180 00181 private : 00182 int m_iIndex; // Insert, Get에 의해 참조된 마지막index. 00183 int m_iCurrentUsedSize; // InsertData( )에 의해서 추가된 총 필드 수. 00184 int m_ReserveSize; 00185 BinaryDataVec m_vBinary; 00186 }; 00187 00188 00189 class CDBField : public CDBVariant { 00190 // Constructors are private to avoid instantiation except by CODBCRecordset 00191 private: 00192 CDBField(); 00193 CDBField( const CDBField& dbv ); 00194 00195 CDBField& operator =( const CDBField& dbv ); 00196 00197 virtual ~CDBField(); 00198 00199 public: 00200 // Assignment operators 00201 CDBField& operator =( const bool bVal ); 00202 CDBField& operator =( const char chVal ); 00203 CDBField& operator =( const unsigned char chVal ); 00204 CDBField& operator =( const short sVal ); 00205 CDBField& operator =( const int iVal ); 00206 CDBField& operator =( const long lVal ); 00207 CDBField& operator =( const float fVal ); 00208 CDBField& operator =( const double fVal ); 00209 CDBField& operator =( const COleDateTime& dtVal ); 00210 CDBField& operator =( const CString& cVal ); 00211 CDBField& operator =( const LPCTSTR szVal ); 00212 00213 00214 00215 // Get the bool value. Do appropriate conversion. 00216 bool AsBool() const; 00217 // Get the unsigned char value. Do appropriate conversion. 00218 unsigned char AsChar() const; 00219 // Get the short value. Do appropriate conversion. 00220 short AsShort() const; 00221 //*** Get the int value which is equal to long value. Do appropriate conversion. 00222 int AsInt() const; 00223 // Get the long value. Do appropriate conversion. 00224 long AsLong() const; 00225 // Get the float value. Do appropriate conversion. 00226 float AsFloat() const; 00227 // Get the double value. Do appropriate conversion. 00228 double AsDouble() const; 00229 // Get the date and time value. Do appropriate conversion. 00230 COleDateTime AsDate() const; 00231 // Get the CString value. Do appropriate conversion. 00232 CString AsString() const; 00233 // Get the long binary value. Do appropriate conversion. 00234 CLongBinary* AsBinary() const; 00235 00236 00237 // Data type conversion operators 00238 00239 operator bool() const; 00240 operator unsigned char() const; 00241 operator short() const; 00242 operator int() const; 00243 operator long() const; 00244 operator float() const; 00245 operator double() const; 00246 operator COleDateTime() const; 00247 operator CString() const; 00248 operator CLongBinary*() const; 00249 00250 // Field type query methods 00251 00252 bool IsNull() const { return m_bIsNull || m_dwType == DBVT_NULL; }; 00253 bool IsBool() const { return m_dwType == DBVT_BOOL; }; 00254 bool IsChar() const { return m_dwType == DBVT_UCHAR; }; 00255 bool IsShort() const { return m_dwType == DBVT_SHORT; }; 00256 bool IsInt() const { return m_dwType == DBVT_LONG; }; 00257 bool IsLong() const { return m_dwType == DBVT_LONG; }; 00258 bool IsFloat() const { return m_dwType == DBVT_SINGLE; }; 00259 bool IsDouble() const { return m_dwType == DBVT_DOUBLE; }; 00260 bool IsNumber() const { return IsShort() || IsLong() || IsFloat() || IsDouble(); }; 00261 bool IsDate() const { return m_dwType == DBVT_DATE; }; 00262 bool IsString() const { return m_dwType == DBVT_STRING; }; 00263 bool IsBinary() const { return m_dwType == DBVT_BINARY; }; 00264 00265 // Get the field name 00266 const CString& GetName() const; 00267 00268 private: 00269 bool m_bIsNull; // If this field contain a NULL value 00270 CString m_cName; // Contain the field (column) name 00271 00272 void SetNull( bool bIsNull ) { m_bIsNull = bIsNull; }; 00273 00274 friend class CODBCRecordset; 00275 }; 00277 inline 00278 const CString& CDBField::GetName() const { 00279 return m_cName; 00280 } 00281 00282 inline 00283 CDBField::operator bool() const { 00284 return AsBool(); 00285 } 00286 inline 00287 CDBField::operator unsigned char() const { 00288 return AsChar(); 00289 } 00290 inline 00291 CDBField::operator short() const { 00292 return AsShort(); 00293 } 00294 inline 00295 CDBField::operator int() const { 00296 return AsInt(); 00297 } 00298 inline 00299 CDBField::operator long() const { 00300 return AsLong(); 00301 } 00302 inline 00303 CDBField::operator float() const { 00304 return AsFloat(); 00305 } 00306 inline 00307 CDBField::operator double() const { 00308 return AsDouble(); 00309 } 00310 inline 00311 CDBField::operator COleDateTime() const { 00312 return AsDate(); 00313 } 00314 inline 00315 CDBField::operator CString() const { 00316 return AsString(); 00317 } 00318 inline 00319 CDBField::operator CLongBinary*() const { 00320 return NULL; 00321 } 00323 00324 00325 00327 // CODBCRecordset 00328 class CODBCRecordset : public CRecordset 00329 { 00330 public: 00331 // Our constructor uses CRecordset constructor 00332 CODBCRecordset( CDatabase* pDatabase = NULL ); 00333 virtual ~CODBCRecordset(); 00334 00335 virtual BOOL Open( LPCTSTR lpszSQL, 00336 UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE, 00337 DWORD dwOptions = 0 ); 00338 00339 virtual void Move( long nRows, WORD wFetchType = SQL_FETCH_RELATIVE );// throw( CDBException, CMemoryException ); 00340 00341 00342 // Number of fields could be get by 00343 // CRecordset::GetODBCFieldCount() method 00344 00345 00346 // New functions: 00347 00348 // Get the field ID by name - case insensitive 00349 // CRecordset::GetFieldIndexByName() works, 00350 // but is case sensitive 00351 int GetFieldID( LPCTSTR szName ); 00352 // Get the field name by ID 00353 CString GetFieldName( int nID ); 00354 00355 00356 // Gets a field by name 00357 CDBField& Field( LPCTSTR szName ); 00358 // Gets a field by number 00359 CDBField& Field( int nField ); 00360 00361 // Gets a field by name 00362 CDBField& operator()( LPCTSTR szField ); 00363 // Gets a field by number 00364 CDBField& operator()( int nField ); 00365 00366 00367 // Get values by field names. Do conversion as appropriate. 00368 00369 bool GetBool( LPCTSTR szName ); 00370 unsigned char GetChar( LPCTSTR szName ); 00371 short GetShort( LPCTSTR szName ); 00372 int GetInt( LPCTSTR szName ); 00373 long GetLong( LPCTSTR szName ); 00374 float GetFloat( LPCTSTR szName ); 00375 double GetDouble( LPCTSTR szName ); 00376 COleDateTime GetDate( LPCTSTR szName ); 00377 CString GetString( LPCTSTR szName ); 00378 CLongBinary* GetBinary( LPCTSTR szName ); 00379 00380 00381 // Get values by field number. Do conversion as appropriate. 00382 00383 bool GetBool( int nCol ); 00384 unsigned char GetChar( int nCol ); 00385 short GetShort( int nCol ); 00386 int GetInt( int nCol ); 00387 long GetLong( int nCol ); 00388 float GetFloat( int nCol ); 00389 double GetDouble( int nCol ); 00390 COleDateTime GetDate( int nCol ); 00391 CString GetString( int nCol ); 00392 CLongBinary* GetBinary( int nCol ); 00393 00394 bool InsertBinary( CString strQuery, char* pData, const int nSize ); 00395 CDBBinary& SelectBinary( CString strQuery ); 00396 00397 00398 private: 00399 CDBField* m_fields; // Storage for fields 00400 int m_AllocatedFields; // Used to make smart storage reallocation 00401 CMapStringToPtr m_mapNameIdx; // Map field names to their ID 00402 bool m_bNotLoadedFieldsMap; // Is field names map still not loaded 00403 00404 void LoadFieldNamesMap(); 00405 00406 // Clear the internal data structures 00407 void Clear(); 00408 00409 // RFX support 00410 virtual void DoFieldExchange( CFieldExchange* pFX ); 00411 00412 // Allocate data buffer and set the field type 00413 void AllocDataBuffer( CDBVariant& varValue, CODBCFieldInfo& fi ); 00414 short GetCFieldType( short nSQLType ); 00415 }; 00417 00418 00419 00421 // CODBCRecordset class inline methods 00422 inline 00423 // Gets a field by name 00424 CDBField& CODBCRecordset::Field( LPCTSTR szName ) { 00425 return Field( GetFieldID( szName ) ); 00426 } 00427 00428 inline 00429 // Gets a field by number 00430 CDBField& CODBCRecordset::Field( int nField ) { 00431 // There is no allocated storage 00432 ASSERT( m_fields != NULL ); 00433 // The field ID is invalid 00434 ASSERT( nField >= 0 ); 00435 ASSERT( nField < GetODBCFieldCount() ); 00436 // There is no data in the current recordset position 00437 ASSERT( IsOpen() ); 00438 00439 return m_fields[ nField ]; 00440 } 00441 00443 // Get field methods 00444 inline 00445 CDBField& CODBCRecordset::operator()( LPCTSTR szField ) { 00446 return Field( szField ); 00447 } 00448 00449 inline 00450 CDBField& CODBCRecordset::operator()( int nField ) { 00451 return Field( nField ); 00452 } 00453 00455 // Get by Column Name 00456 inline 00457 bool CODBCRecordset::GetBool( LPCTSTR szName ) { 00458 return Field( szName ).AsBool(); 00459 } 00460 00461 inline 00462 unsigned char CODBCRecordset::GetChar( LPCTSTR szName ) { 00463 return Field( szName ).AsChar(); 00464 } 00465 00466 inline 00467 short CODBCRecordset::GetShort( LPCTSTR szName ) { 00468 return Field( szName ).AsShort(); 00469 } 00470 00471 inline 00472 int CODBCRecordset::GetInt( LPCTSTR szName ) { 00473 return Field( szName ).AsInt(); 00474 } 00475 00476 inline 00477 long CODBCRecordset::GetLong( LPCTSTR szName ) { 00478 return Field( szName ).AsLong(); 00479 } 00480 00481 inline 00482 float CODBCRecordset::GetFloat( LPCTSTR szName ) { 00483 return Field( szName ).AsFloat(); 00484 } 00485 00486 inline 00487 double CODBCRecordset:: GetDouble( LPCTSTR szName ) { 00488 return Field( szName ).AsDouble(); 00489 } 00490 00491 inline 00492 COleDateTime CODBCRecordset::GetDate( LPCTSTR szName ) { 00493 return Field( szName ).AsDate(); 00494 } 00495 00496 inline 00497 CString CODBCRecordset::GetString( LPCTSTR szName ) { 00498 return Field( szName ).AsString(); 00499 } 00500 00501 inline 00502 CLongBinary* CODBCRecordset::GetBinary( LPCTSTR szName ) { 00503 return Field( szName ).AsBinary(); 00504 } 00505 00507 // Get by Column Number 00508 inline 00509 bool CODBCRecordset::GetBool( int nCol ) { 00510 return Field( nCol ).AsBool(); 00511 } 00512 00513 inline 00514 unsigned char CODBCRecordset::GetChar( int nCol ) { 00515 return Field( nCol ).AsChar(); 00516 } 00517 00518 inline 00519 short CODBCRecordset::GetShort( int nCol ) { 00520 return Field( nCol ).AsShort(); 00521 } 00522 00523 inline 00524 int CODBCRecordset::GetInt( int nCol ) { 00525 return Field( nCol ).AsInt(); 00526 } 00527 00528 inline 00529 long CODBCRecordset::GetLong( int nCol ) { 00530 return Field( nCol ).AsLong(); 00531 } 00532 00533 inline 00534 float CODBCRecordset::GetFloat( int nCol ) { 00535 return Field( nCol ).AsFloat(); 00536 } 00537 00538 inline 00539 double CODBCRecordset:: GetDouble( int nCol ) { 00540 return Field( nCol ).AsDouble(); 00541 } 00542 00543 inline 00544 COleDateTime CODBCRecordset::GetDate( int nCol ) { 00545 return Field( nCol ).AsDate(); 00546 } 00547 00548 inline 00549 CString CODBCRecordset::GetString( int nCol ) { 00550 return Field( nCol ).AsString(); 00551 } 00552 00553 inline 00554 CLongBinary* CODBCRecordset::GetBinary( int nCol ) { 00555 return Field( nCol ).AsBinary(); 00556 } 00558 00559 #endif // __ODBCRECORDSET_H__
MAIET entertainment