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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: lang_cmd.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:20:51  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: lang_cmd.cpp,v 1000.1 2004/06/01 19:20:51 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 language command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ftds/interfaces.hpp>
  41. BEGIN_NCBI_SCOPE
  42. /////////////////////////////////////////////////////////////////////////////
  43. //
  44. //  CTDS_LangCmd::
  45. //
  46. CTDS_LangCmd::CTDS_LangCmd(CTDS_Connection* conn, DBPROCESS* cmd,
  47.                            const string& lang_query,
  48.                            unsigned int nof_params) :
  49.     m_Connect(conn), m_Cmd(cmd), m_Query(lang_query), m_Params(nof_params)
  50. {
  51.     m_WasSent   =  false;
  52.     m_HasFailed =  false;
  53.     m_Res       =  0;
  54.     m_RowCount  = -1;
  55.     m_Status    =  0;
  56. }
  57. bool CTDS_LangCmd::More(const string& query_text)
  58. {
  59.     m_Query.append(query_text);
  60.     return true;
  61. }
  62. bool CTDS_LangCmd::BindParam(const string& param_name, CDB_Object* param_ptr)
  63. {
  64.     return
  65.         m_Params.BindParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  66. }
  67. bool CTDS_LangCmd::SetParam(const string& param_name, CDB_Object* param_ptr)
  68. {
  69.     return
  70.         m_Params.SetParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  71. }
  72. bool CTDS_LangCmd::Send()
  73. {
  74.     if (m_WasSent)
  75.         Cancel();
  76.     m_HasFailed = false;
  77.     if (!x_AssignParams()) {
  78.         dbfreebuf(m_Cmd);
  79.         m_HasFailed = true;
  80.         throw CDB_ClientEx(eDB_Error, 220003, "CTDS_LangCmd::Send",
  81.                            "cannot assign params");
  82.     }
  83.     if (dbcmd(m_Cmd, (char*)(m_Query.c_str())) != SUCCEED) {
  84.         dbfreebuf(m_Cmd);
  85.         m_HasFailed = true;
  86.         throw CDB_ClientEx(eDB_Fatal, 220001, "CTDS_LangCmd::Send",
  87.                            "dbcmd failed");
  88.     }
  89.     
  90.     m_Connect->TDS_SetTimeout();
  91.     if (dbsqlsend(m_Cmd) != SUCCEED) {
  92.         m_HasFailed = true;
  93.         throw CDB_ClientEx(eDB_Error, 220005, "CTDS_LangCmd::Send",
  94.                            "dbsqlsend failed");
  95.     }
  96.     m_WasSent = true;
  97.     m_Status = 0;
  98.     return true;
  99. }
  100. bool CTDS_LangCmd::WasSent() const
  101. {
  102.     return m_WasSent;
  103. }
  104. bool CTDS_LangCmd::Cancel()
  105. {
  106.     if (m_WasSent) {
  107.         if (m_Res) {
  108.             delete m_Res;
  109.             m_Res = 0;
  110.         }
  111.         m_WasSent = false;
  112.         return (dbcancel(m_Cmd) == SUCCEED);
  113.     }
  114.     dbfreebuf(m_Cmd);
  115.     m_Query.erase();
  116.     return true;
  117. }
  118. bool CTDS_LangCmd::WasCanceled() const
  119. {
  120.     return !m_WasSent;
  121. }
  122. CDB_Result* CTDS_LangCmd::Result()
  123. {
  124.     if (m_Res) {
  125.         if(m_RowCount < 0) {
  126.             m_RowCount= DBCOUNT(m_Cmd);
  127.         }
  128.         delete m_Res;
  129.         m_Res = 0;
  130.     }
  131.     if (!m_WasSent) {
  132.         throw CDB_ClientEx(eDB_Error, 220010, "CTDS_LangCmd::Result",
  133.                            "a command has to be sent first");
  134.     }
  135.     if (m_Status == 0) {
  136.         m_Status = 0x1;
  137.         if (dbsqlok(m_Cmd) != SUCCEED) {
  138.             m_WasSent = false;
  139.             m_HasFailed = true;
  140.             throw CDB_ClientEx(eDB_Error, 220011, "CTDS_LangCmd::Result",
  141.                                "dbsqlok failed");
  142.         }
  143.     }
  144.     if ((m_Status & 0x10) != 0) { // we do have a compute result
  145.         m_Res = new CTDS_ComputeResult(m_Cmd, &m_Status);
  146.         m_RowCount= 1;
  147.         return Create_Result(*m_Res);
  148.     }
  149.     while ((m_Status & 0x1) != 0) {
  150.         switch (dbresults(m_Cmd)) {
  151.         case SUCCEED:
  152.             if (DBCMDROW(m_Cmd) == SUCCEED) { // we may get rows in this result
  153.                 m_Res = new CTDS_RowResult(m_Cmd, &m_Status);
  154.                 m_RowCount = -1;
  155.                 return Create_Result(*m_Res);
  156.             } else {
  157.                 m_RowCount = DBCOUNT(m_Cmd);
  158.                 continue;
  159.             }
  160.         case NO_MORE_RESULTS:
  161.             m_Status = 2;
  162.             break;
  163.         default:
  164.             m_HasFailed = true;
  165.             throw CDB_ClientEx(eDB_Warning, 221016, "CTDS_RPCCmd::Result",
  166.                                "error encountered in command execution");
  167.         }
  168.         break;
  169.     }
  170.     // we've done with the row results at this point
  171.     // let's look at return parameters and ret status
  172.     if (m_Status == 2) {
  173.         m_Status = 4;
  174.         int n = dbnumrets(m_Cmd);
  175.         if (n > 0) {
  176.             m_Res = new CTDS_ParamResult(m_Cmd, n);
  177.             m_RowCount = 1;
  178.             return Create_Result(*m_Res);
  179.         }
  180.     }
  181.     if (m_Status == 4) {
  182.         m_Status = 6;
  183.         if (dbhasretstat(m_Cmd)) {
  184.             m_Res = new CTDS_StatusResult(m_Cmd);
  185.             m_RowCount = 1;
  186.             return Create_Result(*m_Res);
  187.         }
  188.     }
  189.     m_WasSent = false;
  190.     return 0;
  191. }
  192. bool CTDS_LangCmd::HasMoreResults() const
  193. {
  194.     return m_WasSent;
  195. }
  196. void CTDS_LangCmd::DumpResults()
  197. {
  198.     CDB_Result* dbres;
  199.     while(m_WasSent) {
  200.         dbres= Result();
  201.         if(dbres) {
  202.             if(m_Connect->m_ResProc) {
  203.                 m_Connect->m_ResProc->ProcessResult(*dbres);
  204.             }
  205.             else {
  206.                 while(dbres->Fetch());
  207.             }
  208.             delete dbres;
  209.         }
  210.     }
  211. }
  212. bool CTDS_LangCmd::HasFailed() const
  213. {
  214.     return m_HasFailed;
  215. }
  216. int CTDS_LangCmd::RowCount() const
  217. {
  218.     return (m_RowCount < 0)? DBCOUNT(m_Cmd) : m_RowCount;
  219. }
  220. void CTDS_LangCmd::Release()
  221. {
  222.     m_BR = 0;
  223.     if (m_WasSent) {
  224.         Cancel();
  225.         m_WasSent = false;
  226.     }
  227.     m_Connect->DropCmd(*this);
  228.     delete this;
  229. }
  230. CTDS_LangCmd::~CTDS_LangCmd()
  231. {
  232.     if (m_BR)
  233.         *m_BR = 0;
  234.     if (m_WasSent)
  235.         Cancel();
  236. }
  237. bool CTDS_LangCmd::x_AssignParams()
  238. {
  239.     static const char s_hexnum[] = "0123456789ABCDEF";
  240.     for (unsigned int n = 0; n < m_Params.NofParams(); n++) {
  241.         if(m_Params.GetParamStatus(n) == 0) continue;
  242.         const string& name  =  m_Params.GetParamName(n);
  243.         CDB_Object&   param = *m_Params.GetParam(n);
  244.         char          val_buffer[16*1024];
  245.         const char*   type;
  246.         string        cmd;
  247.         if (name.length() > kTDSMaxNameLen)
  248.             return false;
  249.         switch (param.GetType()) {
  250.         case eDB_Int:
  251.             type = "int";
  252.             break;
  253.         case eDB_SmallInt:
  254.             type = "smallint";
  255.             break;
  256.         case eDB_TinyInt:
  257.             type = "tinyint";
  258.             break;
  259.         case eDB_BigInt:
  260.             type = "numeric";
  261.             break;
  262.         case eDB_Char:
  263.         case eDB_VarChar:
  264.             type = "varchar(255)";
  265.             break;
  266. case eDB_LongChar: {
  267.     CDB_LongChar& lc = dynamic_cast<CDB_LongChar&> (param);
  268.     sprintf(val_buffer, "varchar(%d)", lc.Size());
  269.     type= val_buffer;
  270. break;
  271. }
  272.         case eDB_Binary:
  273.         case eDB_VarBinary:
  274.             type = "varbinary(255)";
  275.             break;
  276. case eDB_LongBinary: {
  277.     CDB_LongBinary& lb = dynamic_cast<CDB_LongBinary&> (param);
  278. if(lb.DataSize()*2 > (sizeof(val_buffer) - 4)) return false;
  279.     sprintf(val_buffer, "varbinary(%d)", lb.Size());
  280.     type= val_buffer;
  281. break;
  282. }
  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_LongChar: {
  352.                 CDB_LongChar& val = dynamic_cast<CDB_LongChar&> (param);
  353.                 const char* c = val.Value();
  354.                 size_t i = 0;
  355.                 val_buffer[i++] = ''';
  356.                 while (*c && (i < (sizeof(val_buffer)-3))) {
  357.                     if (*c == ''')
  358.                         val_buffer[i++] = ''';
  359.                     val_buffer[i++] = *c++;
  360.                 }
  361.                 val_buffer[i++] = ''';
  362.                 val_buffer[i++] = 'n';
  363.                 val_buffer[i] = '';
  364. if(*c != '') return false;
  365.                 break;
  366.             }
  367.             case eDB_Binary: {
  368.                 CDB_Binary& val = dynamic_cast<CDB_Binary&> (param);
  369.                 const unsigned char* c = (const unsigned char*) val.Value();
  370.                 size_t i = 0, size = val.Size();
  371.                 val_buffer[i++] = '0';
  372.                 val_buffer[i++] = 'x';
  373.                 for (size_t j = 0; j < size; j++) {
  374.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  375.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  376.                 }
  377.                 val_buffer[i++] = 'n';
  378.                 val_buffer[i++] = '';
  379.                 break;
  380.             }
  381.             case eDB_VarBinary: {
  382.                 CDB_VarBinary& val = dynamic_cast<CDB_VarBinary&> (param);
  383.                 const unsigned char* c = (const unsigned char*) val.Value();
  384.                 size_t i = 0, size = val.Size();
  385.                 val_buffer[i++] = '0';
  386.                 val_buffer[i++] = 'x';
  387.                 for (size_t j = 0; j < size; j++) {
  388.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  389.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  390.                 }
  391.                 val_buffer[i++] = 'n';
  392.                 val_buffer[i++] = '';
  393.                 break;
  394.             }
  395.             case eDB_LongBinary: {
  396.                 CDB_LongBinary& val = dynamic_cast<CDB_LongBinary&> (param);
  397.                 const unsigned char* c = (const unsigned char*) val.Value();
  398.                 size_t i = 0, size = val.DataSize();
  399.                 val_buffer[i++] = '0';
  400.                 val_buffer[i++] = 'x';
  401.                 for (size_t j = 0; j < size; j++) {
  402.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  403.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  404.                 }
  405.                 val_buffer[i++] = 'n';
  406.                 val_buffer[i++] = '';
  407.                 break;
  408.             }
  409.             case eDB_Float: {
  410.                 CDB_Float& val = dynamic_cast<CDB_Float&> (param);
  411.                 sprintf(val_buffer, "%En", (double) val.Value());
  412.                 break;
  413.             }
  414.             case eDB_Double: {
  415.                 CDB_Double& val = dynamic_cast<CDB_Double&> (param);
  416.                 sprintf(val_buffer, "%En", val.Value());
  417.                 break;
  418.             }
  419.             case eDB_SmallDateTime: {
  420.                 CDB_SmallDateTime& val =
  421.                     dynamic_cast<CDB_SmallDateTime&> (param);
  422.                 sprintf(val_buffer, "'%s'n",val.Value().AsString("M/D/Y h:m").c_str());
  423.                 break;
  424.             }
  425.             case eDB_DateTime: {
  426.                 CDB_DateTime& val =
  427.                     dynamic_cast<CDB_DateTime&> (param);
  428.                 sprintf(val_buffer,  "'%s:%.3d'n",   val.Value().AsString("M/D/Y h:m:s").c_str(),
  429. (int)(val.Value().NanoSecond()/1000000));
  430.                 break;
  431.             }
  432.             default:
  433.                 return false; // dummy for compiler
  434.             }
  435.             cmd += val_buffer;
  436.         } else
  437.             cmd += "NULLn";
  438.         if (dbcmd(m_Cmd, (char*) cmd.c_str()) != SUCCEED)
  439.             return false;
  440.     }
  441.     return true;
  442. }
  443. END_NCBI_SCOPE
  444. /*
  445.  * ===========================================================================
  446.  * $Log: lang_cmd.cpp,v $
  447.  * Revision 1000.1  2004/06/01 19:20:51  gouriano
  448.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  449.  *
  450.  * Revision 1.13  2004/05/17 21:13:37  gorelenk
  451.  * Added include of PCH ncbi_pch.hpp
  452.  *
  453.  * Revision 1.12  2003/06/05 16:01:40  soussov
  454.  * adds code for DumpResults and for the dumped results processing
  455.  *
  456.  * Revision 1.11  2003/05/16 20:26:09  soussov
  457.  * adds code to skip parameter if it was not set
  458.  *
  459.  * Revision 1.10  2003/04/29 21:15:03  soussov
  460.  * new datatypes CDB_LongChar and CDB_LongBinary added
  461.  *
  462.  * Revision 1.9  2002/09/19 22:28:20  soussov
  463.  * changs order of result processing
  464.  *
  465.  * Revision 1.8  2002/07/22 20:11:07  soussov
  466.  * fixes the RowCount calculations
  467.  *
  468.  * Revision 1.7  2002/01/14 20:38:49  soussov
  469.  * timeout support for tds added
  470.  *
  471.  * Revision 1.6  2001/12/18 19:29:08  soussov
  472.  * adds conversion from nanosecs to milisecs for datetime args
  473.  *
  474.  * Revision 1.5  2001/12/18 17:56:39  soussov
  475.  * copy-paste bug in datetime processing fixed
  476.  *
  477.  * Revision 1.4  2001/12/18 16:42:44  soussov
  478.  * fixes bug in datetime argument processing
  479.  *
  480.  * Revision 1.3  2001/12/13 23:40:53  soussov
  481.  * changes double quotes to single quotes in SQL queries
  482.  *
  483.  * Revision 1.2  2001/11/06 18:00:02  lavr
  484.  * Formatted uniformly as the rest of the library
  485.  *
  486.  * Revision 1.1  2001/10/25 00:39:22  vakatov
  487.  * Initial revision
  488.  *
  489.  * ===========================================================================
  490.  */