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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: result.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:19:47  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.18
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: result.cpp,v 1000.1 2004/06/01 19:19:47 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 Results
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. #include <dbapi/driver/util/numeric_convert.hpp>
  42. BEGIN_NCBI_SCOPE
  43. /////////////////////////////////////////////////////////////////////////////
  44. //
  45. //  CTL_RowResult::
  46. //
  47. CTL_RowResult::CTL_RowResult(CS_COMMAND* cmd)
  48.     : m_Cmd(cmd),
  49.       m_CurrItem(-1),
  50.       m_EOR(false)
  51. {
  52.     CS_INT outlen;
  53.     CS_INT nof_cols;
  54.     if (ct_res_info(m_Cmd, CS_NUMDATA, &nof_cols, CS_UNUSED, &outlen)
  55.         != CS_SUCCEED) {
  56.         throw CDB_ClientEx(eDB_Error, 130001, "::CTL_RowResult",
  57.                            "ct_res_info(CS_NUMDATA) failed");
  58.     }
  59.     m_NofCols = nof_cols;
  60.     CS_INT cmd_num;
  61.     if (ct_res_info(m_Cmd, CS_CMD_NUMBER, &cmd_num, CS_UNUSED, &outlen)
  62.         != CS_SUCCEED) {
  63.         throw CDB_ClientEx(eDB_Error, 130001, "::CTL_RowResult",
  64.                            "ct_res_info(CS_CMD_NUMBER) failed");
  65.     }
  66.     m_CmdNum = cmd_num;
  67. CS_INT bind_len= 0;
  68. m_BindedCols= 0;
  69.     m_ColFmt = new CS_DATAFMT[m_NofCols];
  70.     for (unsigned int nof_items = 0;  nof_items < m_NofCols;  nof_items++) {
  71.         if (ct_describe(m_Cmd, (CS_INT) nof_items + 1, &m_ColFmt[nof_items])
  72.             != CS_SUCCEED) {
  73.             throw CDB_ClientEx(eDB_Error, 130002, "::CTL_RowResult",
  74.                                "ct_describe failed");
  75.         }
  76. bind_len+= m_ColFmt[nof_items].maxlength;
  77. if(bind_len <= 2048) m_BindedCols++;
  78.     }
  79. if(m_BindedCols) {
  80.     m_BindItem= new CS_VOID*[m_BindedCols];
  81. m_Copied= new CS_INT[m_BindedCols];
  82. m_Indicator= new CS_SMALLINT[m_BindedCols];
  83. for(int i= 0; i < m_BindedCols; i++) {
  84.   m_BindItem[i]= i? ((unsigned char*)(m_BindItem[i-1])) + m_ColFmt[i-1].maxlength : m_BindBuff;
  85.   if(ct_bind(m_Cmd, i+1, &m_ColFmt[i], m_BindItem[i], &m_Copied[i], &m_Indicator[i]) 
  86.  != CS_SUCCEED) {
  87.             throw CDB_ClientEx(eDB_Error, 130042, "::CTL_RowResult",
  88.                                "ct_bind failed");
  89.   }
  90. }
  91. }
  92. }
  93. EDB_ResType CTL_RowResult::ResultType() const
  94. {
  95.     return eDB_RowResult;
  96. }
  97. unsigned int CTL_RowResult::NofItems() const
  98. {
  99.     return m_NofCols;
  100. }
  101. const char* CTL_RowResult::ItemName(unsigned int item_num) const
  102. {
  103.     return (item_num < m_NofCols  &&  m_ColFmt[item_num].namelen > 0)
  104.         ? m_ColFmt[item_num].name : 0;
  105. }
  106. size_t CTL_RowResult::ItemMaxSize(unsigned int item_num) const
  107. {
  108.     return (item_num < m_NofCols) ? m_ColFmt[item_num].maxlength : 0;
  109. }
  110. EDB_Type CTL_RowResult::ItemDataType(unsigned int item_num) const
  111. {
  112.     if (item_num >= m_NofCols) {
  113.         return eDB_UnsupportedType;
  114.     }
  115.     const CS_DATAFMT& fmt = m_ColFmt[item_num];
  116.     switch ( fmt.datatype ) {
  117.     case CS_BINARY_TYPE:    return eDB_VarBinary;
  118.     case CS_BIT_TYPE:       return eDB_Bit;
  119.     case CS_CHAR_TYPE:      return eDB_VarChar;
  120.     case CS_DATETIME_TYPE:  return eDB_DateTime;
  121.     case CS_DATETIME4_TYPE: return eDB_SmallDateTime;
  122.     case CS_TINYINT_TYPE:   return eDB_TinyInt;
  123.     case CS_SMALLINT_TYPE:  return eDB_SmallInt;
  124.     case CS_INT_TYPE:       return eDB_Int;
  125.     case CS_DECIMAL_TYPE:
  126.     case CS_NUMERIC_TYPE:   return (fmt.scale == 0  &&  fmt.precision < 20)
  127.                                 ? eDB_BigInt : eDB_Numeric;
  128.     case CS_FLOAT_TYPE:     return eDB_Double;
  129.     case CS_REAL_TYPE:      return eDB_Float;
  130.     case CS_TEXT_TYPE:      return eDB_Text;
  131.     case CS_IMAGE_TYPE:     return eDB_Image;
  132. case CS_LONGCHAR_TYPE:  return eDB_LongChar;
  133. case CS_LONGBINARY_TYPE: return eDB_LongBinary;
  134.     }
  135.     return eDB_UnsupportedType;
  136. }
  137. bool CTL_RowResult::Fetch()
  138. {
  139.     m_CurrItem = -1;
  140.     if ( m_EOR ) {
  141.         return false;
  142.     }
  143.     switch ( ct_fetch(m_Cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, 0) ) {
  144.     case CS_SUCCEED:
  145.         m_CurrItem = 0;
  146.         return true;
  147.     case CS_END_DATA:
  148.         m_EOR = true;
  149.         return false;
  150.     case CS_ROW_FAIL:
  151.         throw CDB_ClientEx(eDB_Error, 130003, "CTL_RowResult::Fetch",
  152.                            "error while fetching the row");
  153.     case CS_FAIL:
  154.         throw CDB_ClientEx(eDB_Error, 130006, "CTL_RowResult::Fetch",
  155.                            "ct_fetch has failed. "
  156.                            "You need to cancel the command");
  157.     case CS_CANCELED:
  158.         throw CDB_ClientEx(eDB_Error, 130004, "CTL_RowResult::Fetch",
  159.                            "the command has been canceled");
  160.     default:
  161.         throw CDB_ClientEx(eDB_Error, 130005, "CTL_RowResult::Fetch",
  162.                            "the connection is busy");
  163.     }
  164. }
  165. int CTL_RowResult::CurrentItemNo() const
  166. {
  167.     return m_CurrItem;
  168. }
  169. CS_RETCODE CTL_RowResult::my_ct_get_data(CS_COMMAND* cmd, CS_INT item, 
  170.  CS_VOID* buffer, 
  171.  CS_INT buflen, CS_INT *outlen)
  172. {
  173.   if(item > m_BindedCols)
  174. return ct_get_data(cmd, item, buffer, buflen, outlen);
  175.   --item;
  176.   if((m_Indicator[item] < 0) || ((CS_INT)m_Indicator[item] >= m_Copied[item])) {
  177. if(outlen) *outlen= 0;
  178. return CS_END_ITEM;
  179.   }
  180.   if(!buffer || (buflen < 1)) return CS_SUCCEED;
  181.   CS_INT n= m_Copied[item] - m_Indicator[item];
  182.   if(buflen > n) buflen= n;
  183.   memcpy(buffer, (char*)(m_BindItem[item]) + m_Indicator[item], buflen);
  184.   if(outlen) *outlen= buflen;
  185.   m_Indicator[item]+= buflen;
  186.   return (n == buflen)? CS_END_ITEM : CS_SUCCEED;
  187. }
  188. // Aux. for CTL_RowResult::GetItem()
  189. CDB_Object* CTL_RowResult::s_GetItem(CS_COMMAND* cmd, CS_INT item_no, CS_DATAFMT& fmt,
  190.  CDB_Object* item_buf)
  191. {
  192.     CS_INT outlen = 0;
  193.     char buffer[2048];
  194.     EDB_Type b_type = item_buf ? item_buf->GetType() : eDB_UnsupportedType;
  195.     switch ( fmt.datatype ) {
  196.     case CS_BINARY_TYPE: {
  197.         if (item_buf  &&
  198.             b_type != eDB_VarBinary  &&  b_type != eDB_Binary  &&
  199.             b_type != eDB_VarChar    &&  b_type != eDB_Char &&
  200. b_type != eDB_LongChar   &&  b_type != eDB_LongBinary) {
  201.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  202.                                "Wrong type of CDB_Object");
  203.         }
  204.         char* v = (fmt.maxlength < (CS_INT) sizeof(buffer))
  205.             ? buffer : new char[fmt.maxlength + 1];
  206.         switch ( my_ct_get_data(cmd, item_no, v, fmt.maxlength, &outlen) ) {
  207.         case CS_SUCCEED:
  208.         case CS_END_ITEM:
  209.         case CS_END_DATA: {
  210.             if ( item_buf ) {
  211.                 switch ( b_type ) {
  212.                 case eDB_VarBinary:
  213.                     ((CDB_VarBinary*) item_buf)->SetValue(v, outlen);
  214.                     break;
  215.                 case eDB_Binary:
  216.                     ((CDB_Binary*)    item_buf)->SetValue(v, outlen);
  217.                     break;
  218.                 case eDB_VarChar:
  219.                     v[outlen] = '';
  220.                     *((CDB_VarChar*)  item_buf) = v;
  221.                     break;
  222.                 case eDB_Char:
  223.                     v[outlen] = '';
  224.                     *((CDB_Char*)     item_buf) = v;
  225.                     break;
  226.                 case eDB_LongChar:
  227.                     v[outlen] = '';
  228.                     *((CDB_LongChar*)     item_buf) = v;
  229.                     break;
  230.                 case eDB_LongBinary:
  231.                     ((CDB_LongBinary*)     item_buf)->SetValue(v, outlen);
  232.                     break;
  233.                 default:
  234.                     break;
  235.                 }
  236.                 if (v != buffer)  delete[] v;
  237.                 return item_buf;
  238.             }
  239.             CDB_VarBinary* val = (outlen == 0)
  240.                 ? new CDB_VarBinary() : new CDB_VarBinary(v, outlen);
  241.             if ( v != buffer)  delete[] v;
  242.             return val;
  243.         }
  244.         case CS_CANCELED:
  245.             if (v != buffer)  delete[] v;
  246.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  247.                                "the command has been canceled");
  248.         default:
  249.             if (v != buffer)  delete[] v;
  250.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  251.                                "ct_get_data failed");
  252.         }
  253.     }
  254.     case CS_LONGBINARY_TYPE: {
  255.         if (item_buf  &&
  256. b_type != eDB_LongChar   &&  b_type != eDB_LongBinary) {
  257.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  258.                                "Wrong type of CDB_Object");
  259.         }
  260.         char* v = (fmt.maxlength < (CS_INT) sizeof(buffer))
  261.             ? buffer : new char[fmt.maxlength + 1];
  262.         switch ( my_ct_get_data(cmd, item_no, v, fmt.maxlength, &outlen) ) {
  263.         case CS_SUCCEED:
  264.         case CS_END_ITEM:
  265.         case CS_END_DATA: {
  266.             if ( item_buf ) {
  267.                 switch ( b_type ) {
  268.                 case eDB_LongBinary:
  269.                     ((CDB_LongBinary*) item_buf)->SetValue(v, outlen);
  270.                     break;
  271. case eDB_LongChar:
  272.                     v[outlen] = '';
  273.                     *((CDB_LongChar*)     item_buf) = v;
  274.                 default:
  275.                     break;
  276.                 }
  277.                 if (v != buffer)  delete[] v;
  278.                 return item_buf;
  279.             }
  280.             CDB_LongBinary* val = (outlen == 0)
  281.                 ? new CDB_LongBinary(fmt.maxlength) : 
  282.       new CDB_LongBinary(fmt.maxlength, v, outlen);
  283.             if ( v != buffer)  delete[] v;
  284.             return val;
  285.         }
  286.         case CS_CANCELED:
  287.             if (v != buffer)  delete[] v;
  288.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  289.                                "the command has been canceled");
  290.         default:
  291.             if (v != buffer)  delete[] v;
  292.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  293.                                "ct_get_data failed");
  294.         }
  295.     }
  296.     case CS_BIT_TYPE: {
  297.         if (item_buf  &&
  298.             b_type != eDB_Bit       &&  b_type != eDB_TinyInt  &&
  299.             b_type != eDB_SmallInt  &&  b_type != eDB_Int) {
  300.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  301.                                "Wrong type of CDB_Object");
  302.         }
  303.         CS_BIT v;
  304.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  305.         case CS_SUCCEED:
  306.         case CS_END_ITEM:
  307.         case CS_END_DATA: {
  308.             if ( item_buf ) {
  309.                 if (outlen == 0) {
  310.                     item_buf->AssignNULL();
  311.                 }
  312.                 else {
  313.                     switch ( b_type ) {
  314.                     case eDB_Bit:
  315.                         *((CDB_Bit*)      item_buf) = (int) v;
  316.                         break;
  317.                     case eDB_TinyInt:
  318.                         *((CDB_TinyInt*)  item_buf) = v ? 1 : 0;
  319.                         break;
  320.                     case eDB_SmallInt:
  321.                         *((CDB_SmallInt*) item_buf) = v ? 1 : 0;
  322.                         break;
  323.                     case eDB_Int:
  324.                         *((CDB_Int*)      item_buf) = v ? 1 : 0;
  325.                         break;
  326.                     default:
  327.                         break;
  328.                     }
  329.                 }
  330.                 return item_buf;
  331.             }
  332.             return (outlen == 0) ? new CDB_Bit() : new CDB_Bit((int) v);
  333.         }
  334.         case CS_CANCELED: {
  335.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  336.                                "the command has been canceled");
  337.         }
  338.         default: {
  339.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  340.                                "ct_get_data failed");
  341.         }
  342.         }
  343.     }
  344.     case CS_CHAR_TYPE: {
  345.         if (item_buf  &&
  346.             b_type != eDB_VarBinary  &&  b_type != eDB_Binary  &&
  347.             b_type != eDB_VarChar    &&  b_type != eDB_Char &&
  348. b_type != eDB_LongChar   &&  b_type != eDB_LongBinary) {
  349.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  350.                                "Wrong type of CDB_Object");
  351.         }
  352.         char* v = fmt.maxlength < 2048
  353.             ? buffer : new char[fmt.maxlength + 1];
  354.         switch ( my_ct_get_data(cmd, item_no, v, fmt.maxlength, &outlen) ) {
  355.         case CS_SUCCEED:
  356.         case CS_END_ITEM:
  357.         case CS_END_DATA: {
  358.             v[outlen] = '';
  359.             if ( item_buf) {
  360.                 if ( outlen <= 0) {
  361.                     item_buf->AssignNULL();
  362.                 }
  363.                 else {
  364.                     switch ( b_type ) {
  365.                     case eDB_VarChar:
  366.                         *((CDB_VarChar*)  item_buf) = v;
  367.                         break;
  368.                     case eDB_Char:
  369.                         *((CDB_Char*)     item_buf) = v;
  370.                         break;
  371.                     case eDB_LongChar:
  372.                         *((CDB_LongChar*)     item_buf) = v;
  373.                         break;
  374.                     case eDB_VarBinary:
  375.                         ((CDB_VarBinary*) item_buf)->SetValue(v, outlen);
  376.                         break;
  377.                     case eDB_Binary:
  378.                         ((CDB_Binary*)    item_buf)->SetValue(v, outlen);
  379.                         break;
  380.                     case eDB_LongBinary:
  381.                         ((CDB_LongBinary*)    item_buf)->SetValue(v, outlen);
  382.                         break;
  383.                     default:
  384.                         break;
  385.                     }
  386.                 }
  387.                 if ( v != buffer) delete[] v;
  388.                 return item_buf;
  389.             }
  390.             CDB_VarChar* val = (outlen == 0)
  391.                 ? new CDB_VarChar() : new CDB_VarChar(v, (size_t) outlen);
  392.             if (v != buffer) delete[] v;
  393.             return val;
  394.         }
  395.         case CS_CANCELED: {
  396.             if (v != buffer) delete[] v;
  397.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  398.                                "the command has been canceled");
  399.         }
  400.         default: {
  401.             if (v != buffer) delete[] v;
  402.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  403.                                "ct_get_data failed");
  404.         }
  405.         }
  406.     }
  407.     case CS_LONGCHAR_TYPE: {
  408.         if (item_buf  &&
  409. b_type != eDB_LongChar   &&  b_type != eDB_LongBinary) {
  410.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  411.                                "Wrong type of CDB_Object");
  412.         }
  413.         char* v = fmt.maxlength < 2048
  414.             ? buffer : new char[fmt.maxlength + 1];
  415.         switch ( my_ct_get_data(cmd, item_no, v, fmt.maxlength, &outlen) ) {
  416.         case CS_SUCCEED:
  417.         case CS_END_ITEM:
  418.         case CS_END_DATA: {
  419.             v[outlen] = '';
  420.             if ( item_buf) {
  421.                 if ( outlen <= 0) {
  422.                     item_buf->AssignNULL();
  423.                 }
  424.                 else {
  425.                     switch ( b_type ) {
  426.                     case eDB_LongChar:
  427.                         *((CDB_LongChar*)     item_buf) = v;
  428.                         break;
  429.                     case eDB_LongBinary:
  430.                         ((CDB_LongBinary*)    item_buf)->SetValue(v, outlen);
  431.                         break;
  432.                     default:
  433.                         break;
  434.                     }
  435.                 }
  436.                 if ( v != buffer) delete[] v;
  437.                 return item_buf;
  438.             }
  439.             CDB_LongChar* val = (outlen == 0)
  440.                 ? new CDB_LongChar(fmt.maxlength) : new CDB_LongChar((size_t) outlen, v);
  441.             if (v != buffer) delete[] v;
  442.             return val;
  443.         }
  444.         case CS_CANCELED: {
  445.             if (v != buffer) delete[] v;
  446.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  447.                                "the command has been canceled");
  448.         }
  449.         default: {
  450.             if (v != buffer) delete[] v;
  451.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  452.                                "ct_get_data failed");
  453.         }
  454.         }
  455.     }
  456.     case CS_DATETIME_TYPE: {
  457.         if (item_buf  &&  b_type != eDB_DateTime) {
  458.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  459.                                "Wrong type of CDB_Object");
  460.         }
  461.         CS_DATETIME v;
  462.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  463.         case CS_SUCCEED:
  464.         case CS_END_ITEM:
  465.         case CS_END_DATA: {
  466.             if ( item_buf) {
  467.                 if ( outlen > 0) {
  468.                     ((CDB_DateTime*)item_buf)->Assign(v.dtdays, v.dttime);
  469.                 }
  470.                 else {
  471.                     item_buf->AssignNULL();
  472.                 }
  473.                 return item_buf;
  474.             }
  475.             CDB_DateTime* val;
  476.             if ( outlen > 0) {
  477.                 val = new CDB_DateTime(v.dtdays, v.dttime);
  478.             } else {
  479.                 val = new CDB_DateTime;
  480.             }
  481.             return val;
  482.         }
  483.         case CS_CANCELED: {
  484.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  485.                                "the command has been canceled");
  486.         }
  487.         default: {
  488.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  489.                                "ct_get_data failed");
  490.         }
  491.         }
  492.     }
  493.     case CS_DATETIME4_TYPE:  {
  494.         if (item_buf  &&
  495.             b_type != eDB_SmallDateTime  &&  b_type != eDB_DateTime) {
  496.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  497.                                "Wrong type of CDB_Object");
  498.         }
  499.         CS_DATETIME4 v;
  500.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  501.         case CS_SUCCEED:
  502.         case CS_END_ITEM:
  503.         case CS_END_DATA: {
  504.             if ( item_buf) {
  505.                 if (outlen > 0) {
  506.                     switch ( b_type ) {
  507.                     case eDB_SmallDateTime:
  508.                         ((CDB_SmallDateTime*) item_buf)->Assign
  509.                             (v.days, v.minutes);
  510.                         break;
  511.                     case eDB_DateTime:
  512.                         ((CDB_DateTime*)      item_buf)->Assign
  513.                             (v.days, v.minutes * 60 * 300);
  514.                         break;
  515.                     default:
  516.                         break;
  517.                     }
  518.                 }
  519.                 else {
  520.                     item_buf->AssignNULL();
  521.                 }
  522.                 return item_buf;
  523.             }
  524.             return (outlen <= 0)
  525.                 ? new CDB_SmallDateTime
  526.                 : new CDB_SmallDateTime(v.days, v.minutes);
  527.         }
  528.         case CS_CANCELED: {
  529.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  530.                                "the command has been canceled");
  531.         }
  532.         default: {
  533.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  534.                                "ct_get_data failed");
  535.         }
  536.         }
  537.     }
  538.     case CS_TINYINT_TYPE: {
  539.         if (item_buf  &&
  540.             b_type != eDB_TinyInt  &&  b_type != eDB_SmallInt  &&
  541.             b_type != eDB_Int) {
  542.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  543.                                "Wrong type of CDB_Object");
  544.         }
  545.         CS_TINYINT v;
  546.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  547.         case CS_SUCCEED:
  548.         case CS_END_ITEM:
  549.         case CS_END_DATA: {
  550.             if ( item_buf ) {
  551.                 if (outlen == 0) {
  552.                     item_buf->AssignNULL();
  553.                 }
  554.                 else {
  555.                     switch ( b_type ) {
  556.                     case eDB_TinyInt:
  557.                         *((CDB_TinyInt*)  item_buf) = (Uint1) v;
  558.                         break;
  559.                     case eDB_SmallInt:
  560.                         *((CDB_SmallInt*) item_buf) = (Int2) v;
  561.                         break;
  562.                     case eDB_Int:
  563.                         *((CDB_Int*)      item_buf) = (Int4) v;
  564.                         break;
  565.                     default:
  566.                         break;
  567.                     }
  568.                 }
  569.                 return item_buf;
  570.             }
  571.             return (outlen == 0)
  572.                 ? new CDB_TinyInt() : new CDB_TinyInt((Uint1) v);
  573.         }
  574.         case CS_CANCELED: {
  575.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  576.                                "the command has been canceled");
  577.         }
  578.         default: {
  579.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  580.                                "ct_get_data failed");
  581.         }
  582.         }
  583.     }
  584.     case CS_SMALLINT_TYPE: {
  585.         if (item_buf  &&
  586.             b_type != eDB_SmallInt  &&  b_type != eDB_Int) {
  587.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  588.                                "Wrong type of CDB_Object");
  589.         }
  590.         CS_SMALLINT v;
  591.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  592.         case CS_SUCCEED:
  593.         case CS_END_ITEM:
  594.         case CS_END_DATA: {
  595.             if ( item_buf ) {
  596.                 if (outlen == 0) {
  597.                     item_buf->AssignNULL();
  598.                 }
  599.                 else {
  600.                     switch ( b_type ) {
  601.                     case eDB_SmallInt:
  602.                         *((CDB_SmallInt*) item_buf) = (Int2) v;
  603.                         break;
  604.                     case eDB_Int:
  605.                         *((CDB_Int*)      item_buf) = (Int4) v;
  606.                         break;
  607.                     default:
  608.                         break;
  609.                     }
  610.                 }
  611.                 return item_buf;
  612.             }
  613.             return (outlen == 0)
  614.                 ? new CDB_SmallInt() : new CDB_SmallInt((Int2) v);
  615.         }
  616.         case CS_CANCELED: {
  617.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  618.                                "the command has been canceled");
  619.         }
  620.         default: {
  621.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  622.                                "ct_get_data failed");
  623.         }
  624.         }
  625.     }
  626.     case CS_INT_TYPE: {
  627.         if (item_buf  &&  b_type != eDB_Int) {
  628.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  629.                                "Wrong type of CDB_Object");
  630.         }
  631.         CS_INT v;
  632.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  633.         case CS_SUCCEED:
  634.         case CS_END_ITEM:
  635.         case CS_END_DATA: {
  636.             if ( item_buf ) {
  637.                 if (outlen == 0) {
  638.                     item_buf->AssignNULL();
  639.                 }
  640.                 else {
  641.                     *((CDB_Int*) item_buf) = (Int4) v;
  642.                 }
  643.                 return item_buf;
  644.             }
  645.             return (outlen == 0) ? new CDB_Int() : new CDB_Int((Int4) v);
  646.         }
  647.         case CS_CANCELED: {
  648.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  649.                                "the command has been canceled");
  650.         }
  651.         default: {
  652.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  653.                                "ct_get_data failed");
  654.         }
  655.         }
  656.     }
  657.     case CS_DECIMAL_TYPE:
  658.     case CS_NUMERIC_TYPE: {
  659.         if (item_buf  &&  b_type != eDB_BigInt  &&  b_type != eDB_Numeric) {
  660.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  661.                                "Wrong type of CDB_Object");
  662.         }
  663.         CS_NUMERIC v;
  664.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  665.         case CS_SUCCEED:
  666.         case CS_END_ITEM:
  667.         case CS_END_DATA: {
  668.             if ( item_buf ) {
  669.                 if (outlen < 3) { /* it used to be == 0 but ctlib on windows
  670.      returns 2 even for NULL numeric */
  671.                     item_buf->AssignNULL();
  672.                 }
  673.                 else {
  674.                     if (b_type == eDB_Numeric) {
  675.                         ((CDB_Numeric*) item_buf)->Assign
  676.                             ((unsigned int)         v.precision,
  677.                              (unsigned int)         v.scale,
  678.                              (const unsigned char*) v.array);
  679.                     }
  680.                     else {
  681.                         *((CDB_BigInt*) item_buf) =
  682.                             numeric_to_longlong((unsigned int)
  683.                                                 v.precision, v.array);
  684.                     }
  685.                 }
  686.                 return item_buf;
  687.             }
  688.             if (fmt.scale == 0  &&  fmt.precision < 20) {
  689.                 return (outlen == 0)
  690.                     ? new CDB_BigInt
  691.                     : new CDB_BigInt(numeric_to_longlong((unsigned int)
  692.                                                          v.precision,v.array));
  693.             } else {
  694.                 return  (outlen == 0)
  695.                     ? new CDB_Numeric
  696.                     : new CDB_Numeric((unsigned int)         v.precision,
  697.                                       (unsigned int)         v.scale,
  698.                                       (const unsigned char*) v.array);
  699.             }
  700.         }
  701.         case CS_CANCELED: {
  702.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  703.                                "the command has been canceled");
  704.         }
  705.         default: {
  706.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  707.                                "ct_get_data failed");
  708.         }
  709.         }
  710.     }
  711.     case CS_FLOAT_TYPE: {
  712.         if (item_buf  &&  b_type != eDB_Double) {
  713.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  714.                                "Wrong type of CDB_Object");
  715.         }
  716.         CS_FLOAT v;
  717.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  718.         case CS_SUCCEED:
  719.         case CS_END_ITEM:
  720.         case CS_END_DATA: {
  721.             if ( item_buf ) {
  722.                 if (outlen == 0) {
  723.                     item_buf->AssignNULL();
  724.                 }
  725.                 else {
  726.                     *((CDB_Double*) item_buf) = (double) v;
  727.                 }
  728.                 return item_buf;
  729.             }
  730.             return (outlen == 0)
  731.                 ? new CDB_Double() : new CDB_Double((double) v);
  732.         }
  733.         case CS_CANCELED: {
  734.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  735.                                "the command has been canceled");
  736.         }
  737.         default: {
  738.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  739.                                "ct_get_data failed");
  740.         }
  741.         }
  742.     }
  743.     case CS_REAL_TYPE: {
  744.         if (item_buf  &&  b_type != eDB_Float) {
  745.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  746.                                "Wrong type of CDB_Object");
  747.         }
  748.         CS_REAL v;
  749.         switch ( my_ct_get_data(cmd, item_no, &v, (CS_INT) sizeof(v), &outlen) ) {
  750.         case CS_SUCCEED:
  751.         case CS_END_ITEM:
  752.         case CS_END_DATA: {
  753.             if ( item_buf ) {
  754.                 if (outlen == 0) {
  755.                     item_buf->AssignNULL();
  756.                 }
  757.                 else {
  758.                     *((CDB_Float*) item_buf) = (float) v;
  759.                 }
  760.                 return item_buf;
  761.             }
  762.             return (outlen == 0) ? new CDB_Float() : new CDB_Float((float) v);
  763.         }
  764.         case CS_CANCELED: {
  765.             throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  766.                                "the command has been canceled");
  767.         }
  768.         default: {
  769.             throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  770.                                "ct_get_data failed");
  771.         }
  772.         }
  773.     }
  774.     case CS_TEXT_TYPE:
  775.     case CS_IMAGE_TYPE: {
  776.        if (item_buf  &&  b_type != eDB_Text  &&  b_type != eDB_Image) {
  777.             throw CDB_ClientEx(eDB_Error, 130020, "CTL_***Result::GetItem",
  778.                                "Wrong type of CDB_Object");
  779.         }
  780.         CDB_Stream* val =
  781.             item_buf                         ? (CDB_Stream*) item_buf
  782.             : (fmt.datatype == CS_TEXT_TYPE) ? (CDB_Stream*) new CDB_Text
  783.             :                                  (CDB_Stream*) new CDB_Image;
  784.         for (;;) {
  785.             switch ( my_ct_get_data(cmd, item_no, buffer, 2048, &outlen) ) {
  786.             case CS_SUCCEED:
  787.                 if (outlen != 0)
  788.                     val->Append(buffer, outlen);
  789.                 continue;
  790.             case CS_END_ITEM:
  791.             case CS_END_DATA:
  792.                 if (outlen != 0)
  793.                     val->Append(buffer, outlen);
  794.                 return val;
  795.             case CS_CANCELED:
  796.                 throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  797.                                    "the command has been canceled");
  798.             default:
  799.                 throw CDB_ClientEx(eDB_Error, 130000, "CTL_***Result::GetItem",
  800.                                    "ct_get_data failed");
  801.             }
  802.         }
  803.     }
  804.     default: {
  805.         throw CDB_ClientEx(eDB_Error, 130004, "CTL_***Result::GetItem",
  806.                            "unexpected result type");
  807.     }
  808.     }
  809. }
  810. CDB_Object* CTL_RowResult::GetItem(CDB_Object* item_buf)
  811. {
  812.     if ((unsigned int) m_CurrItem >= m_NofCols  ||  m_CurrItem == -1) {
  813.         return 0;
  814.     }
  815.     CDB_Object* item = s_GetItem(m_Cmd, m_CurrItem + 1, m_ColFmt[m_CurrItem],
  816.                                  item_buf);
  817.     ++m_CurrItem;
  818.     return item;
  819. }
  820. size_t CTL_RowResult::ReadItem(void* buffer, size_t buffer_size,
  821.                                bool* is_null)
  822. {
  823.     if ((unsigned int) m_CurrItem >= m_NofCols  ||  m_CurrItem == -1) {
  824.         return 0;
  825.     }
  826.     CS_INT outlen = 0;
  827.     if((buffer == 0) && (buffer_size == 0)) {
  828. buffer= (void*)(&buffer_size);
  829.     }
  830.     switch ( my_ct_get_data(m_Cmd, m_CurrItem+1, buffer, (CS_INT) buffer_size,
  831.                          &outlen) ) {
  832.     case CS_END_ITEM:
  833.     case CS_END_DATA:
  834.         ++m_CurrItem;
  835.     case CS_SUCCEED:
  836.         break;
  837.     case CS_CANCELED:
  838.         throw CDB_ClientEx(eDB_Error, 130004, "CTL_RowResult::ReadItem",
  839.                            "the command has been canceled");
  840.     default:
  841.         throw CDB_ClientEx(eDB_Error, 130000, "CTL_RowResult::ReadItem",
  842.                            "ct_get_data failed");
  843.     }
  844.     if ( is_null ) {
  845.         *is_null = (outlen == 0);
  846.     }
  847.     return (size_t) outlen;
  848. }
  849. I_ITDescriptor* CTL_RowResult::GetImageOrTextDescriptor()
  850. {
  851.     if ((unsigned int) m_CurrItem >= m_NofCols  ||  m_CurrItem == -1) {
  852.         return 0;
  853.     }
  854.     char dummy[4];
  855.     switch ( my_ct_get_data(m_Cmd, m_CurrItem+1, dummy, 0, 0) ) {
  856.     case CS_END_ITEM:
  857.     case CS_END_DATA:
  858.     case CS_SUCCEED:
  859.         break;
  860.     case CS_CANCELED:
  861.         throw CDB_ClientEx(eDB_Error, 130004,
  862.                            "CTL_RowResult::GetImageOrTextDescriptor",
  863.                            "the command has been canceled");
  864.     default:
  865.         throw CDB_ClientEx(eDB_Error, 130000,
  866.                            "CTL_RowResult::GetImageOrTextDescriptor",
  867.                            "ct_get_data failed");
  868.     }
  869.     CTL_ITDescriptor* desc = new CTL_ITDescriptor;
  870.     if (ct_data_info(m_Cmd, CS_GET, m_CurrItem+1, &desc->m_Desc)
  871.         != CS_SUCCEED) {
  872.         delete desc;
  873.         throw CDB_ClientEx(eDB_Error, 130010,
  874.                            "CTL_RowResult::GetImageOrTextDescriptor",
  875.                            "ct_data_info failed");
  876.     }
  877.     return desc;
  878. }
  879. bool CTL_RowResult::SkipItem()
  880. {
  881.     if (m_CurrItem < (int) m_NofCols) {
  882.         ++m_CurrItem;
  883.         return true;
  884.     }
  885.     return false;
  886. }
  887. CTL_RowResult::~CTL_RowResult()
  888. {
  889.     if ( m_ColFmt ) {
  890.         delete[] m_ColFmt;
  891.     }
  892. if(m_BindedCols) {
  893.   delete [] m_BindItem;
  894.   delete [] m_Copied;
  895.   delete [] m_Indicator;
  896. }
  897.     if ( m_EOR ) {
  898.         return;
  899.     }
  900.     switch (ct_cancel(NULL, m_Cmd, CS_CANCEL_CURRENT)) {
  901.     case CS_SUCCEED:
  902.     case CS_CANCELED:
  903.         break;
  904.     default:
  905.         CS_INT err_code = 130007;
  906.         ct_cmd_props(m_Cmd, CS_SET, CS_USERDATA,
  907.                      &err_code, (CS_INT) sizeof(err_code), 0);
  908.     }
  909. }
  910. /////////////////////////////////////////////////////////////////////////////
  911. //
  912. //  CTL_ParamResult::
  913. //  CTL_ComputeResult::
  914. //  CTL_StatusResult::
  915. //  CTL_CursorResult::
  916. //
  917. EDB_ResType CTL_ParamResult::ResultType() const
  918. {
  919.     return eDB_ParamResult;
  920. }
  921. EDB_ResType CTL_ComputeResult::ResultType() const
  922. {
  923.     return eDB_ComputeResult;
  924. }
  925. EDB_ResType CTL_StatusResult::ResultType() const
  926. {
  927.     return eDB_StatusResult;
  928. }
  929. EDB_ResType CTL_CursorResult::ResultType() const
  930. {
  931.     return eDB_CursorResult;
  932. }
  933. bool CTL_CursorResult::SkipItem()
  934. {
  935.     if (m_CurrItem < (int) m_NofCols) {
  936.         ++m_CurrItem;
  937. char dummy[4];
  938. switch ( my_ct_get_data(m_Cmd, m_CurrItem, dummy, 0, 0) ) {
  939. case CS_END_ITEM:
  940. case CS_END_DATA:
  941. case CS_SUCCEED:
  942.     break;
  943. case CS_CANCELED:
  944.     throw CDB_ClientEx(eDB_Error, 130004,
  945.        "CTL_CursorResult::SkipItem",
  946.        "the command has been canceled");
  947. default:
  948.     throw CDB_ClientEx(eDB_Error, 130000,
  949.        "CTL_CursorResult::SkipItem",
  950.        "ct_get_data failed");
  951. }
  952.         return true;
  953.     }
  954.     return false;
  955. }
  956. CTL_CursorResult::~CTL_CursorResult()
  957. {
  958.     if (m_EOR) { // this is not a bug
  959.         CS_INT res_type;
  960.         while (ct_results(m_Cmd, &res_type) == CS_SUCCEED) {
  961.             continue;
  962.         }
  963.     }
  964.     else m_EOR= true; // to prevent ct_cancel call (close cursor will do a job)
  965. }
  966. /////////////////////////////////////////////////////////////////////////////
  967. //
  968. //  CTL_ITDescriptor::
  969. //
  970. CTL_ITDescriptor::CTL_ITDescriptor()
  971. {
  972.     return;
  973. }
  974. int CTL_ITDescriptor::DescriptorType() const
  975. {
  976.     return CTL_ITDESCRIPTOR_TYPE_MAGNUM;
  977. }
  978. CTL_ITDescriptor::~CTL_ITDescriptor()
  979. {
  980.     return;
  981. }
  982. END_NCBI_SCOPE
  983. /*
  984.  * ===========================================================================
  985.  * $Log: result.cpp,v $
  986.  * Revision 1000.1  2004/06/01 19:19:47  gouriano
  987.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.18
  988.  *
  989.  * Revision 1.18  2004/05/17 21:12:03  gorelenk
  990.  * Added include of PCH ncbi_pch.hpp
  991.  *
  992.  * Revision 1.17  2003/04/29 21:15:35  soussov
  993.  * new datatypes CDB_LongChar and CDB_LongBinary added
  994.  *
  995.  * Revision 1.16  2003/04/21 20:18:14  soussov
  996.  * Buffering fetched result to avoid ct_get_data performance issue
  997.  *
  998.  * Revision 1.15  2003/01/03 21:47:42  soussov
  999.  * set m_CurrItem = -1 if fetch failes
  1000.  *
  1001.  * Revision 1.14  2002/11/27 17:09:50  soussov
  1002.  * patch to fix NULL numeric related bug in ctlib for Windows
  1003.  *
  1004.  * Revision 1.13  2002/03/26 15:34:38  soussov
  1005.  * new image/text operations added
  1006.  *
  1007.  * Revision 1.12  2002/02/06 22:24:43  soussov
  1008.  * fixes the arguments order in numeric assign
  1009.  *
  1010.  * Revision 1.11  2002/01/04 19:41:46  soussov
  1011.  * allows usage ReadItem(0, 0)
  1012.  *
  1013.  * Revision 1.10  2001/11/06 18:02:00  lavr
  1014.  * Added methods formely inline (moved from header files)
  1015.  *
  1016.  * Revision 1.9  2001/10/11 16:30:44  soussov
  1017.  * exclude ctlib dependencies from numeric conversion calls
  1018.  *
  1019.  * Revision 1.8  2001/10/03 14:21:01  soussov
  1020.  * pevents the ct_cancel call in ~CTL_CursorResult()
  1021.  *
  1022.  * Revision 1.7  2001/10/02 22:14:50  soussov
  1023.  * fixed bug in ~CTL_CursorResult()
  1024.  *
  1025.  * Revision 1.6  2001/10/01 19:27:40  soussov
  1026.  * Fixed typo in ~CTL_CursorResult
  1027.  *
  1028.  * Revision 1.5  2001/10/01 19:13:56  soussov
  1029.  * Eliminates double deletes in results destructor
  1030.  *
  1031.  * Revision 1.4  2001/09/27 23:01:07  vakatov
  1032.  * CTL_***Result::  virtual methods' implementation moved away from the header
  1033.  *
  1034.  * Revision 1.3  2001/09/27 20:08:33  vakatov
  1035.  * Added "DB_" (or "I_") prefix where it was missing
  1036.  *
  1037.  * Revision 1.2  2001/09/26 23:23:31  vakatov
  1038.  * Moved the err.message handlers' stack functionality (generic storage
  1039.  * and methods) to the "abstract interface" level.
  1040.  *
  1041.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  1042.  * -----  Initial (draft) revision.  -----
  1043.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  1044.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  1045.  * The revamp involved massive code shuffling and grooming, numerous local
  1046.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  1047.  *
  1048.  * ===========================================================================
  1049.  */