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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: result.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:21:54  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: result.cpp,v 1000.3 2004/06/01 19:21:54 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Vladimir Soussov
  35.  *
  36.  * File Description:  DBLib Results
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/odbc/interfaces.hpp>
  41. #include <dbapi/driver/util/numeric_convert.hpp>
  42. BEGIN_NCBI_SCOPE
  43. /////////////////////////////////////////////////////////////////////////////
  44. static EDB_Type s_GetDataType(SQLSMALLINT t, SQLSMALLINT dec_digits,
  45.                               SQLUINTEGER prec)
  46. {
  47.     switch (t) {
  48.     case SQL_WCHAR:
  49.     case SQL_CHAR:         return (prec < 256)? eDB_Char : eDB_LongChar;
  50.     case SQL_WVARCHAR:
  51.     case SQL_VARCHAR:      return (prec < 256)? eDB_VarChar : eDB_LongChar;
  52.     case SQL_LONGVARCHAR:  return eDB_Text;
  53.     case SQL_LONGVARBINARY:
  54.     case SQL_WLONGVARCHAR: return eDB_Image;
  55.     case SQL_DECIMAL:
  56.     case SQL_NUMERIC:      if(prec > 20 || dec_digits > 0) return eDB_Numeric;
  57.     case SQL_BIGINT:       return eDB_BigInt;
  58.     case SQL_SMALLINT:     return eDB_SmallInt;
  59.     case SQL_INTEGER:      return eDB_Int;
  60.     case SQL_REAL:         return eDB_Float;
  61.     case SQL_FLOAT:        return eDB_Double;
  62.     case SQL_BINARY:       return (prec < 256)? eDB_Binary : eDB_LongBinary;
  63.     case SQL_BIT:          return eDB_Bit;
  64.     case SQL_TINYINT:      return eDB_TinyInt;
  65.     case SQL_VARBINARY:    return (prec < 256)? eDB_VarBinary : eDB_LongBinary;
  66.     case SQL_TYPE_TIMESTAMP:
  67.         return (prec > 16 || dec_digits > 0)? eDB_DateTime : eDB_SmallDateTime;
  68.     default:               return eDB_UnsupportedType;
  69.     }
  70. }
  71. /////////////////////////////////////////////////////////////////////////////
  72. //
  73. //  CODBC_RowResult::
  74. //
  75. CODBC_RowResult::CODBC_RowResult(SQLSMALLINT nof_cols, SQLHSTMT cmd,
  76.                                  CODBC_Reporter& r) :
  77.     m_Cmd(cmd), m_Reporter(r), m_CurrItem(-1), m_EOR(false)
  78. {
  79.     m_NofCols = nof_cols;
  80.     SQLSMALLINT actual_name_size, nullable;
  81.     m_ColFmt = new SODBC_ColDescr[m_NofCols];
  82.     for (unsigned int n = 0; n < m_NofCols; n++) {
  83.         switch(SQLDescribeCol(m_Cmd, n+1, m_ColFmt[n].ColumnName,
  84.                               ODBC_COLUMN_NAME_SIZE, &actual_name_size,
  85.                               &m_ColFmt[n].DataType, &m_ColFmt[n].ColumnSize,
  86.                               &m_ColFmt[n].DecimalDigits, &nullable)) {
  87.         case SQL_SUCCESS_WITH_INFO:
  88.             m_Reporter.ReportErrors();
  89.         case SQL_SUCCESS:
  90.             continue;
  91.         case SQL_ERROR:
  92.             m_Reporter.ReportErrors();
  93.             throw CDB_ClientEx(eDB_Error, 420020, "CODBC_RowResult::CODBC_RowResult",
  94.                                "SQLDescribeCol failed");
  95.         default:
  96.             throw CDB_ClientEx(eDB_Error, 420021, "CODBC_RowResult::CODBC_RowResult",
  97.                                "SQLDescribeCol failed (memory corruption suspected)");
  98.    }
  99. }
  100. }
  101. EDB_ResType CODBC_RowResult::ResultType() const
  102. {
  103.     return eDB_RowResult;
  104. }
  105. unsigned int CODBC_RowResult::NofItems() const
  106. {
  107.     return m_NofCols;
  108. }
  109. const char* CODBC_RowResult::ItemName(unsigned int item_num) const
  110. {
  111.     return item_num < m_NofCols ? (char*)m_ColFmt[item_num].ColumnName : 0;
  112. }
  113. size_t CODBC_RowResult::ItemMaxSize(unsigned int item_num) const
  114. {
  115.     return item_num < m_NofCols ? m_ColFmt[item_num].ColumnSize : 0;
  116. }
  117. EDB_Type CODBC_RowResult::ItemDataType(unsigned int item_num) const
  118. {
  119.     return item_num < m_NofCols ?
  120.         s_GetDataType(m_ColFmt[item_num].DataType, m_ColFmt[item_num].DecimalDigits,
  121. m_ColFmt[item_num].ColumnSize) :  eDB_UnsupportedType;
  122. }
  123. bool CODBC_RowResult::Fetch()
  124. {
  125.     m_CurrItem= -1;
  126.     if (!m_EOR) {
  127.         switch (SQLFetch(m_Cmd)) {
  128.         case SQL_SUCCESS_WITH_INFO:
  129.             m_Reporter.ReportErrors();
  130.         case SQL_SUCCESS:
  131.             m_CurrItem = 0;
  132.             return true;
  133.         case SQL_NO_DATA:
  134.             m_EOR = true;
  135.             break;
  136.         case SQL_ERROR:
  137.             m_Reporter.ReportErrors();
  138.             throw CDB_ClientEx(eDB_Error, 430003, "CODBC_RowResult::Fetch",
  139.                                "SQLFetch failed");
  140.         default:
  141.             throw CDB_ClientEx(eDB_Error, 430004, "CODBC_RowResult::Fetch",
  142.                                "SQLFetch failed (memory corruption suspected)");
  143.         }
  144.     }
  145.     return false;
  146. }
  147. int CODBC_RowResult::CurrentItemNo() const
  148. {
  149.     return m_CurrItem;
  150. }
  151. int CODBC_RowResult::xGetData(SQLSMALLINT target_type, SQLPOINTER buffer,
  152.                               SQLINTEGER buffer_size)
  153. {
  154.     SQLINTEGER f;
  155.     switch(SQLGetData(m_Cmd, m_CurrItem+1, target_type, buffer, buffer_size, &f)) {
  156.     case SQL_SUCCESS_WITH_INFO:
  157.         switch(f) {
  158.         case SQL_NO_TOTAL:
  159.             return buffer_size;
  160.         case SQL_NULL_DATA:
  161.             return 0;
  162.         default:
  163. if(f < 0)
  164. m_Reporter.ReportErrors();
  165.             return (int)f;
  166.         }
  167.     case SQL_SUCCESS:
  168.         if(target_type==SQL_C_CHAR) buffer_size--;
  169.         return (f > buffer_size)? buffer_size : (int)f;
  170.     case SQL_NO_DATA:
  171.         return 0;
  172.     case SQL_ERROR:
  173.         m_Reporter.ReportErrors();
  174.     default:
  175.         throw CDB_ClientEx(eDB_Error, 430027, "CODBC_*Result::xGetData",
  176.                                    "SQLGetData failed ");
  177.     }
  178. }
  179. static void xConvert2CDB_Numeric(CDB_Numeric* d, SQL_NUMERIC_STRUCT& s)
  180. {
  181.     swap_numeric_endian((unsigned int)s.precision, s.val);
  182.     d->Assign((unsigned int)s.precision, (unsigned int)s.scale,
  183.              s.sign == 0, s.val);
  184. }
  185. CDB_Object* CODBC_RowResult::xLoadItem(CDB_Object* item_buf)
  186. {
  187.     char buffer[8*1024];
  188.     int outlen;
  189.     switch(m_ColFmt[m_CurrItem].DataType) {
  190.     case SQL_WCHAR:
  191.     case SQL_CHAR:
  192.     case SQL_VARCHAR:
  193.     case SQL_WVARCHAR: {
  194.         switch (item_buf->GetType()) {
  195.         case eDB_VarBinary:
  196.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  197.             if ( outlen <= 0) item_buf->AssignNULL();
  198.             else ((CDB_VarBinary*) item_buf)->SetValue(buffer, outlen);
  199.             break;
  200.         case eDB_Binary:
  201.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  202.             if ( outlen <= 0) item_buf->AssignNULL();
  203.             else ((CDB_Binary*) item_buf)->SetValue(buffer, outlen);
  204.             break;
  205.         case eDB_LongBinary:
  206.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  207.             if ( outlen <= 0) item_buf->AssignNULL();
  208.             else ((CDB_LongBinary*) item_buf)->SetValue(buffer, outlen);
  209.             break;
  210.         case eDB_VarChar:
  211.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  212.             if ( outlen <= 0) item_buf->AssignNULL();
  213.             else *((CDB_VarChar*)  item_buf) = buffer;
  214.             break;
  215.         case eDB_Char:
  216.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  217.             if ( outlen <= 0) item_buf->AssignNULL();
  218.             else *((CDB_Char*)     item_buf) = buffer;
  219.             break;
  220.         case eDB_LongChar:
  221.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  222.             if ( outlen <= 0) item_buf->AssignNULL();
  223.             else *((CDB_LongChar*)     item_buf) = buffer;
  224.             break;
  225.         default:
  226.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  227.                                "Wrong type of CDB_Object");
  228.         }
  229.         break;
  230.     }
  231.     case SQL_BINARY:
  232.     case SQL_VARBINARY: {
  233.         switch ( item_buf->GetType() ) {
  234.         case eDB_VarBinary:
  235.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  236.             if ( outlen <= 0) item_buf->AssignNULL();
  237.             else ((CDB_VarBinary*) item_buf)->SetValue(buffer, outlen);
  238.             break;
  239.         case eDB_Binary:
  240.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  241.             if ( outlen <= 0) item_buf->AssignNULL();
  242.             else ((CDB_Binary*) item_buf)->SetValue(buffer, outlen);
  243.             break;
  244.         case eDB_LongBinary:
  245.             outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  246.             if ( outlen <= 0) item_buf->AssignNULL();
  247.             else ((CDB_LongBinary*) item_buf)->SetValue(buffer, outlen);
  248.             break;
  249.         case eDB_VarChar:
  250.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  251.             if (outlen <= 0) item_buf->AssignNULL();
  252.             else *((CDB_VarChar*)  item_buf) = buffer;
  253.             break;
  254.         case eDB_Char:
  255.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  256.             if (outlen <= 0) item_buf->AssignNULL();
  257.             else *((CDB_Char*) item_buf) = buffer;
  258.             break;
  259.         case eDB_LongChar:
  260.             outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  261.             if (outlen <= 0) item_buf->AssignNULL();
  262.             else *((CDB_LongChar*) item_buf) = buffer;
  263.             break;
  264.         default:
  265.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  266.                                "Wrong type of CDB_Object");
  267.         }
  268.         break;
  269.     }
  270.     case SQL_BIT: {
  271.         SQLCHAR v;
  272.         switch (  item_buf->GetType()  ) {
  273.         case eDB_Bit:
  274.             outlen= xGetData(SQL_C_BIT, &v, sizeof(SQLCHAR));
  275.             if (outlen <= 0) item_buf->AssignNULL();
  276.             else *((CDB_Bit*) item_buf) = (int) v;
  277.             break;
  278.         case eDB_TinyInt:
  279.             outlen= xGetData(SQL_C_BIT, &v, sizeof(SQLCHAR));
  280.             if (outlen <= 0) item_buf->AssignNULL();
  281.             else *((CDB_TinyInt*)  item_buf) = v ? 1 : 0;
  282.             break;
  283.         case eDB_SmallInt:
  284.             outlen= xGetData(SQL_C_BIT, &v, sizeof(SQLCHAR));
  285.             if (outlen <= 0) item_buf->AssignNULL();
  286.             else *((CDB_SmallInt*) item_buf) = v ? 1 : 0;
  287.             break;
  288.         case eDB_Int:
  289.             outlen= xGetData(SQL_C_BIT, &v, sizeof(SQLCHAR));
  290.             if (outlen <= 0) item_buf->AssignNULL();
  291.             else *((CDB_Int*)      item_buf) = v ? 1 : 0;
  292.             break;
  293.         default:
  294.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  295.                                "Wrong type of CDB_Object");
  296.         }
  297.         break;
  298.     }
  299.     case SQL_TYPE_TIMESTAMP: {
  300.         SQL_TIMESTAMP_STRUCT v;
  301.         switch ( item_buf->GetType() ) {
  302.         case eDB_SmallDateTime: {
  303.             outlen= xGetData(SQL_C_TYPE_TIMESTAMP, &v, sizeof(SQL_TIMESTAMP_STRUCT));
  304.             if (outlen <= 0) item_buf->AssignNULL();
  305.             else {
  306.                 CTime t((int)v.year, (int)v.month, (int)v.day,
  307.                         (int)v.hour, (int)v.minute, (int)v.second,
  308.                         (long)v.fraction);
  309.                 *((CDB_SmallDateTime*) item_buf)= t;
  310.             }
  311.             break;
  312.         }
  313.         case eDB_DateTime: {
  314.             outlen= xGetData(SQL_C_TYPE_TIMESTAMP, &v, sizeof(SQL_TIMESTAMP_STRUCT));
  315.             if (outlen <= 0) item_buf->AssignNULL();
  316.             else {
  317.                 CTime t((int)v.year, (int)v.month, (int)v.day,
  318.                         (int)v.hour, (int)v.minute, (int)v.second,
  319.                         (long)v.fraction);
  320.                 *((CDB_DateTime*) item_buf)= t;
  321.             }
  322.             break;
  323.         }
  324.         default:
  325.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  326.                                "Wrong type of CDB_Object");
  327.         }
  328.         break;
  329.     }
  330.     case SQL_TINYINT: {
  331.         SQLCHAR v;
  332.         switch (  item_buf->GetType()  ) {
  333.         case eDB_TinyInt:
  334.             outlen= xGetData(SQL_C_UTINYINT, &v, sizeof(SQLCHAR));
  335.             if (outlen <= 0) item_buf->AssignNULL();
  336.             else *((CDB_TinyInt*)  item_buf) = (Uint1) v;
  337.             break;
  338.         case eDB_SmallInt:
  339.             outlen= xGetData(SQL_C_UTINYINT, &v, sizeof(SQLCHAR));
  340.             if (outlen <= 0) item_buf->AssignNULL();
  341.             else *((CDB_SmallInt*) item_buf) = (Int2) v;
  342.             break;
  343.         case eDB_Int:
  344.             outlen= xGetData(SQL_C_UTINYINT, &v, sizeof(SQLCHAR));
  345.             if (outlen <= 0) item_buf->AssignNULL();
  346.             else *((CDB_Int*)      item_buf) = (Int4) v;
  347.             break;
  348.         default:
  349.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  350.                                "Wrong type of CDB_Object");
  351.         }
  352.         break;
  353.     }
  354.     case SQL_SMALLINT: {
  355.         SQLSMALLINT v;
  356.         switch (  item_buf->GetType()  ) {
  357.         case eDB_SmallInt:
  358.             outlen= xGetData(SQL_C_SSHORT, &v, sizeof(SQLSMALLINT));
  359.             if (outlen <= 0) item_buf->AssignNULL();
  360.             else *((CDB_SmallInt*) item_buf) = (Int2) v;
  361.             break;
  362.         case eDB_Int:
  363.             outlen= xGetData(SQL_C_SSHORT, &v, sizeof(SQLSMALLINT));
  364.             if (outlen <= 0) item_buf->AssignNULL();
  365.             else *((CDB_Int*) item_buf) = (Int4) v;
  366.             break;
  367.         default:
  368.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  369.                                "Wrong type of CDB_Object");
  370.         }
  371.         break;
  372.     }
  373.     case SQL_INTEGER: {
  374.         SQLINTEGER v;
  375.         switch (  item_buf->GetType()  ) {
  376.         case eDB_Int:
  377.             outlen= xGetData(SQL_C_SLONG, &v, sizeof(SQLINTEGER));
  378.             if (outlen <= 0) item_buf->AssignNULL();
  379.             else *((CDB_Int*) item_buf) = (Int4) v;
  380.             break;
  381.         default:
  382.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  383.                                "Wrong type of CDB_Object");
  384.         }
  385.         break;
  386.     }
  387.     case SQL_DOUBLE:
  388.     case SQL_FLOAT: {
  389.         SQLDOUBLE v;
  390.         switch (  item_buf->GetType()  ) {
  391.         case eDB_Double:
  392.             outlen= xGetData(SQL_C_DOUBLE, &v, sizeof(SQLDOUBLE));
  393.             if (outlen <= 0) item_buf->AssignNULL();
  394.             else *((CDB_Double*)      item_buf) = v;
  395.             break;
  396.         default:
  397.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  398.                                "Wrong type of CDB_Object");
  399.         }
  400.         break;
  401.     }
  402.     case SQL_REAL: {
  403.         SQLREAL v;
  404.         switch (  item_buf->GetType()  ) {
  405.         case eDB_Float:
  406.             outlen= xGetData(SQL_C_FLOAT, &v, sizeof(SQLREAL));
  407.             if (outlen <= 0) item_buf->AssignNULL();
  408.             else *((CDB_Float*)      item_buf) = v;
  409.             break;
  410.         default:
  411.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  412.                                "Wrong type of CDB_Object");
  413.         }
  414.         break;
  415.     }
  416.     case SQL_BIGINT:
  417.     case SQL_DECIMAL:
  418.     case SQL_NUMERIC: {
  419.         switch (  item_buf->GetType()  ) {
  420.         case eDB_Numeric: {
  421.             SQL_NUMERIC_STRUCT v;
  422. SQLHDESC hdesc;
  423. SQLGetStmtAttr(m_Cmd, SQL_ATTR_APP_ROW_DESC,&hdesc, 0, NULL);
  424. SQLSetDescField(hdesc,m_CurrItem+1,SQL_DESC_TYPE,(VOID*)SQL_C_NUMERIC,0);
  425. SQLSetDescField(hdesc,m_CurrItem+1,SQL_DESC_PRECISION,
  426. (VOID*)(m_ColFmt[m_CurrItem].ColumnSize),0);
  427. SQLSetDescField(hdesc,m_CurrItem+1,SQL_DESC_SCALE,
  428. (VOID*)(m_ColFmt[m_CurrItem].DecimalDigits),0);
  429.             outlen= xGetData(SQL_ARD_TYPE, &v, sizeof(SQL_NUMERIC_STRUCT));
  430.             if (outlen <= 0) item_buf->AssignNULL();
  431.             else xConvert2CDB_Numeric((CDB_Numeric*)item_buf, v);
  432.             break;
  433.         }
  434.         case eDB_BigInt: {
  435.             SQLBIGINT v;
  436.             outlen= xGetData(SQL_C_SBIGINT, &v, sizeof(SQLBIGINT));
  437.             if (outlen <= 0) item_buf->AssignNULL();
  438.             else *((CDB_BigInt*) item_buf) = (Int8) v;
  439.             break;
  440.         }
  441.         default:
  442.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  443.                                "Wrong type of CDB_Object");
  444.         }
  445.         break;
  446.     }
  447.     case SQL_WLONGVARCHAR:
  448.     case SQL_LONGVARBINARY:
  449.     case SQL_LONGVARCHAR: {
  450.         SQLINTEGER f;
  451.         switch(item_buf->GetType()) {
  452.         case eDB_Text: {
  453.             CDB_Stream* val = (CDB_Stream*) item_buf;
  454.             for(;;) {
  455.                 switch(SQLGetData(m_Cmd, m_CurrItem+1, SQL_C_CHAR, buffer, sizeof(buffer), &f)) {
  456.                 case SQL_SUCCESS_WITH_INFO:
  457.                     if(f == SQL_NO_TOTAL) f= sizeof(buffer) - 1;
  458.                     else if(f < 0) m_Reporter.ReportErrors();
  459.                 case SQL_SUCCESS:
  460.                     if(f > 0) {
  461.                         if(f > sizeof(buffer)-1) f= sizeof(buffer)-1;
  462.                         val->Append(buffer, f);
  463.                     }
  464.                     continue;
  465.                 case SQL_NO_DATA:
  466.                     break;
  467.                 case SQL_ERROR:
  468.                     m_Reporter.ReportErrors();
  469.                 default:
  470.                     throw CDB_ClientEx(eDB_Error, 430021, "CODBC_*Result::GetItem",
  471.                                "SQLGetData failed while retrieving text/image into CDB_Text");
  472.                 }
  473. break;
  474.             }
  475.             break;
  476.         }
  477.         case eDB_Image: {
  478.             CDB_Stream* val = (CDB_Stream*) item_buf;
  479.             for(;;) {
  480.                 switch(SQLGetData(m_Cmd, m_CurrItem+1, SQL_C_BINARY, buffer, sizeof(buffer), &f)) {
  481.                 case SQL_SUCCESS_WITH_INFO:
  482.                     if(f == SQL_NO_TOTAL || f > sizeof(buffer)) f= sizeof(buffer);
  483.                     else m_Reporter.ReportErrors();
  484.                 case SQL_SUCCESS:
  485.                     if(f > 0) {
  486.                         if(f > sizeof(buffer)) f= sizeof(buffer);
  487.                         val->Append(buffer, f);
  488.                     }
  489.                     continue;
  490.                 case SQL_NO_DATA:
  491.                     break;
  492.                 case SQL_ERROR:
  493.                     m_Reporter.ReportErrors();
  494.                 default:
  495.                     throw CDB_ClientEx(eDB_Error, 430022, "CODBC_*Result::GetItem",
  496.                                "SQLGetData failed while retrieving text/image into CDB_Image");
  497.                 }
  498. break;
  499.             }
  500.             break;
  501.         }
  502.         default:
  503.             throw CDB_ClientEx(eDB_Error, 430020, "CODBC_*Result::GetItem",
  504.                                "Wrong type of CDB_Object");
  505.         }
  506.         break;
  507.     }
  508.     default:
  509.         throw CDB_ClientEx(eDB_Error, 430025, "CODBC_*Result::GetItem",
  510.                                "Unsupported column type");
  511.     }
  512.     return item_buf;
  513. }
  514. CDB_Object* CODBC_RowResult::xMakeItem()
  515. {
  516.     char buffer[8*1024];
  517.     int outlen;
  518.     switch(m_ColFmt[m_CurrItem].DataType) {
  519.     case SQL_WCHAR:
  520.     case SQL_CHAR:
  521.     case SQL_VARCHAR:
  522.     case SQL_WVARCHAR: {
  523.         outlen= xGetData(SQL_C_CHAR, buffer, sizeof(buffer));
  524. if(m_ColFmt[m_CurrItem].ColumnSize < 256) {
  525. CDB_VarChar* val = (outlen < 0)
  526. ? new CDB_VarChar() : new CDB_VarChar(buffer, (size_t) outlen);
  527. return val;
  528. }
  529. else {
  530. CDB_LongChar* val = (outlen < 0)
  531. ? new CDB_LongChar(m_ColFmt[m_CurrItem].ColumnSize) :
  532. new CDB_LongChar(m_ColFmt[m_CurrItem].ColumnSize,
  533. buffer);
  534. return val;
  535. }
  536.     }
  537.     case SQL_BINARY:
  538.     case SQL_VARBINARY: {
  539.         outlen= xGetData(SQL_C_BINARY, buffer, sizeof(buffer));
  540. if(m_ColFmt[m_CurrItem].ColumnSize < 256) {
  541.         CDB_VarBinary* val = (outlen <= 0)
  542.         ? new CDB_VarBinary() : new CDB_VarBinary(buffer, (size_t)outlen);
  543. return val;
  544. }
  545. else {
  546. CDB_LongBinary* val = (outlen < 0)
  547. ? new CDB_LongBinary(m_ColFmt[m_CurrItem].ColumnSize) :
  548. new CDB_LongBinary(m_ColFmt[m_CurrItem].ColumnSize,
  549. buffer, (size_t) outlen);
  550. return val;
  551. }
  552.     }
  553.     case SQL_BIT: {
  554.         SQLCHAR v;
  555.         outlen= xGetData(SQL_C_BIT, &v, sizeof(SQLCHAR));
  556.         return (outlen <= 0) ? new CDB_Bit() : new CDB_Bit((int) v);
  557.     }
  558.     case SQL_TYPE_TIMESTAMP: {
  559.         SQL_TIMESTAMP_STRUCT v;
  560.         outlen= xGetData(SQL_C_TYPE_TIMESTAMP, &v, sizeof(SQL_TIMESTAMP_STRUCT));
  561.         if (outlen <= 0) {
  562.             return new CDB_SmallInt();
  563.         }
  564.         else {
  565.             CTime t((int)v.year, (int)v.month, (int)v.day,
  566.                     (int)v.hour, (int)v.minute, (int)v.second,
  567.                     (long)v.fraction);
  568.             return new CDB_DateTime(t);
  569.         }
  570.     }
  571.     case SQL_TINYINT: {
  572.         SQLCHAR v;
  573.         outlen= xGetData(SQL_C_UTINYINT, &v, sizeof(SQLCHAR));
  574.         return (outlen <= 0) ? new CDB_TinyInt() : new CDB_TinyInt((Uint1) v);
  575.     }
  576.     case SQL_SMALLINT: {
  577.         SQLSMALLINT v;
  578.         outlen= xGetData(SQL_C_SSHORT, &v, sizeof(SQLSMALLINT));
  579.         return (outlen <= 0) ? new CDB_SmallInt() : new CDB_SmallInt((Int2) v);
  580.     }
  581.     case SQL_INTEGER: {
  582.         SQLINTEGER v;
  583.         outlen= xGetData(SQL_C_SLONG, &v, sizeof(SQLINTEGER));
  584.         return (outlen <= 0) ? new CDB_Int() : new CDB_Int((Int4) v);
  585.     }
  586.     case SQL_DOUBLE:
  587.     case SQL_FLOAT: {
  588.         SQLDOUBLE v;
  589.         outlen= xGetData(SQL_C_DOUBLE, &v, sizeof(SQLDOUBLE));
  590.         return (outlen <= 0) ? new CDB_Double() : new CDB_Double(v);
  591.     }
  592.     case SQL_REAL: {
  593.         SQLREAL v;
  594.         outlen= xGetData(SQL_C_FLOAT, &v, sizeof(SQLREAL));
  595.         return (outlen <= 0) ? new CDB_Float() : new CDB_Float(v);
  596.     }
  597.     case SQL_DECIMAL:
  598.     case SQL_NUMERIC: {
  599.         if((m_ColFmt[m_CurrItem].DecimalDigits > 0) ||
  600.            (m_ColFmt[m_CurrItem].ColumnSize > 20)) { // It should be numeric
  601.             SQL_NUMERIC_STRUCT v;
  602.             outlen= xGetData(SQL_C_NUMERIC, &v, sizeof(SQL_NUMERIC_STRUCT));
  603.             CDB_Numeric* r= new CDB_Numeric;
  604.             if(outlen > 0) {
  605.                 xConvert2CDB_Numeric(r, v);
  606.             }
  607.                 return r;
  608.         }
  609.         else { // It should be bigint
  610.             SQLBIGINT v;
  611.             outlen= xGetData(SQL_C_SBIGINT, &v, sizeof(SQLBIGINT));
  612.             return (outlen <= 0) ? new CDB_BigInt() : new CDB_BigInt((Int8) v);
  613.         }
  614.     }
  615.     case SQL_WLONGVARCHAR:
  616.     case SQL_LONGVARCHAR: {
  617.         CDB_Text* val = new CDB_Text;
  618.         SQLINTEGER f;
  619.         for(;;) {
  620.             switch(SQLGetData(m_Cmd, m_CurrItem+1, SQL_C_CHAR, buffer, sizeof(buffer), &f)) {
  621.             case SQL_SUCCESS_WITH_INFO:
  622.                 if(f == SQL_NO_TOTAL) f= sizeof(buffer) - 1;
  623.                 else if(f < 0) m_Reporter.ReportErrors();
  624.             case SQL_SUCCESS:
  625.                 if(f > 0) {
  626.                     if(f > sizeof(buffer)-1) f= sizeof(buffer)-1;
  627.                     val->Append(buffer, f);
  628.                 }
  629.                 continue;
  630.             case SQL_NO_DATA:
  631.                 break;
  632.             case SQL_ERROR:
  633.                 m_Reporter.ReportErrors();
  634.             default:
  635.                 throw CDB_ClientEx(eDB_Error, 430023, "CODBC_*Result::GetItem",
  636.                                "SQLGetData failed while retrieving text into CDB_Text");
  637.             }
  638.         }
  639.         return val;
  640.     }
  641.     case SQL_LONGVARBINARY: {
  642.         CDB_Image* val = new CDB_Image;
  643.         SQLINTEGER f;
  644.         for(;;) {
  645.             switch(SQLGetData(m_Cmd, m_CurrItem+1, SQL_C_BINARY, buffer, sizeof(buffer), &f)) {
  646.             case SQL_SUCCESS_WITH_INFO:
  647.                 if(f == SQL_NO_TOTAL) f= sizeof(buffer);
  648.                 else if(f < 0) m_Reporter.ReportErrors();
  649.             case SQL_SUCCESS:
  650.                 if(f > 0) {
  651.                     if(f > sizeof(buffer)) f= sizeof(buffer);
  652.                     val->Append(buffer, f);
  653.                 }
  654.                 continue;
  655.             case SQL_NO_DATA:
  656.                 break;
  657.             case SQL_ERROR:
  658.                 m_Reporter.ReportErrors();
  659.             default:
  660.                 throw CDB_ClientEx(eDB_Error, 430024, "CODBC_*Result::GetItem",
  661.                                    "SQLGetData failed while retrieving image into CDB_Image");
  662.             }
  663.         }
  664.         return val;
  665.     }
  666.     default:
  667.         throw CDB_ClientEx(eDB_Error, 430025, "CODBC_*Result::GetItem",
  668.                                "Unsupported column type");
  669.     }
  670. }
  671. CDB_Object* CODBC_RowResult::GetItem(CDB_Object* item_buf)
  672. {
  673.     if ((unsigned int) m_CurrItem >= m_NofCols  ||  m_CurrItem == -1) {
  674.         return 0;
  675.     }
  676.     CDB_Object* item = item_buf? xLoadItem(item_buf) : xMakeItem();
  677.     ++m_CurrItem;
  678.     return item;
  679. }
  680. size_t CODBC_RowResult::ReadItem(void* buffer,size_t buffer_size,bool* is_null)
  681. {
  682.     if ((unsigned int) m_CurrItem >= m_NofCols  ||  m_CurrItem == -1 ||
  683.         buffer == 0 || buffer_size == 0) {
  684.         return 0;
  685.     }
  686.     SQLINTEGER f= 0;
  687.     if(is_null) *is_null= false;
  688.     switch(SQLGetData(m_Cmd, m_CurrItem+1, SQL_C_BINARY, buffer, buffer_size, &f)) {
  689.     case SQL_SUCCESS_WITH_INFO:
  690.         switch(f) {
  691.         case SQL_NO_TOTAL:
  692.             return buffer_size;
  693.         case SQL_NULL_DATA:
  694.             ++m_CurrItem;
  695.             if(is_null) *is_null= true;
  696.             return 0;
  697.         default:
  698.    if(f >= 0) return (f <= buffer_size)? (size_t)f : buffer_size;
  699.             m_Reporter.ReportErrors();
  700.             return 0;
  701.         }
  702.     case SQL_SUCCESS:
  703.         ++m_CurrItem;
  704.         if(f == SQL_NULL_DATA) {
  705.             if(is_null) *is_null= true;
  706.             return 0;
  707.         }
  708.         return (f >= 0)? ((size_t)f) : 0;
  709.     case SQL_NO_DATA:
  710.         ++m_CurrItem;
  711.         if(f == SQL_NULL_DATA) {
  712.             if(is_null) *is_null= true;
  713.         }
  714.         return 0;
  715.     case SQL_ERROR:
  716.         m_Reporter.ReportErrors();
  717.     default:
  718.         throw CDB_ClientEx(eDB_Error, 430026, "CODBC_*Result::ReadItem",
  719.                                    "SQLGetData failed ");
  720.     }
  721. }
  722. CDB_ITDescriptor* CODBC_RowResult::GetImageOrTextDescriptor(int item_no,
  723.                                                             const string& cond)
  724. {
  725.     char* buffer[128];
  726.     SQLSMALLINT slp;
  727.     switch(SQLColAttribute(m_Cmd, item_no+1,
  728.                            SQL_DESC_BASE_TABLE_NAME,
  729.                            (SQLPOINTER)buffer, sizeof(buffer),
  730.                            &slp, 0)) {
  731.     case SQL_SUCCESS_WITH_INFO:
  732.         m_Reporter.ReportErrors();
  733.     case SQL_SUCCESS:
  734.         break;
  735.     case SQL_ERROR:
  736.         m_Reporter.ReportErrors();
  737.         return 0;
  738.     default:
  739.         throw CDB_ClientEx(eDB_Error, 430027,
  740.                            "CODBC_*Result::GetImageOrTextDescriptor",
  741.                            "SQLColAttribute failed");
  742.     }
  743.     string base_table=(const char*)buffer;
  744.     switch(SQLColAttribute(m_Cmd, item_no+1,
  745.                            SQL_DESC_BASE_COLUMN_NAME,
  746.                            (SQLPOINTER)buffer, sizeof(buffer),
  747.                            &slp, 0)) {
  748.     case SQL_SUCCESS_WITH_INFO:
  749.         m_Reporter.ReportErrors();
  750.     case SQL_SUCCESS:
  751.         break;
  752.     case SQL_ERROR:
  753.         m_Reporter.ReportErrors();
  754.         return 0;
  755.     default:
  756.         throw CDB_ClientEx(eDB_Error, 430027,
  757.                            "CODBC_*Result::GetImageOrTextDescriptor",
  758.                            "SQLColAttribute failed");
  759.     }
  760.     string base_column=(const char*)buffer;
  761.     return new CDB_ITDescriptor(base_table, base_column, cond);
  762. }
  763. I_ITDescriptor* CODBC_RowResult::GetImageOrTextDescriptor()
  764. {
  765.     return (I_ITDescriptor*) GetImageOrTextDescriptor(m_CurrItem,
  766.                                                       "don't use me");
  767. }
  768. bool CODBC_RowResult::SkipItem()
  769. {
  770.     if ((unsigned int) m_CurrItem < m_NofCols) {
  771.         ++m_CurrItem;
  772.         return true;
  773.     }
  774.     return false;
  775. }
  776. CODBC_RowResult::~CODBC_RowResult()
  777. {
  778.     if (m_ColFmt) {
  779.         delete[] m_ColFmt;
  780.         m_ColFmt = 0;
  781.     }
  782.     if (!m_EOR)
  783.         SQLFreeStmt(m_Cmd, SQL_CLOSE);
  784. }
  785. /////////////////////////////////////////////////////////////////////////////
  786. //
  787. //  CTL_ParamResult::
  788. //  CTL_StatusResult::
  789. //  CTL_CursorResult::
  790. //
  791. EDB_ResType CODBC_StatusResult::ResultType() const
  792. {
  793.     return eDB_StatusResult;
  794. }
  795. CODBC_StatusResult::~CODBC_StatusResult()
  796. {
  797. }
  798. EDB_ResType CODBC_ParamResult::ResultType() const
  799. {
  800.     return eDB_ParamResult;
  801. }
  802. CODBC_ParamResult::~CODBC_ParamResult()
  803. {
  804. }
  805. /////////////////////////////////////////////////////////////////////////////
  806. //
  807. //  CODBC_CursorResult::
  808. //
  809. CODBC_CursorResult::CODBC_CursorResult(CODBC_LangCmd* cmd) :
  810.     m_Cmd(cmd), m_Res(0)
  811. {
  812.     try {
  813.         m_Cmd->Send();
  814. m_EOR= true;
  815.         while (m_Cmd->HasMoreResults()) {
  816.             m_Res = m_Cmd->Result();
  817.             if (m_Res && m_Res->ResultType() == eDB_RowResult) {
  818. m_EOR= false;
  819.                 return;
  820.             }
  821.             if (m_Res) {
  822.                 while (m_Res->Fetch())
  823.                     ;
  824.                 delete m_Res;
  825.                 m_Res = 0;
  826.             }
  827.         }
  828.     } catch (CDB_Exception& ) {
  829.         throw CDB_ClientEx(eDB_Error, 422010,
  830.                            "CODBC_CursorResult::CODBC_CursorResult",
  831.                            "failed to get the results");
  832.     }
  833. }
  834. EDB_ResType CODBC_CursorResult::ResultType() const
  835. {
  836.     return eDB_CursorResult;
  837. }
  838. unsigned int CODBC_CursorResult::NofItems() const
  839. {
  840.     return m_Res? m_Res->NofItems() : 0;
  841. }
  842. const char* CODBC_CursorResult::ItemName(unsigned int item_num) const
  843. {
  844.     return m_Res ? m_Res->ItemName(item_num) : 0;
  845. }
  846. size_t CODBC_CursorResult::ItemMaxSize(unsigned int item_num) const
  847. {
  848.     return m_Res ? m_Res->ItemMaxSize(item_num) : 0;
  849. }
  850. EDB_Type CODBC_CursorResult::ItemDataType(unsigned int item_num) const
  851. {
  852.     return m_Res ? m_Res->ItemDataType(item_num) : eDB_UnsupportedType;
  853. }
  854. bool CODBC_CursorResult::Fetch()
  855. {
  856. if(m_EOR) return false;
  857. try {
  858. if (m_Res && m_Res->Fetch()) return true;
  859.     } catch (CDB_Exception& ) {
  860. delete m_Res;
  861. m_Res= 0;
  862. }
  863.     try {
  864.         // finish this command
  865. m_EOR= true;
  866.         if(m_Res) {
  867. delete m_Res;
  868. while (m_Cmd->HasMoreResults()) {
  869. m_Res = m_Cmd->Result();
  870. if (m_Res) {
  871. while (m_Res->Fetch())
  872. ;
  873. delete m_Res;
  874. m_Res = 0;
  875. }
  876. }
  877. }
  878.         // send the another "fetch cursor_name" command
  879.         m_Cmd->Send();
  880.         while (m_Cmd->HasMoreResults()) {
  881.             m_Res = m_Cmd->Result();
  882.             if (m_Res && m_Res->ResultType() == eDB_RowResult) {
  883. m_EOR= false;
  884.                 return m_Res->Fetch();
  885.             }
  886.             if (m_Res) {
  887.                 while (m_Res->Fetch())
  888.                     ;
  889.                 delete m_Res;
  890.                 m_Res = 0;
  891.             }
  892.         }
  893.     } catch (CDB_Exception& ) {
  894.         throw CDB_ClientEx(eDB_Error, 422011, "CODBC_CursorResult::Fetch",
  895.                            "Failed to fetch the results");
  896.     }
  897.     return false;
  898. }
  899. int CODBC_CursorResult::CurrentItemNo() const
  900. {
  901.     return m_Res ? m_Res->CurrentItemNo() : -1;
  902. }
  903. CDB_Object* CODBC_CursorResult::GetItem(CDB_Object* item_buff)
  904. {
  905.     return m_Res ? m_Res->GetItem(item_buff) : 0;
  906. }
  907. size_t CODBC_CursorResult::ReadItem(void* buffer, size_t buffer_size,
  908.                                    bool* is_null)
  909. {
  910.     if (m_Res) {
  911.         return m_Res->ReadItem(buffer, buffer_size, is_null);
  912.     }
  913.     if (is_null)
  914.         *is_null = true;
  915.     return 0;
  916. }
  917. I_ITDescriptor* CODBC_CursorResult::GetImageOrTextDescriptor()
  918. {
  919.     return m_Res ? m_Res->GetImageOrTextDescriptor() : 0;
  920. }
  921. bool CODBC_CursorResult::SkipItem()
  922. {
  923.     return m_Res ? m_Res->SkipItem() : false;
  924. }
  925. CODBC_CursorResult::~CODBC_CursorResult()
  926. {
  927.     if (m_Res)
  928.         delete m_Res;
  929. }
  930. END_NCBI_SCOPE
  931. /*
  932.  * ===========================================================================
  933.  * $Log: result.cpp,v $
  934.  * Revision 1000.3  2004/06/01 19:21:54  gouriano
  935.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.12
  936.  *
  937.  * Revision 1.12  2004/05/17 21:16:06  gorelenk
  938.  * Added include of PCH ncbi_pch.hpp
  939.  *
  940.  * Revision 1.11  2004/01/30 20:00:39  soussov
  941.  * fixes GetItem for CDB_Numeric
  942.  *
  943.  * Revision 1.10  2003/12/09 17:35:29  sapojnik
  944.  * data sizes returned by SQLGetData() adjusted to fit within the buffer
  945.  *
  946.  * Revision 1.9  2003/12/09 15:42:15  sapojnik
  947.  * CODBC_RowResult::ReadItem(): * was missing in *is_null=false; corrected
  948.  *
  949.  * Revision 1.8  2003/11/25 20:09:06  soussov
  950.  * fixes bug in ReadItem: it did return the text/image size instead of number of bytes in buffer in some cases
  951.  *
  952.  * Revision 1.7  2003/05/08 20:30:24  soussov
  953.  * CDB_LongChar CDB_LongBinary added
  954.  *
  955.  * Revision 1.6  2003/01/31 16:51:03  lavr
  956.  * Remove unused variable "e" from catch() clause
  957.  *
  958.  * Revision 1.5  2003/01/06 16:59:20  soussov
  959.  * sets m_CurrItem = -1 for all result types if no fetch was called
  960.  *
  961.  * Revision 1.4  2003/01/03 21:48:37  soussov
  962.  * set m_CurrItem = -1 if fetch failes
  963.  *
  964.  * Revision 1.3  2003/01/02 21:05:35  soussov
  965.  * SQL_BIGINT added in CODBC_RowResult::xLoadItem
  966.  *
  967.  * Revision 1.2  2002/07/05 15:15:10  soussov
  968.  * fixes bug in ReadItem
  969.  *
  970.  *
  971.  * ===========================================================================
  972.  */