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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: connection.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:20:42  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: connection.cpp,v 1000.1 2004/06/01 19:20: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.  * Author:  Vladimir Soussov
  35.  *
  36.  * File Description:  TDS connection
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ftds/interfaces.hpp>
  41. #include <string.h>
  42. BEGIN_NCBI_SCOPE
  43. CTDS_Connection::CTDS_Connection(CTDSContext* cntx, DBPROCESS* con,
  44.                                  bool reusable, const string& pool_name) :
  45.     m_Link(con), m_Context(cntx), m_Pool(pool_name), m_Reusable(reusable),
  46.     m_BCPAble(false), m_SecureLogin(false), m_ResProc(0)
  47. {
  48.     dbsetuserdata(m_Link, (BYTE*) this);
  49. }
  50. bool CTDS_Connection::IsAlive()
  51. {
  52.     return DBDEAD(m_Link) == FALSE;
  53. }
  54. CDB_LangCmd* CTDS_Connection::LangCmd(const string& lang_query,
  55.                                       unsigned int nof_parms)
  56. {
  57.     CTDS_LangCmd* lcmd = new CTDS_LangCmd(this, m_Link, lang_query, nof_parms);
  58.     m_CMDs.Add(lcmd);
  59.     return Create_LangCmd(*lcmd);
  60. }
  61. CDB_RPCCmd* CTDS_Connection::RPC(const string& rpc_name, unsigned int nof_args)
  62. {
  63.     CTDS_RPCCmd* rcmd = new CTDS_RPCCmd(this, m_Link, rpc_name, nof_args);
  64.     m_CMDs.Add(rcmd);
  65.     return Create_RPCCmd(*rcmd);
  66. }
  67. CDB_BCPInCmd* CTDS_Connection::BCPIn(const string& tab_name,
  68.                                      unsigned int nof_cols)
  69. {
  70.     if (!m_BCPAble) {
  71.         throw CDB_ClientEx(eDB_Error, 210003, "CTDS_Connection::BCPIn",
  72.                            "No bcp on this connection");
  73.     }
  74.     CTDS_BCPInCmd* bcmd = new CTDS_BCPInCmd(this, m_Link, tab_name, nof_cols);
  75.     m_CMDs.Add(bcmd);
  76.     return Create_BCPInCmd(*bcmd);
  77. }
  78. CDB_CursorCmd* CTDS_Connection::Cursor(const string& cursor_name,
  79.                                        const string& query,
  80.                                        unsigned int nof_params,
  81.                                        unsigned int)
  82. {
  83.     CTDS_CursorCmd* ccmd = new CTDS_CursorCmd(this, m_Link, cursor_name,
  84.                                               query, nof_params);
  85.     m_CMDs.Add(ccmd);
  86.     return Create_CursorCmd(*ccmd);
  87. }
  88. CDB_SendDataCmd* CTDS_Connection::SendDataCmd(I_ITDescriptor& descr_in,
  89.                                               size_t data_size, bool log_it)
  90. {
  91.     if (data_size < 1) {
  92.         throw CDB_ClientEx(eDB_Fatal, 210092,
  93.                            "CTDS_Connection::SendDataCmd",
  94.                            "wrong (zero) data size");
  95.     }
  96.     I_ITDescriptor* p_desc= 0;
  97.     // check what type of descriptor we've got
  98.     if(descr_in.DescriptorType() != CTDS_ITDESCRIPTOR_TYPE_MAGNUM) {
  99.         // this is not a native descriptor
  100.         p_desc= x_GetNativeITDescriptor(dynamic_cast<CDB_ITDescriptor&> (descr_in));
  101.         if(p_desc == 0) return false;
  102.     }
  103.     
  104.     C_ITDescriptorGuard d_guard(p_desc);
  105.     CTDS_ITDescriptor& desc = p_desc? dynamic_cast<CTDS_ITDescriptor&> (*p_desc) : 
  106.         dynamic_cast<CTDS_ITDescriptor&> (descr_in);
  107.     if (dbwritetext(m_Link,
  108.                     (char*) desc.m_ObjName.c_str(),
  109.                     desc.m_TxtPtr_is_NULL ? 0 : desc.m_TxtPtr,
  110.                     DBTXPLEN,
  111.                     desc.m_TimeStamp_is_NULL ? 0 : desc.m_TimeStamp,
  112.                     log_it ? TRUE : FALSE,
  113.                     data_size, 0) != SUCCEED ||
  114.         dbsqlok(m_Link) != SUCCEED ||
  115.         //        dbresults(m_Link) == FAIL) {
  116.         x_Results(m_Link) == FAIL) {
  117.         throw CDB_ClientEx(eDB_Error, 210093, "CTDS_Connection::SendDataCmd",
  118.                            "dbwritetext/dbsqlok/dbresults failed");
  119.     }
  120.     CTDS_SendDataCmd* sd_cmd = new CTDS_SendDataCmd(this, m_Link, data_size);
  121.     m_CMDs.Add(sd_cmd);
  122.     return Create_SendDataCmd(*sd_cmd);
  123. }
  124. bool CTDS_Connection::SendData(I_ITDescriptor& desc,
  125.                                CDB_Image& img, bool log_it){
  126.     return x_SendData(desc, dynamic_cast<CDB_Stream&> (img), log_it);
  127. }
  128. bool CTDS_Connection::SendData(I_ITDescriptor& desc,
  129.                                CDB_Text&  txt, bool log_it) {
  130.     return x_SendData(desc, dynamic_cast<CDB_Stream&> (txt), log_it);
  131. }
  132. bool CTDS_Connection::Refresh()
  133. {
  134.     // close all commands first
  135.     while (m_CMDs.NofItems()) {
  136.         CDB_BaseEnt* pCmd = static_cast<CDB_BaseEnt*> (m_CMDs.Get(0));
  137.         delete pCmd;
  138.         m_CMDs.Remove((int) 0);
  139.     }
  140.     // cancel all pending commands
  141.     if (dbcancel(m_Link) != CS_SUCCEED)
  142.         return false;
  143.     // check the connection status
  144.     return DBDEAD(m_Link) == FALSE;
  145. }
  146. const string& CTDS_Connection::ServerName() const
  147. {
  148.     return m_Server;
  149. }
  150. const string& CTDS_Connection::UserName() const
  151. {
  152.     return m_User;
  153. }
  154. const string& CTDS_Connection::Password() const
  155. {
  156.     return m_Passwd;
  157. }
  158. I_DriverContext::TConnectionMode CTDS_Connection::ConnectMode() const
  159. {
  160.     I_DriverContext::TConnectionMode mode = 0;
  161.     if ( m_BCPAble ) {
  162.         mode |= I_DriverContext::fBcpIn;
  163.     }
  164.     if ( m_SecureLogin ) {
  165.         mode |= I_DriverContext::fPasswordEncrypted;
  166.     }
  167.     return mode;
  168. }
  169. bool CTDS_Connection::IsReusable() const
  170. {
  171.     return m_Reusable;
  172. }
  173. const string& CTDS_Connection::PoolName() const
  174. {
  175.     return m_Pool;
  176. }
  177. I_DriverContext* CTDS_Connection::Context() const
  178. {
  179.     return const_cast<CTDSContext*> (m_Context);
  180. }
  181. void CTDS_Connection::PushMsgHandler(CDB_UserHandler* h)
  182. {
  183.     m_MsgHandlers.Push(h);
  184. }
  185. void CTDS_Connection::PopMsgHandler(CDB_UserHandler* h)
  186. {
  187.     m_MsgHandlers.Pop(h);
  188. }
  189. CDB_ResultProcessor* CTDS_Connection::SetResultProcessor(CDB_ResultProcessor* rp)
  190. {
  191.     CDB_ResultProcessor* r= m_ResProc;
  192.     m_ResProc= rp;
  193.     return r;
  194. }
  195. void CTDS_Connection::Release()
  196. {
  197.     m_BR = 0;
  198.     // close all commands first
  199.     while(m_CMDs.NofItems() > 0) {
  200.         CDB_BaseEnt* pCmd = static_cast<CDB_BaseEnt*> (m_CMDs.Get(0));
  201.         delete pCmd;
  202.         m_CMDs.Remove((int) 0);
  203.     }
  204. }
  205. CTDS_Connection::~CTDS_Connection()
  206. {
  207.     Refresh();
  208.     dbclose(m_Link);
  209. }
  210. void CTDS_Connection::DropCmd(CDB_BaseEnt& cmd)
  211. {
  212.     m_CMDs.Remove(static_cast<TPotItem> (&cmd));
  213. }
  214. bool CTDS_Connection::x_SendData(I_ITDescriptor& descr_in,
  215.                                  CDB_Stream& stream, bool log_it)
  216. {
  217.     size_t size = stream.Size();
  218.     if (size < 1)
  219.         return false;
  220.     I_ITDescriptor* p_desc= 0;
  221.     // check what type of descriptor we've got
  222.     if(descr_in.DescriptorType() != CTDS_ITDESCRIPTOR_TYPE_MAGNUM) {
  223.         // this is not a native descriptor
  224.         p_desc= x_GetNativeITDescriptor(dynamic_cast<CDB_ITDescriptor&> (descr_in));
  225.         if(p_desc == 0) return false;
  226.     }
  227.     
  228.     C_ITDescriptorGuard d_guard(p_desc);
  229.     CTDS_ITDescriptor& desc = p_desc? dynamic_cast<CTDS_ITDescriptor&> (*p_desc) : 
  230.         dynamic_cast<CTDS_ITDescriptor&> (descr_in);
  231.     // CTDS_ITDescriptor& desc = dynamic_cast<CTDS_ITDescriptor&> (descr_in);
  232.     char buff[1800]; // maximal page size
  233.     if (size <= sizeof(buff)) { // we could write a blob in one chunk
  234.         size_t s = stream.Read(buff, sizeof(buff));
  235.         if (dbwritetext(m_Link, (char*) desc.m_ObjName.c_str(),
  236.                         desc.m_TxtPtr_is_NULL ? 0 : desc.m_TxtPtr,
  237.                         DBTXPLEN,
  238.                         desc.m_TimeStamp_is_NULL ? 0 : desc.m_TimeStamp,
  239.                         log_it ? TRUE : FALSE, (DBINT) s, (BYTE*) buff)
  240.             != SUCCEED) {
  241.             throw CDB_ClientEx(eDB_Error, 210030, "CTDS_Connection::SendData",
  242.                                "dbwritetext failed");
  243.         }
  244.         return true;
  245.     }
  246.     // write it in chunks
  247.     if (dbwritetext(m_Link, (char*) desc.m_ObjName.c_str(),
  248.                     desc.m_TxtPtr_is_NULL ? 0 : desc.m_TxtPtr,
  249.                     DBTXPLEN,
  250.                     desc.m_TimeStamp_is_NULL ? 0 : desc.m_TimeStamp,
  251.                     log_it ? TRUE : FALSE, (DBINT) size, 0) != SUCCEED ||
  252.         dbsqlok(m_Link) != SUCCEED ||
  253.         //        dbresults(m_Link) == FAIL) {
  254.         x_Results(m_Link) == FAIL) {
  255.         throw CDB_ClientEx(eDB_Error, 210031, "CTDS_Connection::SendData",
  256.                            "dbwritetext/dbsqlok/dbresults failed");
  257.     }
  258.     while (size > 0) {
  259.         size_t s = stream.Read(buff, sizeof(buff));
  260.         if (s < 1) {
  261.             dbcancel(m_Link);
  262.             throw CDB_ClientEx(eDB_Fatal, 210032, "CTDS_Connection::SendData",
  263.                                "Text/Image data corrupted");
  264.         }
  265.         if (dbmoretext(m_Link, (DBINT) s, (BYTE*) buff) != SUCCEED) {
  266.             dbcancel(m_Link);
  267.             throw CDB_ClientEx(eDB_Error, 210033, "CTDS_Connection::SendData",
  268.                                "dbmoretext failed");
  269.         }
  270.         size -= s;
  271.     }
  272.     //    if (dbsqlok(m_Link) != SUCCEED || dbresults(m_Link) == FAIL) {
  273.     if (dbsqlok(m_Link) != SUCCEED || x_Results(m_Link) == FAIL) {
  274.         throw CDB_ClientEx(eDB_Error, 110034, "CTDS_Connection::SendData",
  275.                            "dbsqlok/dbresults failed");
  276.     }
  277.     return true;
  278. }
  279. I_ITDescriptor* CTDS_Connection::x_GetNativeITDescriptor(const CDB_ITDescriptor& descr_in)
  280. {
  281.     string q= "set rowcount 1nupdate ";
  282.     q+= descr_in.TableName();
  283.     q+= " set ";
  284.     q+= descr_in.ColumnName();
  285.     q+= "='0x0' where ";
  286.     q+= descr_in.SearchConditions();
  287.     q+= " nselect ";
  288.     q+= descr_in.ColumnName();
  289.     q+= " from ";
  290.     q+= descr_in.TableName();
  291.     q+= " where ";
  292.     q+= descr_in.SearchConditions();
  293.     q+= " nset rowcount 0";
  294.     
  295.     CDB_LangCmd* lcmd= LangCmd(q, 0);
  296.     if(!lcmd->Send()) {
  297.         throw CDB_ClientEx(eDB_Error, 210035, "CTDS_Connection::x_GetNativeITDescriptor",
  298.                            "can not send the language command");
  299.     }
  300.     CDB_Result* res;
  301.     I_ITDescriptor* descr= 0;
  302.     bool i;
  303.     while(lcmd->HasMoreResults()) {
  304.         res= lcmd->Result();
  305.         if(res == 0) continue;
  306.         if((res->ResultType() == eDB_RowResult) && (descr == 0)) {
  307.             EDB_Type tt= res->ItemDataType(0);
  308.             if(tt == eDB_Text || tt == eDB_Image) {
  309.                 while(res->Fetch()) {
  310.                     res->ReadItem(&i, 1);
  311.                     descr= new CTDS_ITDescriptor(m_Link, descr_in);
  312.                     // descr= res->GetImageOrTextDescriptor();
  313.                     if(descr) break;
  314.                 }
  315.             }
  316.         }
  317.         delete res;
  318.     }
  319.     delete lcmd;
  320.     return descr;
  321. }
  322. RETCODE CTDS_Connection::x_Results(DBPROCESS* pLink)
  323. {
  324.     unsigned int x_Status= 0x1;
  325.     CDB_Result* dbres;
  326.     I_Result* res= 0;
  327.     while ((x_Status & 0x1) != 0) {
  328.         switch (dbresults(pLink)) {
  329.         case SUCCEED:
  330.             if (DBCMDROW(pLink) == SUCCEED) { // we may get rows in this result
  331.                 if(!m_ResProc) {
  332.                     for(;;) {
  333.                         switch(dbnextrow(pLink)) {
  334.                         case NO_MORE_ROWS:
  335.                         case FAIL:
  336.                         case BUF_FULL: break;
  337.                         default: continue;
  338.                         }
  339.                         break;
  340.                     }
  341.                     continue;
  342.                 }
  343.                 res = new CTDS_RowResult(pLink, &x_Status);
  344.                 if(res) {
  345.                     dbres= Create_Result(*res);
  346.                     m_ResProc->ProcessResult(*dbres);
  347.                     delete dbres;
  348.                     delete res;
  349.                 }
  350.                 if ((x_Status & 0x10) != 0) { // we do have a compute result
  351.                     res = new CTDS_ComputeResult(pLink, &x_Status);
  352.                     if(res) {
  353.                         dbres= Create_Result(*res);
  354.                         m_ResProc->ProcessResult(*dbres);
  355.                         delete dbres;
  356.                         delete res;
  357.                     }
  358.                 }
  359.             } 
  360.             continue;
  361.             
  362.         case NO_MORE_RESULTS:
  363.             x_Status = 2;
  364.             break;
  365.         default:
  366.             return FAIL;
  367.         }
  368.         break;
  369.     }
  370.     
  371.     // we've done with the row results at this point
  372.     // let's look at return parameters and ret status
  373.     if (m_ResProc && x_Status == 2) {
  374.         x_Status = 4;
  375.         int n = dbnumrets(pLink);
  376.         if (n > 0) {
  377.             res = new CTDS_ParamResult(pLink, n);
  378.             if(res) {
  379.                 dbres= Create_Result(*res);
  380.                 m_ResProc->ProcessResult(*dbres);
  381.                 delete dbres;
  382.                 delete res;
  383.             }
  384.         }
  385.     }
  386.     
  387.     if (m_ResProc && x_Status == 4) {
  388.         if (dbhasretstat(pLink)) {
  389.             res = new CTDS_StatusResult(pLink);
  390.             if(res) {
  391.                 dbres= Create_Result(*res);
  392.                 m_ResProc->ProcessResult(*dbres);
  393.                 delete dbres;
  394.                 delete res;
  395.             }
  396.         }
  397.     }
  398.     return SUCCEED;
  399. }
  400. /////////////////////////////////////////////////////////////////////////////
  401. //
  402. //  CTDS_SendDataCmd::
  403. //
  404. CTDS_SendDataCmd::CTDS_SendDataCmd(CTDS_Connection* con, DBPROCESS* cmd,
  405.                                    size_t nof_bytes)
  406. {
  407.     m_Connect  = con;
  408.     m_Cmd      = cmd;
  409.     m_Bytes2go = nof_bytes;
  410. }
  411. size_t CTDS_SendDataCmd::SendChunk(const void* pChunk, size_t nof_bytes)
  412. {
  413.     if (!pChunk  ||  !nof_bytes) {
  414.         throw CDB_ClientEx(eDB_Fatal, 290000, "CTDS_SendDataCmd::SendChunk",
  415.                            "wrong (zero) arguments");
  416.     }
  417.     if (!m_Bytes2go)
  418.         return 0;
  419.     if (nof_bytes > m_Bytes2go)
  420.         nof_bytes = m_Bytes2go;
  421.     if (dbmoretext(m_Cmd, nof_bytes, (BYTE*) pChunk) != SUCCEED) {
  422.         dbcancel(m_Cmd);
  423.         throw CDB_ClientEx(eDB_Error, 290001, "CTDS_SendDataCmd::SendChunk",
  424.                            "dbmoretext failed");
  425.     }
  426.     m_Bytes2go -= nof_bytes;
  427.     if (m_Bytes2go <= 0) {
  428.         //        if (dbsqlok(m_Cmd) != SUCCEED || dbresults(m_Cmd) == FAIL) {
  429.         if (dbsqlok(m_Cmd) != SUCCEED || m_Connect->x_Results(m_Cmd) == FAIL) {
  430.             throw CDB_ClientEx(eDB_Error, 290002,
  431.                                "CTDS_SendDataCmd::SendChunk",
  432.                                "dbsqlok/results failed");
  433.         }
  434.     }
  435.     return nof_bytes;
  436. }
  437. void CTDS_SendDataCmd::Release()
  438. {
  439.     m_BR = 0;
  440.     if (m_Bytes2go > 0) {
  441.         dbcancel(m_Cmd);
  442.         m_Bytes2go = 0;
  443.     }
  444.     m_Connect->DropCmd(*this);
  445.     delete this;
  446. }
  447. CTDS_SendDataCmd::~CTDS_SendDataCmd()
  448. {
  449.     if (m_Bytes2go > 0)
  450.         dbcancel(m_Cmd);
  451.     if (m_BR)
  452.         *m_BR = 0;
  453. }
  454. END_NCBI_SCOPE
  455. /*
  456.  * ===========================================================================
  457.  * $Log: connection.cpp,v $
  458.  * Revision 1000.1  2004/06/01 19:20:42  gouriano
  459.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
  460.  *
  461.  * Revision 1.7  2004/05/17 21:13:37  gorelenk
  462.  * Added include of PCH ncbi_pch.hpp
  463.  *
  464.  * Revision 1.6  2003/06/05 16:01:40  soussov
  465.  * adds code for DumpResults and for the dumped results processing
  466.  *
  467.  * Revision 1.5  2002/12/03 19:21:24  soussov
  468.  * formatting
  469.  *
  470.  * Revision 1.4  2002/08/23 16:32:11  soussov
  471.  * fixes bug in ~CTDS_Connection()
  472.  *
  473.  * Revision 1.3  2002/03/26 15:35:10  soussov
  474.  * new image/text operations added
  475.  *
  476.  * Revision 1.2  2001/11/06 18:00:02  lavr
  477.  * Formatted uniformly as the rest of the library
  478.  *
  479.  * Revision 1.1  2001/10/25 00:39:22  vakatov
  480.  * Initial revision
  481.  *
  482.  * ===========================================================================
  483.  */