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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: cursor.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:20:49  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: cursor.cpp,v 1000.1 2004/06/01 19:20:49 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 cursor command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ftds/interfaces.hpp>
  41. BEGIN_NCBI_SCOPE
  42. /////////////////////////////////////////////////////////////////////////////
  43. //
  44. //  CTDS_CursorCmd::
  45. //
  46. CTDS_CursorCmd::CTDS_CursorCmd(CTDS_Connection* con, DBPROCESS* cmd,
  47.                                const string& cursor_name, const string& query,
  48.                                unsigned int nof_params) :
  49.     m_Connect(con), m_Cmd(cmd), m_Name(cursor_name), m_LCmd(0), m_Query(query),
  50.     m_Params(nof_params), m_IsOpen(false), m_HasFailed(false),
  51.     m_IsDeclared(false), m_Res(0), m_RowCount(-1)
  52. {
  53. }
  54. bool CTDS_CursorCmd::BindParam(const string& param_name, CDB_Object* param_ptr)
  55. {
  56.     return
  57.         m_Params.BindParam(CDB_Params::kNoParamNumber, param_name, param_ptr);
  58. }
  59. static bool for_update_of(const string& q)
  60. {
  61.     if((q.find("update") == string::npos) && 
  62.        (q.find("UPDATE") == string::npos))
  63.         return false;
  64.     if((q.find("for update") != string::npos) || 
  65.        (q.find("FOR UPDATE") != string::npos)) 
  66.         return true;
  67.     // TODO: add more logic here to find "for update" clause
  68.     return false;
  69. }
  70. CDB_Result* CTDS_CursorCmd::Open()
  71. {
  72.     if (m_IsOpen) { // need to close it first
  73.         Close();
  74.     }
  75.     m_HasFailed = false;
  76.     // declare the cursor
  77.     if (!x_AssignParams()) {
  78.         m_HasFailed = true;
  79.         throw CDB_ClientEx(eDB_Error, 222003, "CTDS_CursorCmd::Open",
  80.                            "cannot assign params");
  81.     }
  82.     m_LCmd = 0;
  83.     string cur_feat;
  84.     if(for_update_of(m_Query)) {
  85.         cur_feat= " cursor FORWARD_ONLY SCROLL_LOCKS for ";
  86.     }
  87.     else {
  88.         cur_feat= " cursor FORWARD_ONLY for ";
  89.     }
  90.         
  91.     string buff = "declare " + m_Name + cur_feat + m_Query;
  92.     try {
  93.         m_LCmd = m_Connect->LangCmd(buff);
  94.         m_LCmd->Send();
  95.         m_LCmd->DumpResults();
  96. #if 0
  97.         while (m_LCmd->HasMoreResults()) {
  98.             CDB_Result* r = m_LCmd->Result();
  99.             if (r) {
  100.                 while (r->Fetch())
  101.                     ;
  102.                 delete r;
  103.             }
  104.         }
  105. #endif
  106.         delete m_LCmd;
  107.     } catch (CDB_Exception& e) {
  108.         if (m_LCmd) {
  109.             delete m_LCmd;
  110.             m_LCmd = 0;
  111.         }
  112.         throw CDB_ClientEx(eDB_Error, 222001, "CTDS_CursorCmd::Open",
  113.                            "failed to declare cursor");
  114.     }
  115.     m_IsDeclared = true;
  116.     // open the cursor
  117.     m_LCmd = 0;
  118.     buff = "open " + m_Name;
  119.     try {
  120.         m_LCmd = m_Connect->LangCmd(buff);
  121.         m_LCmd->Send();
  122.         m_LCmd->DumpResults();
  123. #if 0
  124.         while (m_LCmd->HasMoreResults()) {
  125.             CDB_Result* r = m_LCmd->Result();
  126.             if (r) {
  127.                 while (r->Fetch())
  128.                     ;
  129.                 delete r;
  130.             }
  131.         }
  132. #endif
  133.         delete m_LCmd;
  134.     } catch (CDB_Exception& e) {
  135.         if (m_LCmd) {
  136.             delete m_LCmd;
  137.             m_LCmd = 0;
  138.         }
  139.         throw CDB_ClientEx(eDB_Error, 222002, "CTDS_CursorCmd::Open",
  140.                            "failed to open cursor");
  141.     }
  142.     m_IsOpen = true;
  143.     m_LCmd = 0;
  144.     buff = "fetch " + m_Name;
  145.     m_LCmd = m_Connect->LangCmd(buff);
  146.     m_Res = new CTDS_CursorResult(m_LCmd);
  147.     return Create_Result(*m_Res);
  148. }
  149. bool CTDS_CursorCmd::Update(const string&, const string& upd_query)
  150. {
  151.     if (!m_IsOpen)
  152.         return false;
  153.     CDB_LangCmd* cmd = 0;
  154.     try {
  155. while(m_LCmd->HasMoreResults()) {
  156.     CDB_Result* r= m_LCmd->Result();
  157.     if(r) delete r;
  158. }
  159.         string buff = upd_query + " where current of " + m_Name;
  160.         cmd = m_Connect->LangCmd(buff);
  161.         cmd->Send();
  162.         cmd->DumpResults();
  163. #if 0
  164.         while (cmd->HasMoreResults()) {
  165.             CDB_Result* r = cmd->Result();
  166.             if (r) {
  167.                 while (r->Fetch())
  168.                     ;
  169.                 delete r;
  170.             }
  171.         }
  172. #endif
  173.         delete cmd;
  174.     } catch (CDB_Exception& e) {
  175.         if (cmd)
  176.             delete cmd;
  177.         throw CDB_ClientEx(eDB_Error, 222004, "CTDS_CursorCmd::Update",
  178.                            "update failed");
  179.     }
  180.     return true;
  181. }
  182. I_ITDescriptor* CTDS_CursorCmd::x_GetITDescriptor(unsigned int item_num)
  183. {
  184.     if(!m_IsOpen || (m_Res == 0)) {
  185.         return 0;
  186.     }
  187.     while(m_Res->CurrentItemNo() < item_num) {
  188.         if(!m_Res->SkipItem()) return 0;
  189.     }
  190.     
  191.     I_ITDescriptor* desc= new CTDS_ITDescriptor(m_Cmd, item_num+1);
  192.     return desc;
  193. }
  194. bool CTDS_CursorCmd::UpdateTextImage(unsigned int item_num, CDB_Stream& data, 
  195.     bool log_it)
  196. {
  197.     I_ITDescriptor* desc= x_GetITDescriptor(item_num);
  198.     C_ITDescriptorGuard d_guard(desc);
  199.     if(desc) {
  200.         while(m_LCmd->HasMoreResults()) {
  201.             CDB_Result* r= m_LCmd->Result();
  202.             if(r) delete r;
  203.         }
  204.         
  205.         return m_Connect->x_SendData(*desc, data, log_it);
  206.     }
  207.     return false;
  208. }
  209. CDB_SendDataCmd* CTDS_CursorCmd::SendDataCmd(unsigned int item_num, size_t size, 
  210.     bool log_it)
  211. {
  212.     I_ITDescriptor* desc= x_GetITDescriptor(item_num);
  213.     C_ITDescriptorGuard d_guard(desc);
  214.     if(desc) {
  215.         m_LCmd->DumpResults();
  216. #if 0
  217.         while(m_LCmd->HasMoreResults()) {
  218.             CDB_Result* r= m_LCmd->Result();
  219.             if(r) delete r;
  220.         }
  221. #endif
  222.         
  223.         return m_Connect->SendDataCmd(*desc, size, log_it);
  224.     }
  225.     return 0;
  226. }     
  227. bool CTDS_CursorCmd::Delete(const string& table_name)
  228. {
  229.     if (!m_IsOpen)
  230.         return false;
  231.     CDB_LangCmd* cmd = 0;
  232.     try {
  233. while(m_LCmd->HasMoreResults()) {
  234.     CDB_Result* r= m_LCmd->Result();
  235.     if(r) delete r;
  236. }
  237.         string buff = "delete " + table_name + " where current of " + m_Name;
  238.         cmd = m_Connect->LangCmd(buff);
  239.         cmd->Send();
  240.         cmd->DumpResults();
  241. #if 0
  242.         while (cmd->HasMoreResults()) {
  243.             CDB_Result* r = cmd->Result();
  244.             if (r) {
  245.                 while (r->Fetch())
  246.                     ;
  247.                 delete r;
  248.             }
  249.         }
  250. #endif
  251.         delete cmd;
  252.     } catch (CDB_Exception& e) {
  253.         if (cmd)
  254.             delete cmd;
  255.         throw CDB_ClientEx(eDB_Error, 222004, "CTDS_CursorCmd::Update",
  256.                            "update failed");
  257.     }
  258.     return true;
  259. }
  260. int CTDS_CursorCmd::RowCount() const
  261. {
  262.     return m_RowCount;
  263. }
  264. bool CTDS_CursorCmd::Close()
  265. {
  266.     if (!m_IsOpen)
  267.         return false;
  268.     if (m_Res) {
  269.         delete m_Res;
  270.         m_Res = 0;
  271.     }
  272.     if (m_LCmd)
  273.         delete m_LCmd;
  274.     if (m_IsOpen) {
  275.         string buff = "close " + m_Name;
  276.         m_LCmd = 0;
  277.         try {
  278.             m_LCmd = m_Connect->LangCmd(buff);
  279.             m_LCmd->Send();
  280.             m_LCmd->DumpResults();
  281. #if 0
  282.             while (m_LCmd->HasMoreResults()) {
  283.                 CDB_Result* r = m_LCmd->Result();
  284.                 if (r) {
  285.                     while (r->Fetch())
  286.                         ;
  287.                     delete r;
  288.                 }
  289.             }
  290. #endif
  291.             delete m_LCmd;
  292.         } catch (CDB_Exception& e) {
  293.             if (m_LCmd)
  294.                 delete m_LCmd;
  295.             m_LCmd = 0;
  296.             throw CDB_ClientEx(eDB_Error, 222003, "CTDS_CursorCmd::Close",
  297.                                "failed to close cursor");
  298.         }
  299.         m_IsOpen = false;
  300.         m_LCmd = 0;
  301.     }
  302.     if (m_IsDeclared) {
  303.         string buff = "deallocate " + m_Name;
  304.         m_LCmd = 0;
  305.         try {
  306.             m_LCmd = m_Connect->LangCmd(buff);
  307.             m_LCmd->Send();
  308.             m_LCmd->DumpResults();
  309. #if 0
  310.             while (m_LCmd->HasMoreResults()) {
  311.                 CDB_Result* r = m_LCmd->Result();
  312.                 if (r) {
  313.                     while (r->Fetch())
  314.                         ;
  315.                     delete r;
  316.                 }
  317.             }
  318. #endif
  319.             delete m_LCmd;
  320.         } catch (CDB_Exception& e) {
  321.             if (m_LCmd)
  322.                 delete m_LCmd;
  323.             m_LCmd = 0;
  324.             throw CDB_ClientEx(eDB_Error, 222003, "CTDS_CursorCmd::Close",
  325.                                "failed to deallocate cursor");
  326.         }
  327.         m_IsDeclared = false;
  328.         m_LCmd = 0;
  329.     }
  330.     return true;
  331. }
  332. void CTDS_CursorCmd::Release()
  333. {
  334.     m_BR = 0;
  335.     if (m_IsOpen) {
  336.         Close();
  337.         m_IsOpen = false;
  338.     }
  339.     m_Connect->DropCmd(*this);
  340.     delete this;
  341. }
  342. CTDS_CursorCmd::~CTDS_CursorCmd()
  343. {
  344.     if (m_BR)
  345.         *m_BR = 0;
  346.     if (m_IsOpen)
  347.         Close();
  348. }
  349. bool CTDS_CursorCmd::x_AssignParams()
  350. {
  351.     static const char s_hexnum[] = "0123456789ABCDEF";
  352.     for (unsigned int n = 0; n < m_Params.NofParams(); n++) {
  353.         const string& name = m_Params.GetParamName(n);
  354.         if (name.empty())
  355.             continue;
  356.         CDB_Object& param = *m_Params.GetParam(n);
  357.         char val_buffer[16*1024];
  358.         if (!param.IsNULL()) {
  359.             switch (param.GetType()) {
  360.             case eDB_Int: {
  361.                 CDB_Int& val = dynamic_cast<CDB_Int&> (param);
  362.                 sprintf(val_buffer, "%d", val.Value());
  363.                 break;
  364.             }
  365.             case eDB_SmallInt: {
  366.                 CDB_SmallInt& val = dynamic_cast<CDB_SmallInt&> (param);
  367.                 sprintf(val_buffer, "%d", (int) val.Value());
  368.                 break;
  369.             }
  370.             case eDB_TinyInt: {
  371.                 CDB_TinyInt& val = dynamic_cast<CDB_TinyInt&> (param);
  372.                 sprintf(val_buffer, "%d", (int) val.Value());
  373.                 break;
  374.             }
  375.             case eDB_BigInt: {
  376.                 CDB_BigInt& val = dynamic_cast<CDB_BigInt&> (param);
  377.                 Int8 v8 = val.Value();
  378.                 sprintf(val_buffer, "%lld", v8);
  379.                 break;
  380.             }
  381.             case eDB_Char: {
  382.                 CDB_Char& val = dynamic_cast<CDB_Char&> (param);
  383.                 const char* c = val.Value(); // NB: 255 bytes at most
  384.                 size_t i = 0;
  385.                 val_buffer[i++] = ''';
  386.                 while (*c) {
  387.                     if (*c == ''')
  388.                         val_buffer[i++] = ''';
  389.                     val_buffer[i++] = *c++;
  390.                 }
  391.                 val_buffer[i++] = ''';
  392.                 val_buffer[i] = '';
  393.                 break;
  394.             }
  395.             case eDB_VarChar: {
  396.                 CDB_VarChar& val = dynamic_cast<CDB_VarChar&> (param);
  397.                 const char* c = val.Value(); // NB: 255 bytes at most
  398.                 size_t i = 0;
  399.                 val_buffer[i++] = ''';
  400.                 while (*c) {
  401.                     if (*c == ''')
  402.                         val_buffer[i++] = ''';
  403.                     val_buffer[i++] = *c++;
  404.                 }
  405.                 val_buffer[i++] = ''';
  406.                 val_buffer[i] = '';
  407.                 break;
  408.             }
  409.             case eDB_LongChar: {
  410.                 CDB_LongChar& val = dynamic_cast<CDB_LongChar&> (param);
  411.                 const char* c = val.Value(); // NB: 255 bytes at most
  412.                 size_t i = 0;
  413.                 val_buffer[i++] = ''';
  414.                 while (*c && (i < sizeof(val_buffer) - 2)) {
  415.                     if (*c == ''')
  416.                         val_buffer[i++] = ''';
  417.                     val_buffer[i++] = *c++;
  418.                 }
  419. if(*c != '') return false; 
  420.                 val_buffer[i++] = ''';
  421.                 val_buffer[i] = '';
  422.                 break;
  423.             }
  424.             case eDB_Binary: {
  425.                 CDB_Binary& val = dynamic_cast<CDB_Binary&> (param);
  426.                 const unsigned char* c = (const unsigned char*) val.Value();
  427.                 size_t i = 0, size = val.Size();
  428.                 val_buffer[i++] = '0';
  429.                 val_buffer[i++] = 'x';
  430.                 for (size_t j = 0; j < size; j++) {
  431.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  432.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  433.                 }
  434.                 val_buffer[i++] = '';
  435.                 break;
  436.             }
  437.             case eDB_VarBinary: {
  438.                 CDB_VarBinary& val = dynamic_cast<CDB_VarBinary&> (param);
  439.                 const unsigned char* c = (const unsigned char*) val.Value();
  440.                 size_t i = 0, size = val.Size();
  441.                 val_buffer[i++] = '0';
  442.                 val_buffer[i++] = 'x';
  443.                 for (size_t j = 0; j < size; j++) {
  444.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  445.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  446.                 }
  447.                 val_buffer[i++] = '';
  448.                 break;
  449.             }
  450.             case eDB_LongBinary: {
  451.                 CDB_LongBinary& val = dynamic_cast<CDB_LongBinary&> (param);
  452.                 const unsigned char* c = (const unsigned char*) val.Value();
  453.                 size_t i = 0, size = val.DataSize();
  454. if(size*2 > sizeof(val_buffer) - 4) return false;
  455.                 val_buffer[i++] = '0';
  456.                 val_buffer[i++] = 'x';
  457.                 for (size_t j = 0; j < size; j++) {
  458.                     val_buffer[i++] = s_hexnum[c[j] >> 4];
  459.                     val_buffer[i++] = s_hexnum[c[j] & 0x0F];
  460.                 }
  461.                 val_buffer[i++] = '';
  462.                 break;
  463.             }
  464.             case eDB_Float: {
  465.                 CDB_Float& val = dynamic_cast<CDB_Float&> (param);
  466.                 sprintf(val_buffer, "%E", (double) val.Value());
  467.                 break;
  468.             }
  469.             case eDB_Double: {
  470.                 CDB_Double& val = dynamic_cast<CDB_Double&> (param);
  471.                 sprintf(val_buffer, "%E", val.Value());
  472.                 break;
  473.             }
  474.             case eDB_SmallDateTime: {
  475.                 CDB_SmallDateTime& val =
  476.                     dynamic_cast<CDB_SmallDateTime&> (param);
  477.                 string t = val.Value().AsString("M/D/Y h:m");
  478.                 sprintf(val_buffer, "'%s'", t.c_str());
  479.                 break;
  480.             }
  481.             case eDB_DateTime: {
  482.                 CDB_DateTime& val =
  483.                     dynamic_cast<CDB_DateTime&> (param);
  484.                 string t = val.Value().AsString("M/D/Y h:m:s");
  485.                 sprintf(val_buffer, "'%s:%.3d'", t.c_str(),
  486. (int)(val.Value().NanoSecond()/1000000));
  487.                 break;
  488.             }
  489.             default:
  490.                 return false;
  491.             }
  492.         } else
  493.             strcpy(val_buffer, "NULL");
  494.         // substitute the param
  495.         g_SubstituteParam(m_Query, name, val_buffer);
  496.     }
  497.     return true;
  498. }
  499. END_NCBI_SCOPE
  500. /*
  501.  * ===========================================================================
  502.  * $Log: cursor.cpp,v $
  503.  * Revision 1000.1  2004/06/01 19:20:49  gouriano
  504.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  505.  *
  506.  * Revision 1.11  2004/05/17 21:13:37  gorelenk
  507.  * Added include of PCH ncbi_pch.hpp
  508.  *
  509.  * Revision 1.10  2003/06/05 16:01:40  soussov
  510.  * adds code for DumpResults and for the dumped results processing
  511.  *
  512.  * Revision 1.9  2003/04/29 21:15:03  soussov
  513.  * new datatypes CDB_LongChar and CDB_LongBinary added
  514.  *
  515.  * Revision 1.8  2003/02/28 23:27:24  soussov
  516.  * fixes double quote bug in char/varchar parameters substitute
  517.  *
  518.  * Revision 1.7  2002/12/03 19:18:58  soussov
  519.  * adopting the TDS8 cursors
  520.  *
  521.  * Revision 1.6  2002/05/16 21:36:45  soussov
  522.  * fixes the memory leak in text/image processing
  523.  *
  524.  * Revision 1.5  2002/03/26 15:35:10  soussov
  525.  * new image/text operations added
  526.  *
  527.  * Revision 1.4  2001/12/18 19:29:08  soussov
  528.  * adds conversion from nanosecs to milisecs for datetime args
  529.  *
  530.  * Revision 1.3  2001/12/18 17:56:38  soussov
  531.  * copy-paste bug in datetime processing fixed
  532.  *
  533.  * Revision 1.2  2001/11/06 18:00:02  lavr
  534.  * Formatted uniformly as the rest of the library
  535.  *
  536.  * Revision 1.1  2001/10/25 00:39:22  vakatov
  537.  * Initial revision
  538.  *
  539.  * ===========================================================================
  540.  */