rs_impl.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:13k
- /*
- * ===========================================================================
- * PRODUCTION $Log: rs_impl.cpp,v $
- * PRODUCTION Revision 1000.3 2004/06/01 19:18:42 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: rs_impl.cpp,v 1000.3 2004/06/01 19:18:42 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * File Name: $Id: rs_impl.cpp,v 1000.3 2004/06/01 19:18:42 gouriano Exp $
- *
- * Author: Michael Kholodov
- *
- * File Description: Base class for database access
- *
- *
- * $Log: rs_impl.cpp,v $
- * Revision 1000.3 2004/06/01 19:18:42 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
- *
- * Revision 1.32 2004/05/17 21:10:28 gorelenk
- * Added include of PCH ncbi_pch.hpp
- *
- * Revision 1.31 2004/04/26 14:14:27 kholodov
- * Added: ExecteQuery() method
- *
- * Revision 1.30 2004/04/12 14:25:33 kholodov
- * Modified: resultset caching scheme, fixed single connection handling
- *
- * Revision 1.29 2004/04/08 15:56:58 kholodov
- * Multiple bug fixes and optimizations
- *
- * Revision 1.28 2004/03/02 19:37:56 kholodov
- * Added: process close event from CStatement to CResultSet
- *
- * Revision 1.27 2004/03/01 16:21:55 kholodov
- * Fixed: double deletion in calling subsequently CResultset::Close() and delete
- *
- * Revision 1.26 2004/02/19 15:23:21 kholodov
- * Fixed: attempt to delete cached CDB_Result when it was already deleted by the CResultSet object
- *
- * Revision 1.25 2004/02/10 18:50:44 kholodov
- * Modified: made Move() method const
- *
- * Revision 1.24 2003/06/25 21:03:05 kholodov
- * Fixed: method name in error message
- *
- * Revision 1.23 2003/05/05 18:32:50 kholodov
- * Added: LONGCHAR and LONGBINARY support
- *
- * Revision 1.22 2003/02/12 15:52:32 kholodov
- * Added: WasNull() method
- *
- * Revision 1.21 2003/02/06 19:59:22 kholodov
- * Fixed: CResultSet::GetColumnNo() never returned 1
- *
- * Revision 1.20 2002/11/25 15:15:50 kholodov
- * Removed: dynamic array module (array.hpp, array.cpp), using
- * STL vector instead to keep bound column data.
- *
- * Revision 1.19 2002/11/07 14:50:31 kholodov
- * Fixed: truncate BLOB buffer befor each successful read into CVariant object
- *
- * Revision 1.18 2002/10/31 22:37:05 kholodov
- * Added: DisableBind(), GetColumnNo(), GetTotalColumns() methods
- * Fixed: minor errors, diagnostic messages
- *
- * Revision 1.17 2002/10/21 20:38:08 kholodov
- * Added: GetParentConn() method to get the parent connection from IStatement,
- * ICallableStatement and ICursor objects.
- * Fixed: Minor fixes
- *
- * Revision 1.16 2002/10/03 18:50:00 kholodov
- * Added: additional TRACE diagnostics about object deletion
- * Fixed: setting parameters in IStatement object is fully supported
- * Added: IStatement::ExecuteLast() to execute the last statement with
- * different parameters if any
- *
- * Revision 1.15 2002/09/18 18:49:27 kholodov
- * Modified: class declaration and Action method to reflect
- * direct inheritance of CActiveObject from IEventListener
- *
- * Revision 1.14 2002/09/16 19:34:41 kholodov
- * Added: bulk insert support
- *
- * Revision 1.13 2002/09/09 20:48:57 kholodov
- * Added: Additional trace output about object life cycle
- * Added: CStatement::Failed() method to check command status
- *
- * Revision 1.12 2002/08/26 15:35:56 kholodov
- * Added possibility to disable transaction log
- * while updating BLOBs
- *
- * Revision 1.11 2002/07/08 16:08:19 kholodov
- * Modified: moved initialization code to Init() method
- *
- * Revision 1.10 2002/07/02 13:46:05 kholodov
- * Fixed: Incorrect exception class used CDB_Exception
- *
- * Revision 1.9 2002/07/01 13:15:11 kholodov
- * Added ITDescriptor diagnostics
- *
- * Revision 1.8 2002/06/24 19:10:03 kholodov
- * Added more trace diagnostics
- *
- * Revision 1.7 2002/06/11 16:22:54 kholodov
- * Fixed the incorrect declaration of GetMetaData() method
- *
- * Revision 1.6 2002/05/16 22:09:19 kholodov
- * Fixed: incorrect start of BLOB column
- *
- * Revision 1.5 2002/05/14 19:53:17 kholodov
- * Modified: Read() returns 0 to signal end of column
- *
- * Revision 1.4 2002/05/13 19:07:33 kholodov
- * Modified: every call to GetBlobIStream() returns new istream& object. Changed to retrieve data from several BLOB columns.
- *
- * Revision 1.3 2002/04/05 19:29:50 kholodov
- * Modified: GetBlobIStream() returns one and the same object, which is created
- * on the first call.
- * Added: GetVariant(const string& colName) to retrieve column value by
- * column name
- *
- * Revision 1.2 2002/03/13 16:40:16 kholodov
- * Modified indent formatting
- *
- * Revision 1.1 2002/01/30 14:51:21 kholodov
- * User DBAPI implementation, first commit
- *
- * Revision 1.1 2001/11/30 16:30:06 kholodov
- * Snapshot of the first draft of dbapi lib
- *
- *
- *
- */
- #include <ncbi_pch.hpp>
- #include "stmt_impl.hpp"
- #include "cstmt_impl.hpp"
- #include "conn_impl.hpp"
- #include "cursor_impl.hpp"
- #include "rs_impl.hpp"
- #include "rsmeta_impl.hpp"
- #include "dbexception.hpp"
- #include <dbapi/driver/public.hpp>
- #include <dbapi/driver/exception.hpp>
- #include <corelib/ncbistr.hpp>
- #include <typeinfo>
- BEGIN_NCBI_SCOPE
- CResultSet::CResultSet(CConnection* conn, CDB_Result *rs)
- : m_conn(conn),
- m_rs(rs), m_istr(0), m_ostr(0), m_column(-1),
- m_bindBlob(false), m_disableBind(false), m_wasNull(true)
- {
- SetIdent("CResultSet");
- if( m_rs == 0 ) {
- _TRACE("CResultSet::ctor(): null CDB_Result* object");
- _ASSERT(0);
- }
- else {
- Init();
- }
- }
- void CResultSet::Init()
- {
- // Reserve storage for column data
- EDB_Type type;
- for(unsigned int i = 0; i < m_rs->NofItems(); ++i ) {
- type = m_rs->ItemDataType(i);
- switch( type ) {
- case eDB_LongChar:
- m_data.push_back(CVariant::LongChar(0, m_rs->ItemMaxSize(i)));
- break;
- case eDB_LongBinary:
- m_data.push_back(CVariant::LongBinary(m_rs->ItemMaxSize(i), 0, 0));
- break;
- default:
- m_data.push_back(CVariant(type));
- break;
- }
- }
- _TRACE("CResultSet::Init(): Space reserved for " << m_data.size()
- << " columns");
- }
- CResultSet::~CResultSet()
- {
- Notify(CDbapiClosedEvent(this));
- FreeResources();
- Notify(CDbapiDeletedEvent(this));
- _TRACE(GetIdent() << " " << (void*)this << " deleted.");
- }
- const CVariant& CResultSet::GetVariant(unsigned int idx)
- {
- CheckIdx(idx - 1);
- return m_data[idx-1];
- }
- const CVariant& CResultSet::GetVariant(const string& name)
- {
- int zIdx = GetColNum(name);
- CheckIdx(zIdx);
- return m_data[zIdx];
- }
- const IResultSetMetaData* CResultSet::GetMetaData()
- {
- CResultSetMetaData *md = new CResultSetMetaData(m_rs);
- md->AddListener(this);
- AddListener(md);
- return md;
- }
- EDB_ResType CResultSet::GetResultType()
- {
- return m_rs->ResultType();
- }
- void CResultSet::BindBlobToVariant(bool b)
- {
- m_bindBlob = b;
- }
- void CResultSet::DisableBind(bool b)
- {
- m_disableBind = b;
- }
- bool CResultSet::Next()
- {
- bool more = false;
- EDB_Type type = eDB_UnsupportedType;
- more = m_rs->Fetch();
- if( more && !IsDisableBind() ) {
- for(unsigned int i = 0; i < m_rs->NofItems(); ++i ) {
-
- type = m_rs->ItemDataType(i);
-
- if( !IsBindBlob() ) {
- if( type == eDB_Text || type == eDB_Image ) {
- m_column = m_rs->CurrentItemNo();
- break;
- }
- }
- else {
- switch(type) {
- case eDB_Text:
- ((CDB_Text*)m_data[i].GetNonNullData())->Truncate();
- break;
- case eDB_Image:
- ((CDB_Image*)m_data[i].GetNonNullData())->Truncate();
- break;
- }
- }
-
- m_rs->GetItem(m_data[i].GetNonNullData());
- }
- }
- if( !more ) {
- if( m_ostr ) {
- _TRACE("CResulstSet: deleting BLOB output stream...");
- delete m_ostr;
- m_ostr = 0;
- }
- if( m_istr ) {
- _TRACE("CResulstSet: deleting BLOB input stream...");
- delete m_istr;
- m_istr = 0;
- }
- }
-
- return more;
- }
- size_t CResultSet::Read(void* buf, size_t size)
- {
- if( m_column < 0 || m_column != m_rs->CurrentItemNo() ) {
- if( m_column < 0 ) {
- _TRACE("CResulstSet: Column for raw Read not set, current column: "
- << m_rs->CurrentItemNo());
- #ifdef _DEBUG
- _ASSERT(0);
- #endif
- }
- else
- _TRACE("Last column: " << m_column);
- m_column = m_rs->CurrentItemNo();
- return 0;
- }
- else {
- return m_rs->ReadItem(buf, size, &m_wasNull);
- }
- }
- bool CResultSet::WasNull()
- {
- return m_wasNull;
- }
- int CResultSet::GetColumnNo()
- {
- int col = m_rs->CurrentItemNo();
- return col >= 0 ? col + 1 : -1;
- }
- unsigned int CResultSet::GetTotalColumns()
- {
- return m_rs->NofItems();
- }
- istream& CResultSet::GetBlobIStream(size_t buf_size)
- {
- #if 0
- if( m_istr == 0 ) {
- m_istr = new CBlobIStream(m_rs, buf_size);
- }
- #endif
- delete m_istr;
- m_istr = new CBlobIStream(m_rs, buf_size);
-
- return *m_istr;
- }
- ostream& CResultSet::GetBlobOStream(size_t blob_size,
- EAllowLog log_it,
- size_t buf_size)
- {
- // GetConnAux() returns pointer to pooled CDB_Connection.
- // we need to delete it every time we request new one.
- // The same with ITDescriptor
- delete m_ostr;
- // Call ReadItem(0, 0) before getting text/image descriptor
- m_rs->ReadItem(0, 0);
-
- I_ITDescriptor* desc = m_rs->GetImageOrTextDescriptor();
- if( desc == 0 ) {
- _TRACE("CResultSet::GetBlobOStream(): zero IT Descriptor");
- #ifdef _DEBUG
- _ASSERT(0);
- #else
- throw CDbapiException("CResultSet::GetBlobOStream(): Invalid IT Descriptor");
- #endif
- }
- m_ostr = new CBlobOStream(m_conn->CloneCDB_Conn(),
- desc,
- blob_size,
- buf_size,
- log_it == eEnableLog);
- return *m_ostr;
- }
- void CResultSet::Close()
- {
- Notify(CDbapiClosedEvent(this));
- FreeResources();
- }
- void CResultSet::FreeResources()
- {
- //_TRACE("CResultSet::Close(): deleting CDB_Result " << (void*)m_rs);
- Invalidate();
- delete m_istr;
- m_istr = 0;
- delete m_ostr;
- m_ostr = 0;
- }
-
- void CResultSet::Action(const CDbapiEvent& e)
- {
- _TRACE(GetIdent() << " " << (void*)this
- << ": '" << e.GetName()
- << "' received from " << e.GetSource()->GetIdent());
-
- if(dynamic_cast<const CDbapiClosedEvent*>(&e) != 0 ) {
- if( dynamic_cast<CStatement*>(e.GetSource()) != 0
- || dynamic_cast<CCallableStatement*>(e.GetSource()) != 0 ) {
- if( m_rs != 0 ) {
- _TRACE("Discarding old CDB_Result " << (void*)m_rs);
- Invalidate();
- }
- }
- }
- else if(dynamic_cast<const CDbapiDeletedEvent*>(&e) != 0 ) {
- RemoveListener(e.GetSource());
- if(dynamic_cast<CStatement*>(e.GetSource()) != 0
- || dynamic_cast<CCursor*>(e.GetSource()) != 0
- || dynamic_cast<CCallableStatement*>(e.GetSource()) != 0 ) {
- _TRACE("Deleting " << GetIdent() << " " << (void*)this);
- delete this;
- }
- }
- }
- int CResultSet::GetColNum(const string& name) {
-
- unsigned int i = 0;
- for( ; i < m_rs->NofItems(); ++i ) {
-
- if( !NStr::Compare(m_rs->ItemName(i), name) )
- return i;
- }
- throw CDbapiException("CResultSet::GetColNum(): invalid column name ["
- + name + "]");
- }
- void CResultSet::CheckIdx(unsigned int idx)
- {
- if( idx >= m_data.size() ) {
- #ifdef _DEBUG
- NcbiCerr << "CResultSet::CheckIdx(): Column index "
- << idx << " out of range" << endl;
- _ASSERT(0);
- #else
- throw CDbapiException("CResultSet::CheckIdx(): Column index"
- + NStr::IntToString(idx) + " out of range");
- #endif
- }
- }
- END_NCBI_SCOPE