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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: rpc.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:20:24  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: rpc.cpp,v 1000.1 2004/06/01 19:20:24 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:  DBLib RPC command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #ifndef USE_MS_DBLIB
  41. #  include <dbapi/driver/dblib/interfaces.hpp>
  42. #  include <dbapi/driver/dblib/interfaces_p.hpp>
  43. #else
  44. #  include <dbapi/driver/msdblib/interfaces.hpp>
  45. #  include <dbapi/driver/msdblib/interfaces_p.hpp>
  46. #endif
  47. #include <dbapi/driver/util/numeric_convert.hpp>
  48. BEGIN_NCBI_SCOPE
  49. /////////////////////////////////////////////////////////////////////////////
  50. //
  51. //  CDBL_RPCCmd::
  52. //
  53. CDBL_RPCCmd::CDBL_RPCCmd(CDBL_Connection* con, DBPROCESS* cmd,
  54.                          const string& proc_name, unsigned int nof_params) :
  55.     m_Connect(con), m_Cmd(cmd), m_Query(proc_name), m_Params(nof_params),
  56.     m_WasSent(false), m_HasFailed(false), m_Recompile(false), m_Res(0),
  57.     m_RowCount(-1), m_Status(0)
  58. {
  59. }
  60. bool CDBL_RPCCmd::BindParam(const string& param_name,
  61.                             CDB_Object* param_ptr, bool out_param)
  62. {
  63.     return m_Params.BindParam(CDB_Params::kNoParamNumber, param_name,
  64.                               param_ptr, out_param);
  65. }
  66. bool CDBL_RPCCmd::SetParam(const string& param_name,
  67.                            CDB_Object* param_ptr, bool out_param)
  68. {
  69.     return m_Params.SetParam(CDB_Params::kNoParamNumber, param_name,
  70.                              param_ptr, out_param);
  71. }
  72. bool CDBL_RPCCmd::Send()
  73. {
  74.     if (m_WasSent)
  75.         Cancel();
  76.     m_HasFailed = false;
  77.     if (dbrpcinit(m_Cmd, (char*) m_Query.c_str(),
  78.                   m_Recompile ? DBRPCRECOMPILE : 0) != SUCCEED) {
  79.         m_HasFailed = true;
  80.         throw CDB_ClientEx(eDB_Error, 221001, "CDBL_RPCCmd::Send",
  81.                            "dbrpcinit failed");
  82.     }
  83.     char param_buff[2048]; // maximal page size
  84.     if (!x_AssignParams(param_buff)) {
  85.         m_HasFailed = true;
  86.         throw CDB_ClientEx(eDB_Error, 221003, "CDBL_RPCCmd::Send",
  87.                            "can not assign the params");
  88.     }
  89.     if (dbrpcsend(m_Cmd) != SUCCEED) {
  90.         m_HasFailed = true;
  91.         throw CDB_ClientEx(eDB_Error, 221005, "CDBL_RPCCmd::Send",
  92.                            "dbrpcsend failed");
  93.     }
  94.     m_WasSent = true;
  95.     m_Status = 0;
  96.     return true;
  97. }
  98. bool CDBL_RPCCmd::WasSent() const
  99. {
  100.     return m_WasSent;
  101. }
  102. bool CDBL_RPCCmd::Cancel()
  103. {
  104.     if (m_WasSent) {
  105.         if (m_Res) {
  106.             delete m_Res;
  107.             m_Res = 0;
  108.         }
  109.         m_WasSent = false;
  110.         return dbcancel(m_Cmd) == SUCCEED;
  111.     }
  112.     // m_Query.erase();
  113.     return true;
  114. }
  115. bool CDBL_RPCCmd::WasCanceled() const
  116. {
  117.     return !m_WasSent;
  118. }
  119. CDB_Result* CDBL_RPCCmd::Result()
  120. {
  121.     if (m_Res) {
  122.         if(m_RowCount < 0) {
  123.             m_RowCount = DBCOUNT(m_Cmd);
  124.         }
  125.         delete m_Res;
  126.         m_Res = 0;
  127.     }
  128.     if (!m_WasSent) {
  129.         throw CDB_ClientEx(eDB_Error, 221010, "CDBL_RPCCmd::Result",
  130.                            "you have to send a command first");
  131.     }
  132.     if (m_Status == 0) {
  133.         m_Status = 0x1;
  134.         if (dbsqlok(m_Cmd) != SUCCEED) {
  135.             m_WasSent = false;
  136.             m_HasFailed = true;
  137.             throw CDB_ClientEx(eDB_Error, 221011, "CDBL_RPCCmd::Result",
  138.                                "dbsqlok failed");
  139.         }
  140.     }
  141.     if ((m_Status & 0x10) != 0) { // we do have a compute result
  142.         m_Res = new CDBL_ComputeResult(m_Cmd, &m_Status);
  143.         m_RowCount= 1;
  144.         return Create_Result(*m_Res);
  145.     }
  146.     while ((m_Status & 0x1) != 0) {
  147.         switch (dbresults(m_Cmd)) {
  148.         case SUCCEED:
  149.             if (DBCMDROW(m_Cmd) == SUCCEED) { // we may get rows in this result
  150. // This optimization is currently unavailable for MS dblib...
  151. #ifndef MS_DBLIB_IN_USE /*Text,Image*/
  152.                 if (dbnumcols(m_Cmd) == 1) {
  153.                     int ct = dbcoltype(m_Cmd, 1);
  154.                     if ((ct == SYBTEXT) || (ct == SYBIMAGE)) {
  155.                         m_Res = new CDBL_BlobResult(m_Cmd);
  156.                     }
  157.                 }
  158. #endif
  159.                 if (!m_Res)
  160.                     m_Res = new CDBL_RowResult(m_Cmd, &m_Status);
  161.                 m_RowCount= -1;
  162.                 return Create_Result(*m_Res);
  163.             } else {
  164.                 m_RowCount = DBCOUNT(m_Cmd);
  165.                 continue;
  166.             }
  167.         case NO_MORE_RESULTS:
  168.             m_Status = 2;
  169.             break;
  170.         default:
  171.             m_HasFailed = true;
  172.             throw CDB_ClientEx(eDB_Warning, 221016, "CDBL_RPCCmd::Result",
  173.                                "error encountered in command execution");
  174.         }
  175.         break;
  176.     }
  177.     // we've done with the row results at this point
  178.     // let's look at return parameters and ret status
  179.     if (m_Status == 2) {
  180.         m_Status = 4;
  181.         int n = dbnumrets(m_Cmd);
  182.         if (n > 0) {
  183.             m_Res = new CDBL_ParamResult(m_Cmd, n);
  184.             m_RowCount= 1;
  185.             return Create_Result(*m_Res);
  186.         }
  187.     }
  188.     if (m_Status == 4) {
  189.         m_Status = 6;
  190.         if (dbhasretstat(m_Cmd)) {
  191.             m_Res = new CDBL_StatusResult(m_Cmd);
  192.             m_RowCount= 1;
  193.             return Create_Result(*m_Res);
  194.         }
  195.     }
  196.     m_WasSent = false;
  197.     return 0;
  198. }
  199. bool CDBL_RPCCmd::HasMoreResults() const
  200. {
  201.     return m_WasSent;
  202. }
  203. void CDBL_RPCCmd::DumpResults()
  204. {
  205.     CDB_Result* dbres;
  206.     while(m_WasSent) {
  207.         dbres= Result();
  208.         if(dbres) {
  209.             if(m_Connect->m_ResProc) {
  210.                 m_Connect->m_ResProc->ProcessResult(*dbres);
  211.             }
  212.             else {
  213.                 while(dbres->Fetch());
  214.             }
  215.             delete dbres;
  216.         }
  217.     }
  218. }
  219. bool CDBL_RPCCmd::HasFailed() const
  220. {
  221.     return m_HasFailed;
  222. }
  223. int CDBL_RPCCmd::RowCount() const
  224. {
  225.     return (m_RowCount < 0)? DBCOUNT(m_Cmd) : m_RowCount;
  226. }
  227. void CDBL_RPCCmd::SetRecompile(bool recompile)
  228. {
  229.     m_Recompile = recompile;
  230. }
  231. void CDBL_RPCCmd::Release()
  232. {
  233.     m_BR = 0;
  234.     if (m_WasSent) {
  235.         Cancel();
  236.         m_WasSent = false;
  237.     }
  238.     m_Connect->DropCmd(*this);
  239.     delete this;
  240. }
  241. CDBL_RPCCmd::~CDBL_RPCCmd()
  242. {
  243.     if (m_BR)
  244.         *m_BR = 0;
  245.     if (m_WasSent)
  246.         Cancel();
  247. }
  248. bool CDBL_RPCCmd::x_AssignParams(char* param_buff)
  249. {
  250.     RETCODE r;
  251.     for (unsigned int i = 0; i < m_Params.NofParams(); i++) {
  252.         if(m_Params.GetParamStatus(i) == 0) continue;
  253.         CDB_Object& param = *m_Params.GetParam(i);
  254.         BYTE status =
  255.             (m_Params.GetParamStatus(i) & CDB_Params::fOutput)
  256.             ? DBRPCRETURN : 0;
  257.         bool is_null = param.IsNULL();
  258.         switch (param.GetType()) {
  259.         case eDB_Int: {
  260.             CDB_Int& val = dynamic_cast<CDB_Int&> (param);
  261.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  262.                            status, SYBINT4, -1,
  263.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  264.             break;
  265.         }
  266.         case eDB_SmallInt: {
  267.             CDB_SmallInt& val = dynamic_cast<CDB_SmallInt&> (param);
  268.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  269.                            status, SYBINT2, -1,
  270.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  271.             break;
  272.         }
  273.         case eDB_TinyInt: {
  274.             CDB_TinyInt& val = dynamic_cast<CDB_TinyInt&> (param);
  275.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  276.                            status, SYBINT1, -1,
  277.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  278.             break;
  279.         }
  280.         case eDB_Bit: {
  281.             CDB_Bit& val = dynamic_cast<CDB_Bit&> (param);
  282.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  283.                            status, SYBBIT, -1,
  284.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  285.             break;
  286.         }
  287.         case eDB_BigInt: {
  288.             CDB_BigInt& val = dynamic_cast<CDB_BigInt&> (param);
  289.             DBNUMERIC* v = (DBNUMERIC*) param_buff;
  290.             Int8 v8 = val.Value();
  291.             if (longlong_to_numeric(v8, 18, DBNUMERIC_val(v)) == 0)
  292.                 return false;
  293.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  294.                            status, SYBNUMERIC, -1,
  295.                            is_null ? 0 : -1, (BYTE*) v);
  296.             param_buff = (char*) (v + 1);
  297.             break;
  298.         }
  299.         case eDB_Char: {
  300.             CDB_Char& val = dynamic_cast<CDB_Char&> (param);
  301.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  302.                            status, SYBCHAR, -1,
  303.                            is_null ? 0 : (DBINT) val.Size(),
  304.                            (BYTE*) val.Value());
  305.             break;
  306.         }
  307.         case eDB_VarChar: {
  308.             CDB_VarChar& val = dynamic_cast<CDB_VarChar&> (param);
  309.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  310.                            status, SYBCHAR, -1,
  311.                            is_null ? 0 : (DBINT) val.Size(),
  312.                            (BYTE*) val.Value());
  313.         }
  314.         break;
  315.         case eDB_Binary: {
  316.             CDB_Binary& val = dynamic_cast<CDB_Binary&> (param);
  317.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  318.                            status, SYBBINARY, -1,
  319.                            is_null ? 0 : (DBINT) val.Size(),
  320.                            (BYTE*) val.Value());
  321.             break;
  322.         }
  323.         case eDB_VarBinary: {
  324.             CDB_VarBinary& val = dynamic_cast<CDB_VarBinary&> (param);
  325.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  326.                            status, SYBBINARY, -1,
  327.                            is_null ? 0 : (DBINT) val.Size(),
  328.                            (BYTE*) val.Value());
  329.         }
  330.         break;
  331.         case eDB_Float: {
  332.             CDB_Float& val = dynamic_cast<CDB_Float&> (param);
  333.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  334.                            status, SYBREAL, -1,
  335.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  336.             break;
  337.         }
  338.         case eDB_Double: {
  339.             CDB_Double& val = dynamic_cast<CDB_Double&> (param);
  340.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  341.                            status, SYBFLT8, -1,
  342.                            is_null ? 0 : -1, (BYTE*) val.BindVal());
  343.             break;
  344.         }
  345.         case eDB_SmallDateTime: {
  346.             CDB_SmallDateTime& val = dynamic_cast<CDB_SmallDateTime&> (param);
  347.             DBDATETIME4* dt        = (DBDATETIME4*) param_buff;
  348.             DBDATETIME4_days(dt)   = val.GetDays();
  349.             DBDATETIME4_mins(dt)   = val.GetMinutes();
  350.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  351.                            status, SYBDATETIME4, -1,
  352.                            is_null ? 0 : -1, (BYTE*) dt);
  353.             param_buff = (char*) (dt + 1);
  354.             break;
  355.         }
  356.         case eDB_DateTime: {
  357.             CDB_DateTime& val = dynamic_cast<CDB_DateTime&> (param);
  358.             DBDATETIME* dt = (DBDATETIME*) param_buff;
  359.             dt->dtdays     = val.GetDays();
  360.             dt->dttime     = val.Get300Secs();
  361.             r = dbrpcparam(m_Cmd, (char*) m_Params.GetParamName(i).c_str(),
  362.                            status, SYBDATETIME, -1,
  363.                            is_null ? 0 : -1, (BYTE*) dt);
  364.             param_buff = (char*) (dt + 1);
  365.             break;
  366.         }
  367.         default:
  368.             return false;
  369.         }
  370.         if (r != SUCCEED)
  371.             return false;
  372.     }
  373.     return true;
  374. }
  375. END_NCBI_SCOPE
  376. /*
  377.  * ===========================================================================
  378.  * $Log: rpc.cpp,v $
  379.  * Revision 1000.1  2004/06/01 19:20:24  gouriano
  380.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  381.  *
  382.  * Revision 1.13  2004/05/18 18:30:37  gorelenk
  383.  * PCH <ncbi_pch.hpp> moved to correct place .
  384.  *
  385.  * Revision 1.12  2004/05/17 21:12:41  gorelenk
  386.  * Added include of PCH ncbi_pch.hpp
  387.  *
  388.  * Revision 1.11  2003/06/05 16:01:13  soussov
  389.  * adds code for DumpResults and for the dumped results processing
  390.  *
  391.  * Revision 1.10  2003/05/16 20:25:20  soussov
  392.  * adds code to skip parameter if it was not set
  393.  *
  394.  * Revision 1.9  2002/07/22 20:02:59  soussov
  395.  * fixes the RowCount calculations
  396.  *
  397.  * Revision 1.8  2002/07/02 16:05:50  soussov
  398.  * splitting Sybase dblib and MS dblib
  399.  *
  400.  * Revision 1.7  2002/02/22 22:12:33  soussov
  401.  * fixes bug with return params result
  402.  *
  403.  * Revision 1.6  2002/01/08 18:10:18  sapojnik
  404.  * Syabse to MSSQL name translations moved to interface_p.hpp
  405.  *
  406.  * Revision 1.5  2002/01/03 17:01:56  sapojnik
  407.  * fixing CR/LF mixup
  408.  *
  409.  * Revision 1.4  2002/01/03 15:46:23  sapojnik
  410.  * ported to MS SQL (about 12 'ifdef NCBI_OS_MSWIN' in 6 files)
  411.  *
  412.  * Revision 1.3  2001/10/24 16:39:32  lavr
  413.  * Explicit casts (where necessary) to eliminate 64->32 bit compiler warnings
  414.  *
  415.  * Revision 1.2  2001/10/22 16:28:02  lavr
  416.  * Default argument values removed
  417.  * (mistakenly left while moving code from header files)
  418.  *
  419.  * Revision 1.1  2001/10/22 15:19:56  lavr
  420.  * This is a major revamp (by Anton Lavrentiev, with help from Vladimir
  421.  * Soussov and Denis Vakatov) of the DBAPI "driver" libs originally
  422.  * written by Vladimir Soussov. The revamp follows the one of CTLib
  423.  * driver, and it involved massive code shuffling and grooming, numerous
  424.  * local API redesigns, adding comments and incorporating DBAPI to
  425.  * the C++ Toolkit.
  426.  *
  427.  * ===========================================================================
  428.  */