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:20:19  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.14
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: lang_cmd.cpp,v 1000.1 2004/06/01 19:20:19 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 language 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. BEGIN_NCBI_SCOPE
  48. /////////////////////////////////////////////////////////////////////////////
  49. //
  50. //  CDBL_LangCmd::
  51. //
  52. CDBL_LangCmd::CDBL_LangCmd(CDBL_Connection* conn, DBPROCESS* cmd,
  53.                            const string& lang_query,
  54.                            unsigned int nof_params) :
  55.     m_Connect(conn), m_Cmd(cmd), m_Query(lang_query), m_Params(nof_params)
  56. {
  57.     m_WasSent   =  false;
  58.     m_HasFailed =  false;
  59.     m_Res       =  0;
  60.     m_RowCount  = -1;
  61.     m_Status    =  0;
  62. }
  63. bool CDBL_LangCmd::More(const string& query_text)
  64. {
  65.     m_Query.append(query_text);
  66.     return true;
  67. }
  68. bool CDBL_LangCmd::BindParam(const string& param_name, CDB_Object* param_ptr)
  69. {
  70.     return
  71.         m_Params.BindParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  72. }
  73. bool CDBL_LangCmd::SetParam(const string& param_name, CDB_Object* param_ptr)
  74. {
  75.     return
  76.         m_Params.SetParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  77. }
  78. bool CDBL_LangCmd::Send()
  79. {
  80.     if (m_WasSent)
  81.         Cancel();
  82.     m_HasFailed = false;
  83.     if (!x_AssignParams()) {
  84.         dbfreebuf(m_Cmd);
  85.         m_HasFailed = true;
  86.         throw CDB_ClientEx(eDB_Error, 220003, "CDBL_LangCmd::Send",
  87.                            "cannot assign params");
  88.     }
  89.     if (dbcmd(m_Cmd, (char*)(m_Query.c_str())) != SUCCEED) {
  90.         dbfreebuf(m_Cmd);
  91.         m_HasFailed = true;
  92.         throw CDB_ClientEx(eDB_Fatal, 220001, "CDBL_LangCmd::Send",
  93.                            "dbcmd failed");
  94.     }
  95.     if (dbsqlsend(m_Cmd) != SUCCEED) {
  96.         m_HasFailed = true;
  97.         throw CDB_ClientEx(eDB_Error, 220005, "CDBL_LangCmd::Send",
  98.                            "dbsqlsend failed");
  99.     }
  100.     m_WasSent = true;
  101.     m_Status = 0;
  102.     return true;
  103. }
  104. bool CDBL_LangCmd::WasSent() const
  105. {
  106.     return m_WasSent;
  107. }
  108. bool CDBL_LangCmd::Cancel()
  109. {
  110.     if (m_WasSent) {
  111.         if (m_Res) {
  112.             delete m_Res;
  113.             m_Res = 0;
  114.         }
  115.         m_WasSent = false;
  116.         return (dbcancel(m_Cmd) == SUCCEED);
  117.     }
  118.     dbfreebuf(m_Cmd);
  119.     m_Query.erase();
  120.     return true;
  121. }
  122. bool CDBL_LangCmd::WasCanceled() const
  123. {
  124.     return !m_WasSent;
  125. }
  126. CDB_Result* CDBL_LangCmd::Result()
  127. {
  128.     if (m_Res) {
  129.         if(m_RowCount < 0) {
  130.             m_RowCount = DBCOUNT(m_Cmd);
  131.         }
  132.         delete m_Res;
  133.         m_Res = 0;
  134.     }
  135.     if (!m_WasSent) {
  136.         throw CDB_ClientEx(eDB_Error, 220010, "CDBL_LangCmd::Result",
  137.                            "a command has to be sent first");
  138.     }
  139.     if (m_Status == 0) {
  140.         m_Status = 0x1;
  141.         if (dbsqlok(m_Cmd) != SUCCEED) {
  142.             m_WasSent = false;
  143.             m_HasFailed = true;
  144.             throw CDB_ClientEx(eDB_Error, 220011, "CDBL_LangCmd::Result",
  145.                                "dbsqlok failed");
  146.         }
  147.     }
  148.     if ((m_Status & 0x10) != 0) { // we do have a compute result
  149.         m_Res = new CDBL_ComputeResult(m_Cmd, &m_Status);
  150.         m_RowCount= 1;
  151.         return Create_Result(*m_Res);
  152.     }
  153.     while ((m_Status & 0x1) != 0) {
  154.         if ((m_Status & 0x20) != 0) { // check for return parameters from exec
  155.             m_Status ^= 0x20;
  156.             int n;
  157.             if ((n = dbnumrets(m_Cmd)) > 0) {
  158.                 m_Res = new CDBL_ParamResult(m_Cmd, n);
  159.                 m_RowCount= 1;
  160.                 return Create_Result(*m_Res);
  161.             }
  162.         }
  163.         if ((m_Status & 0x40) != 0) { // check for ret status
  164.             m_Status ^= 0x40;
  165.             if (dbhasretstat(m_Cmd)) {
  166.                 m_Res = new CDBL_StatusResult(m_Cmd);
  167.                 m_RowCount= 1;
  168.                 return Create_Result(*m_Res);
  169.             }
  170.         }
  171.         switch (dbresults(m_Cmd)) {
  172.         case SUCCEED:
  173.             m_Status |= 0x60;
  174.             if (DBCMDROW(m_Cmd) == SUCCEED) { // we could get rows in result
  175. // This optimization is currently unavailable for MS dblib...
  176. #ifndef MS_DBLIB_IN_USE /*Text,Image*/
  177.                 if (dbnumcols(m_Cmd) == 1) {
  178.                     int ct = dbcoltype(m_Cmd, 1);
  179.                     if ((ct == SYBTEXT) || (ct == SYBIMAGE)) {
  180.                         m_Res = new CDBL_BlobResult(m_Cmd);
  181.                     }
  182.                 }
  183. #endif
  184.                 if (!m_Res)
  185.                     m_Res = new CDBL_RowResult(m_Cmd, &m_Status);
  186.                 m_RowCount= -1;
  187.                 return Create_Result(*m_Res);
  188.             } else {
  189.                 m_RowCount = DBCOUNT(m_Cmd);
  190.                 continue;
  191.             }
  192.         case NO_MORE_RESULTS:
  193.             m_Status = 2;
  194.             break;
  195.         default:
  196.             m_HasFailed = true;
  197.             throw CDB_ClientEx(eDB_Warning, 220016, "CDBL_LangCmd::Result",
  198.                                "an error was encountered by server");
  199.         }
  200.         break;
  201.     }
  202.     m_WasSent = false;
  203.     return 0;
  204. }
  205. bool CDBL_LangCmd::HasMoreResults() const
  206. {
  207.     return m_WasSent;
  208. }
  209. void CDBL_LangCmd::DumpResults()
  210. {
  211.     CDB_Result* dbres;
  212.     while(m_WasSent) {
  213.         dbres= Result();
  214.         if(dbres) {
  215.             if(m_Connect->m_ResProc) {
  216.                 m_Connect->m_ResProc->ProcessResult(*dbres);
  217.             }
  218.             else {
  219.                 while(dbres->Fetch());
  220.             }
  221.             delete dbres;
  222.         }
  223.     }
  224. }
  225. bool CDBL_LangCmd::HasFailed() const
  226. {
  227.     return m_HasFailed;
  228. }
  229. int CDBL_LangCmd::RowCount() const
  230. {
  231.     return (m_RowCount < 0)? DBCOUNT(m_Cmd) : m_RowCount;
  232. }
  233. void CDBL_LangCmd::Release()
  234. {
  235.     m_BR = 0;
  236.     if (m_WasSent) {
  237.         Cancel();
  238.         m_WasSent = false;
  239.     }
  240.     m_Connect->DropCmd(*this);
  241.     delete this;
  242. }
  243. CDBL_LangCmd::~CDBL_LangCmd()
  244. {
  245.     if (m_BR)
  246.         *m_BR = 0;
  247.     if (m_WasSent)
  248.         Cancel();
  249. }
  250. bool CDBL_LangCmd::x_AssignParams()
  251. {
  252.     static const char s_hexnum[] = "0123456789ABCDEF";
  253.     for (unsigned int n = 0; n < m_Params.NofParams(); n++) {
  254.         if(m_Params.GetParamStatus(n) == 0) continue;
  255.         const string& name  =  m_Params.GetParamName(n);
  256.         CDB_Object&   param = *m_Params.GetParam(n);
  257.         char          val_buffer[1024];
  258.         const char*   type;
  259.         string        cmd;
  260.         if (name.length() > kDBLibMaxNameLen)
  261.             return false;
  262.         switch (param.GetType()) {
  263.         case eDB_Int:
  264.             type = "int";
  265.             break;
  266.         case eDB_SmallInt:
  267.             type = "smallint";
  268.             break;
  269.         case eDB_TinyInt:
  270.             type = "tinyint";
  271.             break;
  272.         case eDB_BigInt:
  273.             type = "numeric";
  274.             break;
  275.         case eDB_Char:
  276.         case eDB_VarChar:
  277.             type = "varchar(255)";
  278.             break;
  279.         case eDB_Binary:
  280.         case eDB_VarBinary:
  281.             type = "varbinary(255)";
  282.             break;
  283.         case eDB_Float:
  284.             type = "real";
  285.             break;
  286.         case eDB_Double:
  287.             type = "float";
  288.             break;
  289.         case eDB_SmallDateTime:
  290.             type = "smalldatetime";
  291.             break;
  292.         case eDB_DateTime:
  293.             type = "datetime";
  294.             break;
  295.         default:
  296.             return false;
  297.         }
  298.         cmd += "declare " + name + ' ' + type + "nselect " + name + " = ";
  299.         if (!param.IsNULL()) {
  300.             switch (param.GetType()) {
  301.             case eDB_Int: {
  302.                 CDB_Int& val = dynamic_cast<CDB_Int&> (param);
  303.                 sprintf(val_buffer, "%dn", val.Value());
  304.                 break;
  305.             }
  306.             case eDB_SmallInt: {
  307.                 CDB_SmallInt& val = dynamic_cast<CDB_SmallInt&> (param);
  308.                 sprintf(val_buffer, "%dn", (int) val.Value());
  309.                 break;
  310.             }
  311.             case eDB_TinyInt: {
  312.                 CDB_TinyInt& val = dynamic_cast<CDB_TinyInt&> (param);
  313.                 sprintf(val_buffer, "%dn", (int) val.Value());
  314.                 break;
  315.             }
  316.             case eDB_BigInt: {
  317.                 CDB_BigInt& val = dynamic_cast<CDB_BigInt&> (param);
  318.                 sprintf(val_buffer, "%lldn", val.Value());
  319.                 break;
  320.             }
  321.             case eDB_Char: {
  322.                 CDB_Char& val = dynamic_cast<CDB_Char&> (param);
  323.                 const char* c = val.Value(); // No more than 255 chars
  324.                 size_t i = 0;
  325.                 val_buffer[i++] = '"';
  326.                 while (*c) {
  327.                     if (*c == '"')
  328.                         val_buffer[i++] = '"';
  329.                     val_buffer[i++] = *c++;
  330.                 }
  331.                 val_buffer[i++] = '"';
  332.                 val_buffer[i++] = 'n';
  333.                 val_buffer[i] = '';
  334.                 break;
  335.             }
  336.             case eDB_VarChar: {
  337.                 CDB_VarChar& val = dynamic_cast<CDB_VarChar&> (param);
  338.                 const char* c = val.Value();
  339.                 size_t i = 0;
  340.                 val_buffer[i++] = '"';
  341.                 while (*c) {
  342.                     if (*c == '"')
  343.                         val_buffer[i++] = '"';
  344.                     val_buffer[i++] = *c++;
  345.                 }
  346.                 val_buffer[i++] = '"';
  347.                 val_buffer[i++] = 'n';
  348.                 val_buffer[i] = '';
  349.                 break;
  350.             }
  351.             case eDB_Binary: {
  352.                 CDB_Binary& val = dynamic_cast<CDB_Binary&> (param);
  353.                 const unsigned char* c = (const unsigned char*) val.Value();
  354.                 size_t i = 0, size = val.Size();
  355.                 val_buffer[i++] = '0';
  356.                 val_buffer[i++] = 'x';
  357.                 for (size_t j = 0; j < size; j++) {
  358.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  359.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  360.                 }
  361.                 val_buffer[i++] = 'n';
  362.                 val_buffer[i++] = '';
  363.                 break;
  364.             }
  365.             case eDB_VarBinary: {
  366.                 CDB_VarBinary& val = dynamic_cast<CDB_VarBinary&> (param);
  367.                 const unsigned char* c = (const unsigned char*) val.Value();
  368.                 size_t i = 0, size = val.Size();
  369.                 val_buffer[i++] = '0';
  370.                 val_buffer[i++] = 'x';
  371.                 for (size_t j = 0; j < size; j++) {
  372.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  373.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  374.                 }
  375.                 val_buffer[i++] = 'n';
  376.                 val_buffer[i++] = '';
  377.                 break;
  378.             }
  379.             case eDB_Float: {
  380.                 CDB_Float& val = dynamic_cast<CDB_Float&> (param);
  381.                 sprintf(val_buffer, "%En", (double) val.Value());
  382.                 break;
  383.             }
  384.             case eDB_Double: {
  385.                 CDB_Double& val = dynamic_cast<CDB_Double&> (param);
  386.                 sprintf(val_buffer, "%En", val.Value());
  387.                 break;
  388.             }
  389.             case eDB_SmallDateTime: {
  390.                 CDB_SmallDateTime& val =
  391.                     dynamic_cast<CDB_SmallDateTime&> (param);
  392.                 sprintf(val_buffer, "'%s'n",
  393. val.Value().AsString("M/D/Y h:m").c_str());
  394.                 break;
  395.             }
  396.             case eDB_DateTime: {
  397.                 CDB_DateTime& val =
  398.                     dynamic_cast<CDB_DateTime&> (param);
  399.                 sprintf(val_buffer, "'%s:%.3d'n",
  400. val.Value().AsString("M/D/Y h:m:s").c_str(),
  401. (int)(val.Value().NanoSecond()/1000000));
  402.                 break;
  403.             }
  404.             default:
  405.                 return false; // dummy for compiler
  406.             }
  407.             cmd += val_buffer;
  408.         } else
  409.             cmd += "NULLn";
  410.         if (dbcmd(m_Cmd, (char*) cmd.c_str()) != SUCCEED)
  411.             return false;
  412.     }
  413.     return true;
  414. }
  415. END_NCBI_SCOPE
  416. /*
  417.  * ===========================================================================
  418.  * $Log: lang_cmd.cpp,v $
  419.  * Revision 1000.1  2004/06/01 19:20:19  gouriano
  420.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.14
  421.  *
  422.  * Revision 1.14  2004/05/18 18:30:36  gorelenk
  423.  * PCH <ncbi_pch.hpp> moved to correct place .
  424.  *
  425.  * Revision 1.13  2003/06/05 16:01:13  soussov
  426.  * adds code for DumpResults and for the dumped results processing
  427.  *
  428.  * Revision 1.12  2003/05/16 20:25:20  soussov
  429.  * adds code to skip parameter if it was not set
  430.  *
  431.  * Revision 1.11  2002/07/22 20:02:59  soussov
  432.  * fixes the RowCount calculations
  433.  *
  434.  * Revision 1.10  2002/07/02 16:05:49  soussov
  435.  * splitting Sybase dblib and MS dblib
  436.  *
  437.  * Revision 1.9  2002/01/11 20:11:43  vakatov
  438.  * Fixed CVS logs from prev. revision that messed up the compilation
  439.  *
  440.  * Revision 1.8  2002/01/10 22:05:52  sapojnik
  441.  * MS-specific workarounds needed to use blobs via I_ITDescriptor
  442.  * (see Text,Image)
  443.  *
  444.  * Revision 1.7  2002/01/08 18:10:18  sapojnik
  445.  * Syabse to MSSQL name translations moved to interface_p.hpp
  446.  *
  447.  * Revision 1.6  2001/12/18 19:29:22  soussov
  448.  * adds conversion from nanosecs to milisecs for datetime args
  449.  *
  450.  * Revision 1.5  2001/12/18 17:56:53  soussov
  451.  * copy-paste bug in datetime processing fixed
  452.  *
  453.  * Revision 1.4  2001/12/18 16:47:11  soussov
  454.  * fixes bug in datetime argument processing
  455.  *
  456.  * Revision 1.3  2001/12/13 23:48:44  soussov
  457.  * inserts space after declare
  458.  *
  459.  * Revision 1.2  2001/10/24 16:41:13  lavr
  460.  * File description changed to be of the same style as in other files
  461.  *
  462.  * Revision 1.1  2001/10/22 15:19:55  lavr
  463.  * This is a major revamp (by Anton Lavrentiev, with help from Vladimir
  464.  * Soussov and Denis Vakatov) of the DBAPI "driver" libs originally
  465.  * written by Vladimir Soussov. The revamp follows the one of CTLib
  466.  * driver, and it involved massive code shuffling and grooming, numerous
  467.  * local API redesigns, adding comments and incorporating DBAPI to
  468.  * the C++ Toolkit.
  469.  *
  470.  * ===========================================================================
  471.  */