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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: lang_cmd.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:19:44  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: lang_cmd.cpp,v 1000.1 2004/06/01 19:19:44 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:  CTLib language command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. BEGIN_NCBI_SCOPE
  42. /////////////////////////////////////////////////////////////////////////////
  43. //
  44. //  CTL_LangCmd::
  45. //
  46. CTL_LangCmd::CTL_LangCmd(CTL_Connection* conn, CS_COMMAND* cmd,
  47.                          const string& lang_query, unsigned int nof_params)
  48.     : m_Connect(conn),
  49.       m_Cmd(cmd),
  50.       m_Query(lang_query),
  51.       m_Params(nof_params)
  52. {
  53.     m_WasSent     = false;
  54.     m_HasFailed   = false;
  55.     m_Res         = 0;
  56.     m_RowCount    = -1;
  57. }
  58. bool CTL_LangCmd::More(const string& query_text)
  59. {
  60.     m_Query.append(query_text);
  61.     return true;
  62. }
  63. bool CTL_LangCmd::BindParam(const string& param_name, CDB_Object* param_ptr)
  64. {
  65.     return
  66.         m_Params.BindParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  67. }
  68. bool CTL_LangCmd::SetParam(const string& param_name, CDB_Object* param_ptr)
  69. {
  70.     return
  71.         m_Params.SetParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  72. }
  73. bool CTL_LangCmd::Send()
  74. {
  75.     if ( m_WasSent ) {
  76.         Cancel();
  77.     }
  78.     m_HasFailed = false;
  79.     switch ( ct_command(m_Cmd, CS_LANG_CMD,
  80.                         const_cast<char*> (m_Query.c_str()), CS_NULLTERM,
  81.                         CS_END) ) {
  82.     case CS_SUCCEED:
  83.         break;
  84.     case CS_FAIL:
  85.         m_HasFailed = true;
  86.         throw CDB_ClientEx(eDB_Fatal, 120001, "CTL_LangCmd::Send",
  87.                            "ct_command failed");
  88.     case CS_BUSY:
  89.         throw CDB_ClientEx(eDB_Error, 120002, "CTL_LangCmd::Send",
  90.                            "the connection is busy");
  91.     }
  92.     if ( !x_AssignParams() ) {
  93.         m_HasFailed = true;
  94.         throw CDB_ClientEx(eDB_Error, 120003, "CTL_LangCmd::Send",
  95.                            "cannot assign the params");
  96.     }
  97.     switch ( ct_send(m_Cmd) ) {
  98.     case CS_SUCCEED:
  99.         break;
  100.     case CS_FAIL:
  101.         m_HasFailed = true;
  102.         if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  103.             // we need to close this connection
  104.             throw CDB_ClientEx(eDB_Fatal, 120004, "CTL_LangCmd::Send",
  105.                                "Unrecoverable crash of ct_send. "
  106.                                "Connection must be closed");
  107.         }
  108.         throw CDB_ClientEx(eDB_Error, 120005, "CTL_LangCmd::Send",
  109.                            "ct_send failed");
  110.     case CS_CANCELED:
  111.         throw CDB_ClientEx(eDB_Error, 120006, "CTL_LangCmd::Send",
  112.                            "command was canceled");
  113.     case CS_BUSY:
  114.         throw CDB_ClientEx(eDB_Error, 120007, "CTL_LangCmd::Send",
  115.                            "connection has another request pending");
  116.     case CS_PENDING:
  117.     default:
  118.         m_WasSent = true;
  119.         return false;
  120.     }
  121.     m_WasSent = true;
  122.     return true;
  123. }
  124. bool CTL_LangCmd::WasSent() const
  125. {
  126.     return m_WasSent;
  127. }
  128. bool CTL_LangCmd::Cancel()
  129. {
  130.     if ( m_WasSent ) {
  131.         if ( m_Res ) {
  132.             // to prevent ct_cancel(NULL, m_Cmd, CS_CANCEL_CURRENT) call:
  133.             ((CTL_RowResult*)m_Res)->m_EOR= true; 
  134.             delete m_Res;
  135.             m_Res = 0;
  136.         }
  137.         switch ( ct_cancel(0, m_Cmd, CS_CANCEL_ALL) ) {
  138.         case CS_SUCCEED:
  139.             m_WasSent = false;
  140.             return true;
  141.         case CS_FAIL:
  142.             throw CDB_ClientEx(eDB_Error, 120008, "CTL_LangCmd::Cancel",
  143.                                "ct_cancel failed");
  144.         case CS_BUSY:
  145.             throw CDB_ClientEx(eDB_Error, 120009, "CTL_LangCmd::Cancel",
  146.                                "connection has another request pending");
  147.         default:
  148.             return false;
  149.         }
  150.     }
  151.     m_Query.erase();
  152.     return true;
  153. }
  154. bool CTL_LangCmd::WasCanceled() const
  155. {
  156.     return !m_WasSent;
  157. }
  158. CDB_Result* CTL_LangCmd::Result()
  159. {
  160.     if ( m_Res) {
  161.         delete m_Res;
  162.         m_Res = 0;
  163.     }
  164.     if ( !m_WasSent ) {
  165.         throw CDB_ClientEx(eDB_Error, 120010, "CTL_LangCmd::Result",
  166.                            "you need to send a command first");
  167.     }
  168.     for (;;) {
  169.         CS_INT res_type;
  170.         switch ( ct_results(m_Cmd, &res_type) ) {
  171.         case CS_SUCCEED:
  172.             break;
  173.         case CS_END_RESULTS:
  174.             m_WasSent = false;
  175.             return 0;
  176.         case CS_FAIL:
  177.             m_HasFailed = true;
  178.             if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  179.                 // we need to close this connection
  180.                 throw CDB_ClientEx(eDB_Fatal, 120012, "CTL_LangCmd::Result",
  181.                                    "Unrecoverable crash of ct_result. "
  182.                                    "Connection must be closed");
  183.             }
  184.             m_WasSent = false;
  185.             throw CDB_ClientEx(eDB_Error, 120013, "CTL_LangCmd::Result",
  186.                                "ct_result failed");
  187.         case CS_CANCELED:
  188.             m_WasSent = false;
  189.             throw CDB_ClientEx(eDB_Error, 120011, "CTL_LangCmd::Result",
  190.                                "your command has been canceled");
  191.         case CS_BUSY:
  192.             throw CDB_ClientEx(eDB_Error, 120014, "CTL_LangCmd::Result",
  193.                                "connection has another request pending");
  194.         default:
  195.             throw CDB_ClientEx(eDB_Error, 120015, "CTL_LangCmd::Result",
  196.                                "your request is pending");
  197.         }
  198.         switch ( res_type ) {
  199.         case CS_CMD_SUCCEED:
  200.         case CS_CMD_DONE: // done with this command
  201.             // check the number of affected rows
  202.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  203.             continue;
  204.         case CS_CMD_FAIL: // the command has failed
  205.             // check the number of affected rows
  206.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  207.             m_HasFailed = true;
  208.             throw CDB_ClientEx(eDB_Warning, 120016, "CTL_LangCmd::Result",
  209.                                "The server encountered an error while "
  210.                                "executing a command");
  211.         case CS_ROW_RESULT:
  212.             m_Res = new CTL_RowResult(m_Cmd);
  213.             break;
  214.         case CS_PARAM_RESULT:
  215.             m_Res = new CTL_ParamResult(m_Cmd);
  216.             break;
  217.         case CS_COMPUTE_RESULT:
  218.             m_Res = new CTL_ComputeResult(m_Cmd);
  219.             break;
  220.         case CS_STATUS_RESULT:
  221.             m_Res = new CTL_StatusResult(m_Cmd);
  222.             break;
  223.         case CS_COMPUTEFMT_RESULT:
  224.             throw CDB_ClientEx(eDB_Info, 120017, "CTL_LangCmd::Result",
  225.                                "CS_COMPUTEFMT_RESULT has arrived");
  226.         case CS_ROWFMT_RESULT:
  227.             throw CDB_ClientEx(eDB_Info, 120018, "CTL_LangCmd::Result",
  228.                                "CS_ROWFMT_RESULT has arrived");
  229.         case CS_MSG_RESULT:
  230.             throw CDB_ClientEx(eDB_Info, 120019, "CTL_LangCmd::Result",
  231.                                "CS_MSG_RESULT has arrived");
  232.         default:
  233.             throw CDB_ClientEx(eDB_Warning, 120020, "CTL_LangCmd::Result",
  234.                                "Unexpected result type has arrived");
  235.         }
  236.         return Create_Result(*m_Res);
  237.     }
  238. }
  239. void CTL_LangCmd::DumpResults()
  240. {
  241.     if ( m_Res) {
  242.         delete m_Res;
  243.         m_Res = 0;
  244.     }
  245.     if ( !m_WasSent ) {
  246.         throw CDB_ClientEx(eDB_Error, 120010, "CTL_LangCmd::DumpResults",
  247.                            "you need to send a command first");
  248.     }
  249.     
  250.     for (;;) {
  251.         CS_INT res_type;
  252.         switch ( ct_results(m_Cmd, &res_type) ) {
  253.         case CS_SUCCEED:
  254.             break;
  255.         case CS_END_RESULTS:
  256.             m_WasSent = false;
  257.             return;
  258.         case CS_FAIL:
  259.             m_HasFailed = true;
  260.             if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  261.                 // we need to close this connection
  262.                 throw CDB_ClientEx(eDB_Fatal, 120012, "CTL_LangCmd::DumpResults",
  263.                                    "Unrecoverable crash of ct_result. "
  264.                                    "Connection must be closed");
  265.             }
  266.             m_WasSent = false;
  267.             throw CDB_ClientEx(eDB_Error, 120013, "CTL_LangCmd::DumpResults",
  268.                                "ct_result failed");
  269.         case CS_CANCELED:
  270.             m_WasSent = false;
  271.             throw CDB_ClientEx(eDB_Error, 120011, "CTL_LangCmd::DumpResults",
  272.                                "your command has been canceled");
  273.         case CS_BUSY:
  274.             throw CDB_ClientEx(eDB_Error, 120014, "CTL_LangCmd::DumpResults",
  275.                                "connection has another request pending");
  276.         default:
  277.             throw CDB_ClientEx(eDB_Error, 120015, "CTL_LangCmd::DumpResults",
  278.                                "your request is pending");
  279.         }
  280.         switch ( res_type ) {
  281.         case CS_CMD_SUCCEED:
  282.         case CS_CMD_DONE: // done with this command
  283.             // check the number of affected rows
  284.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  285.             continue;
  286.         case CS_CMD_FAIL: // the command has failed
  287.             // check the number of affected rows
  288.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  289.             m_HasFailed = true;
  290.             throw CDB_ClientEx(eDB_Warning, 120016, "CTL_LangCmd::DumpResults",
  291.                                "The server encountered an error while "
  292.                                "executing a command");
  293.         case CS_ROW_RESULT:
  294.             m_Res = new CTL_RowResult(m_Cmd);
  295.             break;
  296.         case CS_PARAM_RESULT:
  297.             m_Res = new CTL_ParamResult(m_Cmd);
  298.             break;
  299.         case CS_COMPUTE_RESULT:
  300.             m_Res = new CTL_ComputeResult(m_Cmd);
  301.             break;
  302.         case CS_STATUS_RESULT:
  303.             m_Res = new CTL_StatusResult(m_Cmd);
  304.             break;
  305.         case CS_COMPUTEFMT_RESULT:
  306.             throw CDB_ClientEx(eDB_Info, 120017, "CTL_LangCmd::Result",
  307.                                "CS_COMPUTEFMT_RESULT has arrived");
  308.         case CS_ROWFMT_RESULT:
  309.             throw CDB_ClientEx(eDB_Info, 120018, "CTL_LangCmd::Result",
  310.                                "CS_ROWFMT_RESULT has arrived");
  311.         case CS_MSG_RESULT:
  312.             throw CDB_ClientEx(eDB_Info, 120019, "CTL_LangCmd::Result",
  313.                                "CS_MSG_RESULT has arrived");
  314.         default:
  315.             throw CDB_ClientEx(eDB_Warning, 120020, "CTL_LangCmd::Result",
  316.                                "Unexpected result type has arrived");
  317.         }
  318.         if(m_Res) {
  319.             if(m_Connect->m_ResProc) {
  320.                 CDB_Result* r= Create_Result(*m_Res);
  321.                 m_Connect->m_ResProc->ProcessResult(*r);
  322.                 delete r;
  323.             }
  324.             else {
  325.                 while(m_Res->Fetch());
  326.             }
  327.             delete m_Res;
  328.             m_Res= 0;
  329.         }
  330.     }
  331. }
  332. bool CTL_LangCmd::HasMoreResults() const
  333. {
  334.     return m_WasSent;
  335. }
  336. bool CTL_LangCmd::HasFailed() const
  337. {
  338.     return m_HasFailed;
  339. }
  340. int CTL_LangCmd::RowCount() const
  341. {
  342.     return m_RowCount;
  343. }
  344. void CTL_LangCmd::Release()
  345. {
  346.     m_BR = 0;
  347.     if ( m_WasSent ) {
  348.         try {
  349.             Cancel();
  350.         }catch (CDB_Exception& ) {}
  351.         m_WasSent = false;
  352.     }
  353.     m_Connect->DropCmd(*this);
  354.     delete this;
  355. }
  356. CTL_LangCmd::~CTL_LangCmd()
  357. {
  358.     if ( m_BR ) {
  359.         *m_BR = 0;
  360.     }
  361.     if ( m_WasSent ) {
  362.         try {
  363.             Cancel();
  364.         } catch (CDB_Exception& ) {
  365.         }
  366.     }
  367.     ct_cmd_drop(m_Cmd);
  368. }
  369. bool CTL_LangCmd::x_AssignParams()
  370. {
  371.     CS_DATAFMT param_fmt;
  372.     memset(&param_fmt, 0, sizeof(param_fmt));
  373.     param_fmt.namelen = CS_NULLTERM;
  374.     param_fmt.status  = CS_INPUTVALUE;
  375.     for (unsigned int i = 0;  i < m_Params.NofParams();  i++) {
  376.         if(m_Params.GetParamStatus(i) == 0) continue;
  377.         CDB_Object&   param      = *m_Params.GetParam(i);
  378.         const string& param_name = m_Params.GetParamName(i);
  379.         CS_SMALLINT   indicator  = param.IsNULL() ? -1 : 0;
  380.         if ( !g_CTLIB_AssignCmdParam(m_Cmd, param, param_name, param_fmt,
  381.                                      indicator, false/*!declare_only*/) ) {
  382.             return false;
  383.         }
  384.     }
  385.     return true;
  386. }
  387. END_NCBI_SCOPE
  388. /*
  389.  * ===========================================================================
  390.  * $Log: lang_cmd.cpp,v $
  391.  * Revision 1000.1  2004/06/01 19:19:44  gouriano
  392.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  393.  *
  394.  * Revision 1.9  2004/05/17 21:12:03  gorelenk
  395.  * Added include of PCH ncbi_pch.hpp
  396.  *
  397.  * Revision 1.8  2003/10/07 16:09:48  soussov
  398.  * adds code which prevents ct_cancel(NULL, m_Cmd, CS_CANCEL_CURRENT) call if command is canceled while retrieving results
  399.  *
  400.  * Revision 1.7  2003/06/24 18:42:25  soussov
  401.  * removes throwing exception from destructor
  402.  *
  403.  * Revision 1.6  2003/06/05 16:00:31  soussov
  404.  * adds code for DumpResults and for the dumped results processing
  405.  *
  406.  * Revision 1.5  2003/05/16 20:24:24  soussov
  407.  * adds code to skip parameters if it was not set
  408.  *
  409.  * Revision 1.4  2003/01/31 16:49:38  lavr
  410.  * Remove unused variable "e" from catch() clause
  411.  *
  412.  * Revision 1.3  2002/09/16 16:34:16  soussov
  413.  * add try catch when canceling in Release method
  414.  *
  415.  * Revision 1.2  2001/11/06 17:59:55  lavr
  416.  * Formatted uniformly as the rest of the library
  417.  *
  418.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  419.  * -----  Initial (draft) revision.  -----
  420.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  421.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  422.  * The revamp involved massive code shuffling and grooming, numerous local
  423.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  424.  *
  425.  * ===========================================================================
  426.  */