rs_impl.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:13k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: rs_impl.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:18:42  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: rs_impl.cpp,v 1000.3 2004/06/01 19:18:42 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE                          
  13. *               National Center for Biotechnology Information
  14. *                                                                          
  15. *  This software/database is a "United States Government Work" under the   
  16. *  terms of the United States Copyright Act.  It was written as part of    
  17. *  the author's official duties as a United States Government employee and 
  18. *  thus cannot be copyrighted.  This software/database is freely available 
  19. *  to the public for use. The National Library of Medicine and the U.S.    
  20. *  Government have not placed any restriction on its use or reproduction.  
  21. *                                                                          
  22. *  Although all reasonable efforts have been taken to ensure the accuracy  
  23. *  and reliability of the software and data, the NLM and the U.S.          
  24. *  Government do not and cannot warrant the performance or results that    
  25. *  may be obtained by using this software or data. The NLM and the U.S.    
  26. *  Government disclaim all warranties, express or implied, including       
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.                                                                
  29. *                                                                          
  30. *  Please cite the author in any work or product based on this material.   
  31. *
  32. * ===========================================================================
  33. *
  34. * File Name:  $Id: rs_impl.cpp,v 1000.3 2004/06/01 19:18:42 gouriano Exp $
  35. *
  36. * Author:  Michael Kholodov
  37. *   
  38. * File Description:  Base class for database access
  39. *
  40. *
  41. * $Log: rs_impl.cpp,v $
  42. * Revision 1000.3  2004/06/01 19:18:42  gouriano
  43. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
  44. *
  45. * Revision 1.32  2004/05/17 21:10:28  gorelenk
  46. * Added include of PCH ncbi_pch.hpp
  47. *
  48. * Revision 1.31  2004/04/26 14:14:27  kholodov
  49. * Added: ExecteQuery() method
  50. *
  51. * Revision 1.30  2004/04/12 14:25:33  kholodov
  52. * Modified: resultset caching scheme, fixed single connection handling
  53. *
  54. * Revision 1.29  2004/04/08 15:56:58  kholodov
  55. * Multiple bug fixes and optimizations
  56. *
  57. * Revision 1.28  2004/03/02 19:37:56  kholodov
  58. * Added: process close event from CStatement to CResultSet
  59. *
  60. * Revision 1.27  2004/03/01 16:21:55  kholodov
  61. * Fixed: double deletion in calling subsequently CResultset::Close() and delete
  62. *
  63. * Revision 1.26  2004/02/19 15:23:21  kholodov
  64. * Fixed: attempt to delete cached CDB_Result when it was already deleted by the CResultSet object
  65. *
  66. * Revision 1.25  2004/02/10 18:50:44  kholodov
  67. * Modified: made Move() method const
  68. *
  69. * Revision 1.24  2003/06/25 21:03:05  kholodov
  70. * Fixed: method name in error message
  71. *
  72. * Revision 1.23  2003/05/05 18:32:50  kholodov
  73. * Added: LONGCHAR and LONGBINARY support
  74. *
  75. * Revision 1.22  2003/02/12 15:52:32  kholodov
  76. * Added: WasNull() method
  77. *
  78. * Revision 1.21  2003/02/06 19:59:22  kholodov
  79. * Fixed: CResultSet::GetColumnNo() never returned 1
  80. *
  81. * Revision 1.20  2002/11/25 15:15:50  kholodov
  82. * Removed: dynamic array module (array.hpp, array.cpp), using
  83. * STL vector instead to keep bound column data.
  84. *
  85. * Revision 1.19  2002/11/07 14:50:31  kholodov
  86. * Fixed: truncate BLOB buffer befor each successful read into CVariant object
  87. *
  88. * Revision 1.18  2002/10/31 22:37:05  kholodov
  89. * Added: DisableBind(), GetColumnNo(), GetTotalColumns() methods
  90. * Fixed: minor errors, diagnostic messages
  91. *
  92. * Revision 1.17  2002/10/21 20:38:08  kholodov
  93. * Added: GetParentConn() method to get the parent connection from IStatement,
  94. * ICallableStatement and ICursor objects.
  95. * Fixed: Minor fixes
  96. *
  97. * Revision 1.16  2002/10/03 18:50:00  kholodov
  98. * Added: additional TRACE diagnostics about object deletion
  99. * Fixed: setting parameters in IStatement object is fully supported
  100. * Added: IStatement::ExecuteLast() to execute the last statement with
  101. * different parameters if any
  102. *
  103. * Revision 1.15  2002/09/18 18:49:27  kholodov
  104. * Modified: class declaration and Action method to reflect
  105. * direct inheritance of CActiveObject from IEventListener
  106. *
  107. * Revision 1.14  2002/09/16 19:34:41  kholodov
  108. * Added: bulk insert support
  109. *
  110. * Revision 1.13  2002/09/09 20:48:57  kholodov
  111. * Added: Additional trace output about object life cycle
  112. * Added: CStatement::Failed() method to check command status
  113. *
  114. * Revision 1.12  2002/08/26 15:35:56  kholodov
  115. * Added possibility to disable transaction log
  116. * while updating BLOBs
  117. *
  118. * Revision 1.11  2002/07/08 16:08:19  kholodov
  119. * Modified: moved initialization code to Init() method
  120. *
  121. * Revision 1.10  2002/07/02 13:46:05  kholodov
  122. * Fixed: Incorrect exception class used CDB_Exception
  123. *
  124. * Revision 1.9  2002/07/01 13:15:11  kholodov
  125. * Added ITDescriptor diagnostics
  126. *
  127. * Revision 1.8  2002/06/24 19:10:03  kholodov
  128. * Added more trace diagnostics
  129. *
  130. * Revision 1.7  2002/06/11 16:22:54  kholodov
  131. * Fixed the incorrect declaration of GetMetaData() method
  132. *
  133. * Revision 1.6  2002/05/16 22:09:19  kholodov
  134. * Fixed: incorrect start of BLOB column
  135. *
  136. * Revision 1.5  2002/05/14 19:53:17  kholodov
  137. * Modified: Read() returns 0 to signal end of column
  138. *
  139. * Revision 1.4  2002/05/13 19:07:33  kholodov
  140. * Modified: every call to GetBlobIStream() returns new istream& object. Changed to retrieve data from several BLOB columns.
  141. *
  142. * Revision 1.3  2002/04/05 19:29:50  kholodov
  143. * Modified: GetBlobIStream() returns one and the same object, which is created
  144. * on the first call.
  145. * Added: GetVariant(const string& colName) to retrieve column value by
  146. * column name
  147. *
  148. * Revision 1.2  2002/03/13 16:40:16  kholodov
  149. * Modified indent formatting
  150. *
  151. * Revision 1.1  2002/01/30 14:51:21  kholodov
  152. * User DBAPI implementation, first commit
  153. *
  154. * Revision 1.1  2001/11/30 16:30:06  kholodov
  155. * Snapshot of the first draft of dbapi lib
  156. *
  157. *
  158. *
  159. */
  160. #include <ncbi_pch.hpp>
  161. #include "stmt_impl.hpp"
  162. #include "cstmt_impl.hpp"
  163. #include "conn_impl.hpp"
  164. #include "cursor_impl.hpp"
  165. #include "rs_impl.hpp"
  166. #include "rsmeta_impl.hpp"
  167. #include "dbexception.hpp"
  168. #include <dbapi/driver/public.hpp>
  169. #include <dbapi/driver/exception.hpp>
  170. #include <corelib/ncbistr.hpp>
  171. #include <typeinfo>
  172. BEGIN_NCBI_SCOPE
  173. CResultSet::CResultSet(CConnection* conn, CDB_Result *rs)
  174.     : m_conn(conn),
  175.       m_rs(rs), m_istr(0), m_ostr(0), m_column(-1),
  176.       m_bindBlob(false), m_disableBind(false), m_wasNull(true)
  177. {
  178.     SetIdent("CResultSet");
  179.     if( m_rs == 0 ) {
  180.         _TRACE("CResultSet::ctor(): null CDB_Result* object");
  181.         _ASSERT(0);
  182.     }
  183.     else {
  184.         Init();
  185.     }
  186. }
  187. void CResultSet::Init() 
  188. {
  189.     // Reserve storage for column data
  190.     EDB_Type type;
  191.     for(unsigned int i = 0; i < m_rs->NofItems(); ++i ) {
  192.         type = m_rs->ItemDataType(i);
  193.         switch( type ) {
  194.         case eDB_LongChar:
  195.             m_data.push_back(CVariant::LongChar(0, m_rs->ItemMaxSize(i)));
  196.             break;
  197.         case eDB_LongBinary:
  198.             m_data.push_back(CVariant::LongBinary(m_rs->ItemMaxSize(i), 0, 0));
  199.             break;
  200.         default:
  201.             m_data.push_back(CVariant(type));
  202.             break;
  203.         }
  204.     }
  205.     _TRACE("CResultSet::Init(): Space reserved for " << m_data.size() 
  206.            << " columns");
  207. }
  208. CResultSet::~CResultSet()
  209. {
  210.     Notify(CDbapiClosedEvent(this));
  211.     FreeResources();
  212.     Notify(CDbapiDeletedEvent(this));
  213.     _TRACE(GetIdent() << " " << (void*)this << " deleted."); 
  214. }
  215. const CVariant& CResultSet::GetVariant(unsigned int idx) 
  216. {
  217.     CheckIdx(idx - 1);
  218.     return m_data[idx-1];
  219. }
  220. const CVariant& CResultSet::GetVariant(const string& name) 
  221. {
  222.     int zIdx = GetColNum(name);
  223.     CheckIdx(zIdx);
  224.     return m_data[zIdx];
  225. }
  226. const IResultSetMetaData* CResultSet::GetMetaData() 
  227. {
  228.     CResultSetMetaData *md = new CResultSetMetaData(m_rs);
  229.     md->AddListener(this);
  230.     AddListener(md);
  231.     return md;
  232. }
  233. EDB_ResType CResultSet::GetResultType() 
  234. {
  235.     return m_rs->ResultType();
  236. }
  237. void CResultSet::BindBlobToVariant(bool b) 
  238. {
  239.     m_bindBlob = b;
  240. }
  241. void CResultSet::DisableBind(bool b) 
  242. {
  243.     m_disableBind = b;
  244. }
  245. bool CResultSet::Next() 
  246. {
  247.     bool more = false;
  248.     EDB_Type type = eDB_UnsupportedType;
  249.     more = m_rs->Fetch();
  250.     if( more && !IsDisableBind() ) {
  251.         for(unsigned int i = 0; i < m_rs->NofItems(); ++i ) {
  252.             
  253.             type = m_rs->ItemDataType(i);
  254.             
  255.             if( !IsBindBlob() ) {
  256.                 if( type == eDB_Text || type == eDB_Image )  {
  257.                     m_column = m_rs->CurrentItemNo();
  258.                     break;
  259.                 }
  260.             }
  261.             else {
  262.                 switch(type) {
  263.                 case eDB_Text:
  264.                     ((CDB_Text*)m_data[i].GetNonNullData())->Truncate();
  265.                     break;
  266.                 case eDB_Image:
  267.                     ((CDB_Image*)m_data[i].GetNonNullData())->Truncate();
  268.                     break;
  269.                 }
  270.             }
  271.             
  272.             m_rs->GetItem(m_data[i].GetNonNullData());
  273.         }
  274.     } 
  275.     if( !more ) {
  276.         if( m_ostr ) {
  277.             _TRACE("CResulstSet: deleting BLOB output stream...");
  278.                    delete m_ostr;
  279.                    m_ostr = 0;
  280.         }
  281.         if( m_istr ) {
  282.             _TRACE("CResulstSet: deleting BLOB input stream...");
  283.             delete m_istr;
  284.             m_istr = 0;
  285.         }
  286.     }
  287.   
  288.     return more;
  289. }
  290. size_t CResultSet::Read(void* buf, size_t size)
  291. {
  292.     if( m_column < 0 || m_column != m_rs->CurrentItemNo() ) {
  293.         if( m_column < 0 ) {
  294.             _TRACE("CResulstSet: Column for raw Read not set, current column: "
  295.                    << m_rs->CurrentItemNo());
  296. #ifdef _DEBUG
  297.             _ASSERT(0);
  298. #endif
  299.         }
  300.         else
  301.             _TRACE("Last column: " << m_column);
  302.         m_column = m_rs->CurrentItemNo();
  303.         return 0;
  304.     }
  305.     else {
  306.         return m_rs->ReadItem(buf, size, &m_wasNull);
  307.     }
  308. }
  309. bool CResultSet::WasNull()
  310. {
  311.     return m_wasNull;
  312. }
  313. int CResultSet::GetColumnNo()
  314. {
  315.     int col = m_rs->CurrentItemNo();
  316.     return col >= 0 ? col + 1 : -1;
  317. }
  318. unsigned int CResultSet::GetTotalColumns()
  319. {
  320.     return m_rs->NofItems();
  321. }
  322. istream& CResultSet::GetBlobIStream(size_t buf_size)
  323. {
  324. #if 0
  325.     if( m_istr == 0 ) {
  326.         m_istr = new CBlobIStream(m_rs, buf_size);
  327.     }
  328. #endif
  329.     delete m_istr;
  330.     m_istr = new CBlobIStream(m_rs, buf_size);
  331.  
  332.     return *m_istr;
  333. }
  334. ostream& CResultSet::GetBlobOStream(size_t blob_size, 
  335.                                     EAllowLog log_it,
  336.                                     size_t buf_size)
  337. {
  338.     // GetConnAux() returns pointer to pooled CDB_Connection.
  339.     // we need to delete it every time we request new one.
  340.     // The same with ITDescriptor
  341.     delete m_ostr;
  342.     // Call ReadItem(0, 0) before getting text/image descriptor
  343.     m_rs->ReadItem(0, 0);
  344.     
  345.     I_ITDescriptor* desc = m_rs->GetImageOrTextDescriptor();
  346.     if( desc == 0 ) {
  347.         _TRACE("CResultSet::GetBlobOStream(): zero IT Descriptor");
  348. #ifdef _DEBUG
  349.         _ASSERT(0);
  350. #else
  351.         throw CDbapiException("CResultSet::GetBlobOStream(): Invalid IT Descriptor");
  352. #endif
  353.     }
  354.     m_ostr = new CBlobOStream(m_conn->CloneCDB_Conn(),
  355.                               desc,
  356.                               blob_size,
  357.                               buf_size,
  358.                               log_it == eEnableLog);
  359.     return *m_ostr;
  360. }
  361. void CResultSet::Close()
  362. {
  363.     Notify(CDbapiClosedEvent(this));
  364.     FreeResources();
  365. }
  366. void CResultSet::FreeResources()
  367. {
  368.     //_TRACE("CResultSet::Close(): deleting CDB_Result " << (void*)m_rs);
  369.     Invalidate();
  370.     delete m_istr;
  371.     m_istr = 0;
  372.     delete m_ostr;
  373.     m_ostr = 0;
  374. }
  375.   
  376. void CResultSet::Action(const CDbapiEvent& e) 
  377. {
  378.     _TRACE(GetIdent() << " " << (void*)this 
  379.               << ": '" << e.GetName() 
  380.               << "' received from " << e.GetSource()->GetIdent());
  381.     
  382.     if(dynamic_cast<const CDbapiClosedEvent*>(&e) != 0 ) {
  383.         if( dynamic_cast<CStatement*>(e.GetSource()) != 0
  384.             || dynamic_cast<CCallableStatement*>(e.GetSource()) != 0 ) {
  385.             if( m_rs != 0 ) {
  386.                 _TRACE("Discarding old CDB_Result " << (void*)m_rs);
  387.                 Invalidate();
  388.             }
  389.         }
  390.     }
  391.     else if(dynamic_cast<const CDbapiDeletedEvent*>(&e) != 0 ) {
  392.         RemoveListener(e.GetSource());
  393.         if(dynamic_cast<CStatement*>(e.GetSource()) != 0
  394.            || dynamic_cast<CCursor*>(e.GetSource()) != 0
  395.            || dynamic_cast<CCallableStatement*>(e.GetSource()) != 0 ) {
  396.             _TRACE("Deleting " << GetIdent() << " " << (void*)this); 
  397.             delete this;
  398.         }
  399.     }
  400. }
  401. int CResultSet::GetColNum(const string& name) {
  402.     
  403.     unsigned int i = 0;
  404.     for( ; i < m_rs->NofItems(); ++i ) {
  405.         
  406.         if( !NStr::Compare(m_rs->ItemName(i), name) )
  407.             return i;
  408.     }
  409.     throw CDbapiException("CResultSet::GetColNum(): invalid column name ["
  410.                           + name + "]");
  411. }
  412. void CResultSet::CheckIdx(unsigned int idx) 
  413. {
  414.     if( idx >= m_data.size() ) {
  415. #ifdef _DEBUG
  416.         NcbiCerr << "CResultSet::CheckIdx(): Column index " 
  417.                  << idx << " out of range" << endl;
  418.         _ASSERT(0);
  419. #else
  420.         throw CDbapiException("CResultSet::CheckIdx(): Column index" 
  421.                               + NStr::IntToString(idx) + " out of range");
  422. #endif
  423.     }
  424. }
  425. END_NCBI_SCOPE