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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bcp.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:19:32  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: bcp.cpp,v 1000.1 2004/06/01 19:19:32 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 bcp-in command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. #include <dbapi/driver/util/numeric_convert.hpp>
  42. #include <string.h>
  43. BEGIN_NCBI_SCOPE
  44. /////////////////////////////////////////////////////////////////////////////
  45. //
  46. //  CTL_BCPInCmd::
  47. //
  48. CTL_BCPInCmd::CTL_BCPInCmd(CTL_Connection* con, CS_BLKDESC* cmd,
  49.                            const string& table_name, unsigned int nof_columns)
  50.     : m_Query(table_name), m_Params(nof_columns)
  51. {
  52.     m_Connect    = con;
  53.     m_Cmd        = cmd;
  54.     m_WasSent    = false;
  55.     m_HasFailed  = false;
  56.     m_Bind       = new SBcpBind[nof_columns];
  57. }
  58. bool CTL_BCPInCmd::Bind(unsigned int column_num, CDB_Object* pVal)
  59. {
  60.     return m_Params.BindParam(column_num, kEmptyStr, pVal);
  61. }
  62. bool CTL_BCPInCmd::x_AssignParams()
  63. {
  64.     CS_DATAFMT param_fmt;
  65.     memset(&param_fmt, 0, sizeof(param_fmt));
  66.     param_fmt.format = CS_FMT_UNUSED;
  67.     param_fmt.count  = 1;
  68.     for (unsigned int i = 0;  i < m_Params.NofParams();  i++) {
  69.         if (m_Params.GetParamStatus(i) == 0)
  70.             continue;
  71.         CDB_Object& param = *m_Params.GetParam(i);
  72.         m_Bind[i].indicator = param.IsNULL() ? -1 : 0;
  73.         m_Bind[i].datalen   = (m_Bind[i].indicator == 0) ? CS_UNUSED : 0;
  74.         CS_RETCODE ret_code;
  75.         switch ( param.GetType() ) {
  76.         case eDB_Int: {
  77.             CDB_Int& par = dynamic_cast<CDB_Int&> (param);
  78.             param_fmt.datatype = CS_INT_TYPE;
  79.             CS_INT value = (CS_INT) par.Value();
  80.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_INT));
  81.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  82.                                 (CS_VOID*) m_Bind[i].buffer,
  83.                                 &m_Bind[i].datalen,
  84.                                 &m_Bind[i].indicator);
  85.             break;
  86.         }
  87.         case eDB_SmallInt: {
  88.             CDB_SmallInt& par = dynamic_cast<CDB_SmallInt&> (param);
  89.             param_fmt.datatype = CS_SMALLINT_TYPE;
  90.             CS_SMALLINT value = (CS_SMALLINT) par.Value();
  91.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_SMALLINT));
  92.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  93.                                 (CS_VOID*) m_Bind[i].buffer,
  94.                                 &m_Bind[i].datalen,
  95.                                 &m_Bind[i].indicator);
  96.             break;
  97.         }
  98.         case eDB_TinyInt: {
  99.             CDB_TinyInt& par = dynamic_cast<CDB_TinyInt&> (param);
  100.             param_fmt.datatype = CS_TINYINT_TYPE;
  101.             CS_TINYINT value = (CS_TINYINT) par.Value();
  102.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_TINYINT));
  103.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  104.                                 (CS_VOID*) m_Bind[i].buffer,
  105.                                 &m_Bind[i].datalen,
  106.                                 &m_Bind[i].indicator);
  107.             break;
  108.         }
  109.         case eDB_BigInt: {
  110.             CDB_BigInt& par = dynamic_cast<CDB_BigInt&> (param);
  111.             param_fmt.datatype = CS_NUMERIC_TYPE;
  112.             CS_NUMERIC value;
  113.             Int8 val8 = par.Value();
  114.             memset(&value, 0, sizeof(value));
  115.             value.precision= 18;
  116.             if (longlong_to_numeric(val8, 18, value.array) == 0)
  117.                 return false;
  118.             param_fmt.scale     = 0;
  119.             param_fmt.precision = 18;
  120.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_NUMERIC));
  121.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  122.                                 (CS_VOID*) m_Bind[i].buffer,
  123.                                 &m_Bind[i].datalen,
  124.                                 &m_Bind[i].indicator);
  125.             break;
  126.         }
  127.         case eDB_Char: {
  128.             CDB_Char& par = dynamic_cast<CDB_Char&> (param);
  129.             param_fmt.datatype  = CS_CHAR_TYPE;
  130.             param_fmt.maxlength = (CS_INT) par.Size() + 1;
  131.             m_Bind[i].datalen   =
  132.                 (m_Bind[i].indicator == -1) ? 0 : (CS_INT) par.Size();
  133.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  134.                                 (CS_VOID*) par.Value(), &m_Bind[i].datalen,
  135.                                 &m_Bind[i].indicator);
  136.             break;
  137.         }
  138.         case eDB_VarChar: {
  139.             CDB_VarChar& par = dynamic_cast<CDB_VarChar&> (param);
  140.             param_fmt.datatype  = CS_CHAR_TYPE;
  141.             param_fmt.maxlength = (CS_INT) par.Size() + 1;
  142.             m_Bind[i].datalen   = (CS_INT) par.Size();
  143.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  144.                                 (CS_VOID*) par.Value(), &m_Bind[i].datalen,
  145.                                 &m_Bind[i].indicator);
  146.             break;
  147.         }
  148.         case eDB_Binary: {
  149.             CDB_Binary& par = dynamic_cast<CDB_Binary&> (param);
  150.             param_fmt.datatype  = CS_BINARY_TYPE;
  151.             param_fmt.maxlength = (CS_INT) par.Size() + 1;
  152.             m_Bind[i].datalen   =
  153.                 (m_Bind[i].indicator == -1) ? 0 : (CS_INT) par.Size();
  154.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  155.                                 (CS_VOID*) par.Value(), &m_Bind[i].datalen,
  156.                                 &m_Bind[i].indicator);
  157.             break;
  158.         }
  159.         case eDB_VarBinary: {
  160.             CDB_VarBinary& par = dynamic_cast<CDB_VarBinary&> (param);
  161.             param_fmt.datatype  = CS_BINARY_TYPE;
  162.             param_fmt.maxlength = (CS_INT) par.Size() + 1;
  163.             m_Bind[i].datalen   = (CS_INT) par.Size();
  164.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  165.                                 (CS_VOID*) par.Value(), &m_Bind[i].datalen,
  166.                                 &m_Bind[i].indicator);
  167.             break;
  168.         }
  169.         case eDB_Float: {
  170.             CDB_Float& par = dynamic_cast<CDB_Float&> (param);
  171.             param_fmt.datatype = CS_REAL_TYPE;
  172.             CS_REAL value = (CS_REAL) par.Value();
  173.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_REAL));
  174.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  175.                                 (CS_VOID*) m_Bind[i].buffer,
  176.                                 &m_Bind[i].datalen,
  177.                                 &m_Bind[i].indicator);
  178.             break;
  179.         }
  180.         case eDB_Double: {
  181.             CDB_Double& par = dynamic_cast<CDB_Double&> (param);
  182.             param_fmt.datatype = CS_FLOAT_TYPE;
  183.             CS_FLOAT value = (CS_FLOAT) par.Value();
  184.             memcpy(m_Bind[i].buffer, &value, sizeof(CS_FLOAT));
  185.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  186.                                 (CS_VOID*) m_Bind[i].buffer,
  187.                                 &m_Bind[i].datalen,
  188.                                 &m_Bind[i].indicator);
  189.             break;
  190.         }
  191.         case eDB_SmallDateTime: {
  192.             CDB_SmallDateTime& par = dynamic_cast<CDB_SmallDateTime&> (param);
  193.             param_fmt.datatype = CS_DATETIME4_TYPE;
  194.             CS_DATETIME4 dt;
  195.             dt.days    = par.GetDays();
  196.             dt.minutes = par.GetMinutes();
  197.             memcpy(m_Bind[i].buffer, &dt, sizeof(CS_DATETIME4));
  198.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  199.                                 (CS_VOID*) m_Bind[i].buffer,
  200.                                 &m_Bind[i].datalen,
  201.                                 &m_Bind[i].indicator);
  202.             break;
  203.         }
  204.         case eDB_DateTime: {
  205.             CDB_DateTime& par = dynamic_cast<CDB_DateTime&> (param);
  206.             param_fmt.datatype = CS_DATETIME_TYPE;
  207.             CS_DATETIME dt;
  208.             dt.dtdays = par.GetDays();
  209.             dt.dttime = par.Get300Secs();
  210.             memcpy(m_Bind[i].buffer, &dt, sizeof(CS_DATETIME));
  211.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  212.                                 (CS_VOID*) m_Bind[i].buffer,
  213.                                 &m_Bind[i].datalen,
  214.                                 &m_Bind[i].indicator);
  215.             break;
  216.         }
  217.         case eDB_Text: {
  218.             CDB_Text& par = dynamic_cast<CDB_Text&> (param);
  219.             param_fmt.datatype  = CS_TEXT_TYPE;
  220.             param_fmt.maxlength = (CS_INT) par.Size();
  221.             m_Bind[i].datalen   = (CS_INT) par.Size();
  222.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  223.                                 0, &m_Bind[i].datalen,
  224.                                 &m_Bind[i].indicator);
  225.             break;
  226.         }
  227.         case eDB_Image: {
  228.             CDB_Image& par = dynamic_cast<CDB_Image&> (param);
  229.             param_fmt.datatype  = CS_IMAGE_TYPE;
  230.             param_fmt.maxlength = (CS_INT) par.Size();
  231.             m_Bind[i].datalen   = (CS_INT) par.Size();
  232.             ret_code = blk_bind(m_Cmd, i + 1, &param_fmt,
  233.                                 0, &m_Bind[i].datalen,
  234.                                 &m_Bind[i].indicator);
  235.             break;
  236.         }
  237.         default: {
  238.             return false;
  239.         }
  240.         }
  241.         if (ret_code != CS_SUCCEED) {
  242.             return false;
  243.         }
  244.     }
  245.     return true;
  246. }
  247. bool CTL_BCPInCmd::SendRow()
  248. {
  249.     unsigned int i;
  250.     CS_INT       datalen = 0;
  251.     CS_SMALLINT  indicator = 0;
  252.     if ( !m_WasSent ) {
  253.         // we need to init the bcp
  254.         if (blk_init(m_Cmd, CS_BLK_IN, (CS_CHAR*) m_Query.c_str(), CS_NULLTERM)
  255.             != CS_SUCCEED) {
  256.             m_HasFailed = true;
  257.             throw CDB_ClientEx(eDB_Fatal, 123001, "CTL_BCPInCmd::SendRow",
  258.                                "blk_init failed");
  259.         }
  260.         m_WasSent = true;
  261.         // check what needs to be default
  262.         CS_DATAFMT fmt;
  263.         for (i = 0;  i < m_Params.NofParams();  i++) {
  264.             if (m_Params.GetParamStatus(i) != 0)
  265.                 continue;
  266.             if (blk_describe(m_Cmd, i + 1, &fmt) != CS_SUCCEED) {
  267.                 m_HasFailed = true;
  268.                 throw CDB_ClientEx(eDB_Error, 123002, "CTL_BCPInCmd::SendRow",
  269.                                    "blk_describe failed (check the number of "
  270.                                    "columns in a table)");
  271.             }
  272.             if (blk_bind(m_Cmd, i + 1, &fmt, (void*) &m_Params,
  273.                          &datalen, &indicator) != CS_SUCCEED) {
  274.                 m_HasFailed = true;
  275.                 throw CDB_ClientEx(eDB_Error, 123003, "CTL_BCPInCmd::SendRow",
  276.                                    "blk_bind failed for default value");
  277.             }
  278.         }
  279.     }
  280.     if ( !x_AssignParams() ) {
  281.         m_HasFailed = true;
  282.         throw CDB_ClientEx(eDB_Error, 123004, "CTL_BCPInCmd::SendRow",
  283.                            "cannot assign the params");
  284.     }
  285.     switch ( blk_rowxfer(m_Cmd) ) {
  286.     case CS_BLK_HAS_TEXT:  {
  287.         char buff[2048];
  288.         size_t n;
  289.         for (i = 0;  i < m_Params.NofParams();  i++) {
  290.             if (m_Params.GetParamStatus(i) == 0)
  291.                 continue;
  292.             CDB_Object& param = *m_Params.GetParam(i);
  293.             if ((param.GetType() != eDB_Text) &&
  294.                 (param.GetType() != eDB_Image)) {
  295.                 continue;
  296.             } else {
  297.                 CDB_Stream& par = dynamic_cast<CDB_Stream&> (param);
  298.                 for (datalen = (CS_INT) par.Size();  datalen > 0;
  299.                      datalen -= (CS_INT) n) {
  300.                     n = par.Read(buff, 2048);
  301.                     if (blk_textxfer(m_Cmd, (CS_BYTE*) buff, (CS_INT) n, 0)
  302.                         == CS_FAIL) {
  303.                         m_HasFailed = true;
  304.                         throw CDB_ClientEx
  305.                             (eDB_Error, 123005, "CTL_BCPInCmd::SendRow",
  306.                              "blk_textxfer failed for the text/image field");
  307.                     }
  308.                 }
  309.             }
  310.         }
  311.     }
  312.     case CS_SUCCEED:
  313.         return true;
  314.     default:
  315.         m_HasFailed = true;
  316.         throw CDB_ClientEx(eDB_Fatal, 123007,
  317.                            "CTL_BCPInCmd::SendRow", "blk_rowxfer failed");
  318.     }
  319.     return false;
  320. }
  321. bool CTL_BCPInCmd::Cancel()
  322. {
  323.     if(!m_WasSent) return false;
  324.     CS_INT outrow = 0;
  325.     switch( blk_done(m_Cmd, CS_BLK_CANCEL, &outrow) ) {
  326.     case CS_SUCCEED: m_WasSent= false; return true;
  327.     case CS_FAIL:
  328.         m_HasFailed = true;
  329.         throw CDB_ClientEx(eDB_Fatal, 123020,
  330.                            "CTL_BCPInCmd::Cancel", "blk_done failed");
  331.     default: m_WasSent = false; return false;
  332.     }
  333. }
  334. bool CTL_BCPInCmd::CompleteBatch()
  335. {
  336.     if(!m_WasSent) return false;
  337.     CS_INT outrow = 0;
  338.     switch( blk_done(m_Cmd, CS_BLK_BATCH, &outrow) ) {
  339.     case CS_SUCCEED: return (outrow > 0);
  340.     case CS_FAIL:
  341.         m_HasFailed = true;
  342.         throw CDB_ClientEx(eDB_Fatal, 123020,
  343.                            "CTL_BCPInCmd::CompleteBatch", "blk_done failed");
  344.     default: return false;
  345.     }
  346. }
  347. bool CTL_BCPInCmd::CompleteBCP()
  348. {
  349.     if(!m_WasSent) return false;
  350.     CS_INT outrow = 0;
  351.     switch( blk_done(m_Cmd, CS_BLK_ALL, &outrow) ) {
  352.     case CS_SUCCEED: m_WasSent= false; return (outrow > 0);
  353.     case CS_FAIL:
  354.         m_HasFailed = true;
  355.         throw CDB_ClientEx(eDB_Fatal, 123020,
  356.                            "CTL_BCPInCmd::CompleteBCP", "blk_done failed");
  357.     default: m_WasSent= false; return false;
  358.     }
  359. }
  360. void CTL_BCPInCmd::Release()
  361. {
  362.     m_BR = 0;
  363.     if (m_WasSent) {
  364.         try {
  365.             Cancel();
  366.         } catch (CDB_Exception& ) {}
  367.         m_WasSent = false;
  368.     }
  369.     m_Connect->DropCmd(*this);
  370.     delete this;
  371. }
  372. CTL_BCPInCmd::~CTL_BCPInCmd()
  373. {
  374.     if ( m_BR ) {
  375.         *m_BR = 0;
  376.     }
  377.     if ( m_WasSent ) {
  378.         try {
  379.             Cancel();
  380.         } catch (CDB_Exception& ) {}
  381.     }
  382.     delete[] m_Bind;
  383.     blk_drop(m_Cmd);
  384. }
  385. END_NCBI_SCOPE
  386. /*
  387.  * ===========================================================================
  388.  * $Log: bcp.cpp,v $
  389.  * Revision 1000.1  2004/06/01 19:19:32  gouriano
  390.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8
  391.  *
  392.  * Revision 1.8  2004/05/17 21:12:02  gorelenk
  393.  * Added include of PCH ncbi_pch.hpp
  394.  *
  395.  * Revision 1.7  2003/01/31 16:49:38  lavr
  396.  * Remove unused variable "e" from catch() clause
  397.  *
  398.  * Revision 1.6  2002/09/16 16:34:16  soussov
  399.  * add try catch when canceling in Release method
  400.  *
  401.  * Revision 1.5  2002/09/16 15:13:12  soussov
  402.  * throw exceptions in CompleteBCP, CompleteBatch, Cancel if blk_done fails
  403.  *
  404.  * Revision 1.4  2001/11/06 17:59:55  lavr
  405.  * Formatted uniformly as the rest of the library
  406.  *
  407.  * Revision 1.3  2001/10/11 19:10:59  soussov
  408.  * merges the text/image processing in CTL_BCPInCmd::SendRow()]
  409.  *
  410.  * Revision 1.2  2001/10/11 16:30:44  soussov
  411.  * exclude ctlib dependencies from numeric conversion calls
  412.  *
  413.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  414.  * -----  Initial (draft) revision.  -----
  415.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  416.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  417.  * The revamp involved massive code shuffling and grooming, numerous local
  418.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  419.  *
  420.  * ===========================================================================
  421.  */