Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

CTBodbcStatement.cxx

Go to the documentation of this file.
00001 //
00002 // $Id: CTBodbcStatement.cxx,v 1.12 2000/02/29 12:50:10 mueller Exp $
00003 //
00004 /*----------------------------------------------------------------------------*/
00005 /* C Tool Box: Designed and implemented by:                                   */
00006 /*    Walter F.J. Mueller   Gesellschaft fuer Schwerionenforschung (GSI)      */
00007 /*                          Planckstrasse 1, D-64291 Darmstadt, Germany       */
00008 /*                  Email:  W.F.J.Mueller@gsi.de                              */
00009 /*                  WWW:    http://www-kp3.gsi.de/www/kp3/people/mueller.html */
00010 /*------------------------------------------+---------------------------------*/
00011 #include <string.h>
00012 
00013 #include "CTB.hxx"
00014 #include "CTBprintf.hxx"
00015 #include "CTBcarray.hxx"
00016 #include "CTBodbc.hxx"
00017 #include "CTBodbcConnect.hxx"
00018 #include "CTBodbcStatement.hxx"
00019 
00025 //------------------------------------------+-----------------------------------
00027 
00028 CTBodbcStatement::CTBodbcStatement(CTBodbcConnect& dbc)
00029   : m_dbc(dbc),
00030     m_hstmt(0)
00031 {
00032 }
00033 
00034 //------------------------------------------+-----------------------------------
00036 
00037 CTBodbcStatement::~CTBodbcStatement()
00038 {
00039   RETCODE   i_rc;
00040 
00041   if (m_hstmt != 0) {
00042     i_rc = SQLFreeStmt (m_hstmt,SQL_DROP);
00043     m_dbc.TraceODBCCall("CTBodbcStatement::~CTBodbcStatement->SQLFreeStmt",i_rc);
00044   }
00045 }
00046 
00047 //------------------------------------------+-----------------------------------
00049 
00050 bool CTBodbcStatement::Prepare(const char* c_stmt)
00051 {
00052   RETCODE   i_rc;
00053 
00054   if (!AllocIfNull()) return false;
00055   
00056   i_rc = SQLPrepare (m_hstmt,(UCHAR *) c_stmt,SQL_NTS);
00057   m_dbc.TraceODBCCall("CTBodbcStatement::Prepare->SQLPrepare",i_rc);
00058 
00059   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00060     PrintError(cerr);
00061     return false;
00062   }
00063   
00064   return true;
00065 }
00066 
00067 //------------------------------------------+-----------------------------------
00069 
00070 bool CTBodbcStatement::Execute()
00071 {
00072   RETCODE   i_rc;
00073 
00074   if (!AllocIfNull()) return false;
00075   
00076   i_rc = SQLExecute(m_hstmt);
00077   m_dbc.TraceODBCCall("CTBodbcStatement::Execute->SQLExecute",i_rc);
00078 
00079   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00080     PrintError(cerr);
00081     return false;
00082   }
00083   
00084   return true;
00085 }
00086 
00087 //------------------------------------------+-----------------------------------
00089 
00090 bool CTBodbcStatement::Fetch()
00091 {
00092   RETCODE   i_rc;
00093 
00094   if (!AllocIfNull()) return false;
00095   
00096   i_rc = SQLFetch(m_hstmt);
00097   m_dbc.TraceODBCCall("CTBodbcStatement::Fetch->SQLFetch",i_rc);
00098 
00099   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00100     PrintError(cerr);
00101     return false;
00102   }
00103   
00104   return true;
00105 }
00106 
00107 //------------------------------------------+-----------------------------------
00109 
00110 bool CTBodbcStatement::Close()
00111 {
00112   RETCODE   i_rc;
00113 
00114   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00115   
00116   i_rc = SQLFreeStmt (m_hstmt,SQL_CLOSE);
00117   m_dbc.TraceODBCCall("CTBodbcStatement::Close->SQLFreeStmt",i_rc);
00118 
00119   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00120     PrintError(cerr);
00121     return false;
00122   }
00123   
00124   return true;
00125 }
00126 
00127 //------------------------------------------+-----------------------------------
00129 
00130 bool CTBodbcStatement::UnbindParameter()
00131 {
00132   RETCODE   i_rc;
00133 
00134   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00135   
00136   i_rc = SQLFreeStmt(m_hstmt,SQL_RESET_PARAMS);
00137   m_dbc.TraceODBCCall("CTBodbcStatement::UnbindParameter->SQLFreeStmt",i_rc);
00138 
00139   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00140     PrintError(cerr);
00141     return false;
00142   }
00143   
00144   return true;
00145 }
00146 
00147 //------------------------------------------+-----------------------------------
00149 
00150 bool CTBodbcStatement::UnbindCol()
00151 {
00152   RETCODE   i_rc;
00153 
00154   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00155   
00156   i_rc = SQLFreeStmt(m_hstmt,SQL_UNBIND);
00157   m_dbc.TraceODBCCall("CTBodbcStatement::UnbindCol->SQLFreeStmt",i_rc);
00158 
00159   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00160     PrintError(cerr);
00161     return false;
00162   }  
00163   
00164   return true;
00165 }
00166 
00167 //------------------------------------------+-----------------------------------
00169 
00170 bool CTBodbcStatement::NumResultCols(int& i_ncol)
00171 {
00172   RETCODE   i_rc;
00173   SWORD     i_l_ncol = 0;
00174 
00175   i_ncol = 0;                               // init to zero ...
00176   
00177   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00178 
00179   i_rc = SQLNumResultCols(m_hstmt,&i_l_ncol);
00180   m_dbc.TraceODBCCall("CTBodbcStatement::NumResultCols->SQLNumResultCols",i_rc);
00181   if (i_rc != SQL_SUCCESS) {
00182     PrintError(cerr);
00183     return false;
00184   }
00185 
00186   i_ncol = i_l_ncol;
00187   return true;
00188 }
00189 
00190 //------------------------------------------+-----------------------------------
00192 
00202 bool CTBodbcStatement::DescribeCol(int i_icol, char* c_colname,
00203                                    int i_size, SWORD& i_sqltype,
00204                                    int& i_precision, int& i_scale,
00205                                    bool& b_nullable)
00206 {
00207   RETCODE   i_rc;
00208   SWORD     i_l_sqltype   = 0;
00209   UDWORD    i_l_precision = 0;
00210   SWORD     i_l_scale     = 0;
00211   SWORD     i_l_nullable  = SQL_NULLABLE_UNKNOWN;
00212 
00213   if (i_size > 0) c_colname[0] = 0;         // init all
00214   i_sqltype   = 0;
00215   i_precision = 0;
00216   i_scale     = 0;
00217   b_nullable  = true;
00218 
00219   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00220 
00221   i_rc = SQLDescribeCol(m_hstmt,i_icol,(UCHAR*) c_colname,i_size,0,
00222                         &i_l_sqltype,&i_l_precision,&i_l_scale,&i_l_nullable);
00223   m_dbc.TraceODBCCall("CTBodbcStatement::DescribeCol->SQLDescribeCol",i_rc);
00224   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00225     PrintError(cerr);
00226     return false;
00227   }
00228 
00229   i_sqltype   = i_l_sqltype;
00230   i_precision = i_l_precision;
00231   i_scale     = i_l_scale;
00232   b_nullable  = (i_l_nullable != SQL_NO_NULLS);
00233 
00234   return true;
00235 }
00236 
00237 //------------------------------------------+-----------------------------------
00239 
00245 bool CTBodbcStatement::FetchToStream(ostream& os,
00246                                      int i_format, int i_maxrow = 0)
00247 {
00248   static const int dim_col = 255;           // handle at most 255 columns
00249   int       i_ncol;
00250   int       i_nrow = 0;
00251   char      c_sep  = 0;                     // separator character
00252 
00253   CTBcarray<CTBcstring<256>,dim_col+1> c_colname;
00254   CTBcarray<int,dim_col+1>             i_coltype;
00255   SWORD     i_sqltype;
00256   int       i_precision;
00257   int       i_scale;
00258   bool      b_nullable;
00259 
00260   enum {
00261     e_bad = 0,
00262     e_int,
00263     e_double,
00264     e_char,
00265     e_date    
00266   };
00267 
00268   if (m_hstmt == 0) return true;            // is a noop if still unused ...
00269 
00270   if (!NumResultCols(i_ncol)) return false;
00271   if (i_ncol >= dim_col) i_ncol = dim_col;
00272 
00273   switch (i_format) {                       // setup separator character
00274   case format_bsv:
00275   case format_bsvh:
00276     c_sep = ' ';
00277     break;
00278   case format_tsv:
00279   case format_tsvh:
00280     c_sep = '\t';
00281     break;
00282   case format_csv:
00283   case format_csvh:
00284     c_sep = ',';
00285     break;
00286   default:
00287     c_sep = 0;
00288     break;
00289   }
00290 
00291   for (int i_icol = 1; i_icol <= i_ncol; i_icol++) {
00292     //???    DescribeCol(i_icol,c_colname[i_icol],c_colname[i_icol].Size(),
00293     DescribeCol(i_icol,c_colname[i_icol],256,
00294                 i_sqltype,i_precision,i_scale,b_nullable);
00295     switch (i_sqltype) {
00296 
00297     case SQL_BIT:
00298     case SQL_TINYINT:
00299     case SQL_SMALLINT:
00300     case SQL_INTEGER:
00301       i_coltype[i_icol] = e_int;
00302       break;
00303 
00304     case SQL_DOUBLE:
00305     case SQL_DECIMAL:
00306     case SQL_NUMERIC:
00307     case SQL_FLOAT:
00308       i_coltype[i_icol] = e_double;
00309       break;
00310 
00311     case SQL_VARCHAR:
00312     case SQL_CHAR:
00313       i_coltype[i_icol] = e_char;
00314       break;
00315 
00316     case SQL_TIMESTAMP:
00317       i_coltype[i_icol] = e_date;
00318       break;
00319 
00320     default:
00321       i_coltype[i_icol] = e_bad;
00322       break;
00323     }
00324 
00325     switch (i_format) {
00326     case format_bsvh:
00327     case format_tsvh:
00328     case format_csvh:
00329       if (i_icol > 1) os << c_sep;
00330       os << c_colname[i_icol];
00331       break;
00332     case format_lvph:
00333       os << "#" << c_colname[i_icol] << ": ";
00334       switch (i_sqltype) {
00335       case SQL_BIT:        os << "BIT";      break;
00336       case SQL_TINYINT:    os << "TINYINT";  break;
00337       case SQL_SMALLINT:   os << "SMALLINT"; break;
00338       case SQL_INTEGER:    os << "INTEGER";  break;
00339       case SQL_DOUBLE:     os << "DOUBLE";   break;
00340       case SQL_DECIMAL:    os << "DECIMAL";  break;
00341       case SQL_NUMERIC:    os << "NUMERIC";  break;
00342       case SQL_FLOAT:      os << "FLOAT";    break;
00343       case SQL_VARCHAR:    os << "VARCHAR";  break;
00344       case SQL_CHAR:       os << "CHAR";     break;
00345       case SQL_TIMESTAMP:  os << "TIMESTAMP"; break;
00346       default:             os << "?????????"; break;
00347       }
00348       os << " " << CTBprintf(i_precision,"d",4)
00349          << " " << CTBprintf(i_scale,"d",4)
00350          << endl;
00351       
00352       break;
00353     }
00354   }
00355 
00356   switch (i_format) {
00357   case format_bsvh:
00358   case format_tsvh:
00359   case format_csvh:
00360     os << endl;
00361     break;
00362   case format_lvph:
00363     os << "---" << endl;
00364     break;
00365   }
00366 
00367   while (Fetch()) {                         // now fetch all rows
00368     int               i_value;
00369     double            d_value;
00370     static const int  dim_c_value = 2000;
00371     char              c_value[dim_c_value];
00372     CTBodbcTime       time;
00373     bool              b_null;
00374     bool              b_drop_row  = true;
00375     int               i_ncol_null = 0;
00376 
00377     i_nrow += 1;
00378     if (i_maxrow > 0 && i_nrow > i_maxrow) break;
00379 
00380     for (int i_icol = 1; i_icol <= i_ncol; i_icol++) {
00381       
00382       switch (i_coltype[i_icol]) {
00383       case e_int:
00384         GetData(i_icol,i_value,b_null);
00385         break;
00386       case e_double:
00387         GetData(i_icol,d_value,b_null);
00388         break;
00389       case e_char:
00390         GetData(i_icol,c_value,dim_c_value,b_null);
00391         break;
00392       case e_date:
00393         GetData(i_icol,time,b_null);
00394         break;
00395       }
00396 
00397       if (!b_null) b_drop_row = false;
00398 
00399       switch (i_format) {
00400       case format_bsv:
00401       case format_bsvh:
00402         if (!b_null && i_ncol_null > 0) {
00403           for (int i = 0; i < i_ncol_null; i++) { // write all cached NULLs
00404             if (i > 0) os << " ";
00405             os << "NULL";
00406           }
00407           i_ncol_null = 0;
00408         }
00409         if (!b_drop_row && i_icol > 1) os << " ";
00410         if (b_null) {
00411           if (b_drop_row) {
00412             i_ncol_null += 1;
00413           } else {
00414             os << "NULL";
00415           }
00416         }
00417         break;
00418         
00419       case format_tsv:
00420       case format_tsvh:
00421       case format_csv:
00422       case format_csvh:
00423         if (!b_null && i_ncol_null > 0) {
00424           for (int i = 1; i < i_ncol_null; i++) { // n-1 sep's for cached NULLs
00425             os << c_sep;
00426           }
00427           i_ncol_null = 0;
00428         }
00429         if (!b_drop_row && i_icol > 1) os << c_sep;
00430         if (b_null && b_drop_row) i_ncol_null += 1;
00431         break;
00432 
00433       case format_lvp:
00434       case format_lvph:
00435         b_drop_row = false;
00436         os << c_colname[i_icol] << ": ";
00437         break;
00438       }
00439 
00440       if (!b_null) {
00441         switch (i_coltype[i_icol]) {
00442         case e_int:
00443           os << i_value;
00444           break;
00445         case e_double:
00446           os << d_value;                    // needs some work !!!
00447           break;
00448         case e_char:
00449           if (i_format == format_csv || i_format == format_csvh) {
00450             if (strpbrk(c_value,",\"\n") == 0) { // no , " or \n
00451               os << c_value;                // than just output string as is
00452             } else {                        // else quote and escape
00453               const char* p = c_value;
00454               char c;
00455               os << '"';
00456               while ((c = *p++)) {
00457                 if (c == '"')       os << '\\' << '"';
00458                 else if (c == '\n') os << '\\' << 'n';
00459                 else                os << c;
00460               }
00461               os << '"';
00462             }
00463           } else {
00464             os << c_value;
00465           }
00466           
00467           break;
00468         case e_date:
00469           os << time;
00470           break;
00471         }
00472       }
00473 
00474       if (i_format == format_lvp || i_format == format_lvph) os << "\n";
00475     }
00476 
00477     switch (i_format) {
00478     case format_bsv:
00479     case format_bsvh:
00480     case format_tsv:
00481     case format_tsvh:
00482     case format_csv:
00483     case format_csvh:
00484       if (!b_drop_row) os << endl;
00485       break;
00486     case format_lvp:
00487     case format_lvph:
00488       os << "---" << endl;
00489       break;
00490     }
00491   }
00492   Close();
00493 
00494   return true;
00495 }
00496 
00497 // ??? egcs 1.1.1 bug checked on the CTBcstring.Size() function....
00498 // ??? replaced it with integer literal.
00499 
00500 //------------------------------------------+-----------------------------------
00502 
00510 bool CTBodbcStatement::GetData(int i_icol, SWORD i_ctype,
00511                                void* p_value, int i_size, bool& b_null)
00512 {
00513   RETCODE   i_rc;
00514   SDWORD    i_rsize;
00515   
00516   b_null = false;
00517   if (!AllocIfNull()) return false;
00518   
00519   i_rc = SQLGetData (m_hstmt,i_icol,i_ctype,p_value,i_size,&i_rsize);
00520   m_dbc.TraceODBCCall("CTBodbcStatement::GetData->SQLGetData",i_rc);
00521 
00522   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00523     PrintError(cerr);
00524     return false;
00525   }
00526   
00527   b_null = (i_rsize == SQL_NULL_DATA);
00528   return true;
00529 }
00530 
00531 //------------------------------------------+-----------------------------------
00533 
00540 bool CTBodbcStatement::BindIParameter(int i_ipar, SWORD i_ctype,
00541                                       SWORD i_sqltype, void* p_value)
00542 {
00543   RETCODE          i_rc;
00544   static SDWORD    i_rsize=0;
00545   
00546   if (!AllocIfNull()) return false;
00547   if (i_rsize != 0) 
00548     cerr << "%CTBodbcStatement::BindIParameter-F sanity" << endl;
00549   i_rc = SQLBindParameter(m_hstmt,i_ipar,SQL_PARAM_INPUT,i_ctype,
00550                           i_sqltype,0,0,p_value,0,&i_rsize);
00551   m_dbc.TraceODBCCall("CTBodbcStatement::BindIParameter->SQLBindParameter",i_rc)
00552 ;
00553 
00554   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00555     PrintError(cerr);
00556     return false;
00557   }
00558 
00559   return true;
00560 }
00561 
00562 //------------------------------------------+-----------------------------------
00564 
00570 bool CTBodbcStatement::BindIParameter(int i_ipar, SWORD i_sqltype,
00571                                       const char* c_pvalue)
00572 {
00573   RETCODE          i_rc;
00574   static SDWORD    i_rsize=SQL_NTS;
00575   
00576   if (!AllocIfNull()) return false;  
00577   if (i_rsize != SQL_NTS) 
00578     cerr << "%CTBodbcStatement::BindIParameter-F sanity" << endl;
00579 
00580   i_rc = SQLBindParameter(m_hstmt,i_ipar,SQL_PARAM_INPUT,SQL_C_CHAR,
00581                           i_sqltype,0,0,(char*) c_pvalue,0,&i_rsize);
00582   m_dbc.TraceODBCCall("CTBodbcStatement::BindIParameter->SQLBindParameter",i_rc);
00583 
00584   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00585     PrintError(cerr);
00586     return false;
00587   }
00588 
00589   return true;
00590 }
00591 
00592 //------------------------------------------+-----------------------------------
00594 
00602 bool CTBodbcStatement::BindCol(int i_icol, SWORD i_ctype,
00603                                void* p_value, int i_size, CTBint32& i_rsize)
00604 {
00605   RETCODE          i_rc;
00606   
00607   if (!AllocIfNull()) return false;
00608 
00609   i_rc = SQLBindCol(m_hstmt,i_icol,i_ctype,p_value,i_size,(SDWORD*) &i_rsize);
00610   m_dbc.TraceODBCCall("CTBodbcStatement::BindCol->SQLBindCol",i_rc);
00611 
00612   if (i_rc != SQL_SUCCESS && i_rc != SQL_SUCCESS_WITH_INFO) {
00613     PrintError(cerr);
00614     return false;
00615   }
00616 
00617   return true;
00618 }
00619 
00620 //------------------------------------------+-----------------------------------
00622 
00623 void CTBodbcStatement::PrintError(ostream& os)
00624 {
00625   unsigned char  c_state[16];
00626   unsigned char  c_msg[SQL_MAX_MESSAGE_LENGTH];
00627   
00628   while (SQLError(m_dbc.m_henv,m_dbc.m_hdbc,m_hstmt,c_state,0,
00629                   c_msg,SQL_MAX_MESSAGE_LENGTH-1,0) == SQL_SUCCESS) {
00630     os << c_msg << " SQLSTATE " << c_state << endl;
00631   }
00632 
00633   m_dbc.PrintError(os);
00634 
00635   return;
00636 }
00637 
00638 //------------------------------------------+-----------------------------------
00640 
00641 bool CTBodbcStatement::AllocIfNull()
00642 {
00643   RETCODE   i_rc;
00644 
00645   if (m_hstmt != 0) return true;            // if allocated, all fine ...
00646 
00647   i_rc = SQLAllocStmt (m_dbc.m_hdbc, &m_hstmt);
00648   m_dbc.TraceODBCCall("CTBodbcStatement::Alloc->SQLAllocStmt",i_rc);
00649 
00650   if (i_rc != SQL_SUCCESS) {
00651     PrintError(cerr);
00652     return false;
00653   }
00654   return true;
00655 }
00656 
00657 //------------------------------------------+-----------------------------------
00658 
00659 #if (defined(CTB__OutLine) || defined(CTBodbcStatement__OutLine))
00660 #define inline
00661 #include "CTBodbcStatement.icc"
00662 #undef  inline
00663 #endif

Generated at Fri Oct 24 18:16:03 2003 for CTBodbc by doxygen1.2.9-20010812 written by Dimitri van Heesch, © 1997-2001