SOCI Logo Get SOCI at SourceForge.net. Fast, secure and Free Open Source software downloads

vector-into-type.cpp

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, David Courtney
00003 // Distributed under the Boost Software License, Version 1.0.
00004 // (See accompanying file LICENSE_1_0.txt or copy at
00005 // http://www.boost.org/LICENSE_1_0.txt)
00006 //
00007 
00008 #define SOCI_ODBC_SOURCE
00009 #include "soci-odbc.h"
00010 #include <cctype>
00011 #include <cstdio>
00012 #include <cstring>
00013 #include <ctime>
00014 #include <sstream>
00015 
00016 using namespace soci;
00017 using namespace soci::details;
00018 
00019 void odbc_vector_into_type_backend::prepare_indicators(std::size_t size)
00020 {
00021     if (size == 0)
00022     {
00023          throw soci_error("Vectors of size 0 are not allowed.");
00024     }
00025 
00026     indHolderVec_.resize(size);
00027     indHolders_ = &indHolderVec_[0];
00028 }
00029 
00030 void odbc_vector_into_type_backend::define_by_pos(
00031     int &position, void *data, exchange_type type)
00032 {
00033     data_ = data; // for future reference
00034     type_ = type; // for future reference
00035 
00036     SQLINTEGER size = 0;       // also dummy
00037 
00038     switch (type)
00039     {
00040     // simple cases
00041     case x_short:
00042         {
00043             odbcType_ = SQL_C_SSHORT;
00044             size = sizeof(short);
00045             std::vector<short> *vp = static_cast<std::vector<short> *>(data);
00046             std::vector<short> &v(*vp);
00047             prepare_indicators(v.size());
00048             data = &v[0];
00049         }
00050         break;
00051     case x_integer:
00052         {
00053             odbcType_ = SQL_C_SLONG;
00054             size = sizeof(long);
00055             std::vector<long> *vp = static_cast<std::vector<long> *>(data);
00056             std::vector<long> &v(*vp);
00057             prepare_indicators(v.size());
00058             data = &v[0];
00059         }
00060         break;
00061     case x_unsigned_long:
00062         {
00063             odbcType_ = SQL_C_ULONG;
00064             size = sizeof(unsigned long);
00065             std::vector<unsigned long> *vp
00066                 = static_cast<std::vector<unsigned long> *>(data);
00067             std::vector<unsigned long> &v(*vp);
00068             prepare_indicators(v.size());
00069             data = &v[0];
00070         }
00071         break;
00072     case x_double:
00073         {
00074             odbcType_ = SQL_C_DOUBLE;
00075             size = sizeof(double);
00076             std::vector<double> *vp = static_cast<std::vector<double> *>(data);
00077             std::vector<double> &v(*vp);
00078             prepare_indicators(v.size());
00079             data = &v[0];
00080         }
00081         break;
00082 
00083     // cases that require adjustments and buffer management
00084 
00085     case x_char:
00086         {
00087             odbcType_ = SQL_C_CHAR;
00088 
00089             std::vector<char> *v
00090                 = static_cast<std::vector<char> *>(data);
00091 
00092             prepare_indicators(v->size());
00093 
00094             size = sizeof(char) * 2;
00095             std::size_t bufSize = size * v->size();
00096 
00097             colSize_ = size;
00098 
00099             buf_ = new char[bufSize];
00100             data = buf_;
00101         }
00102         break;
00103     case x_stdstring:
00104         {
00105             odbcType_ = SQL_C_CHAR;
00106             std::vector<std::string> *v
00107                 = static_cast<std::vector<std::string> *>(data);
00108             colSize_ = statement_.column_size(position) + 1;
00109             std::size_t bufSize = colSize_ * v->size();
00110             buf_ = new char[bufSize];
00111 
00112             prepare_indicators(v->size());
00113 
00114             size = static_cast<SQLINTEGER>(colSize_);
00115             data = buf_;
00116         }
00117         break;
00118     case x_stdtm:
00119         {
00120             odbcType_ = SQL_C_TYPE_TIMESTAMP;
00121             std::vector<std::tm> *v
00122                 = static_cast<std::vector<std::tm> *>(data);
00123 
00124             prepare_indicators(v->size());
00125 
00126             size = sizeof(TIMESTAMP_STRUCT);
00127             colSize_ = size;
00128 
00129             std::size_t bufSize = size * v->size();
00130 
00131             buf_ = new char[bufSize];
00132             data = buf_;
00133         }
00134         break;
00135 
00136     case x_statement: break; // not supported
00137     case x_rowid:     break; // not supported
00138     case x_blob:      break; // not supported
00139     }
00140 
00141     SQLRETURN rc = SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
00142                               odbcType_, data, size, indHolders_);
00143     if (is_odbc_error(rc))
00144     {
00145         throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
00146                             "vector into type define by pos");
00147     }
00148 }
00149 
00150 void odbc_vector_into_type_backend::pre_fetch()
00151 {
00152     // nothing to do for the supported types
00153 }
00154 
00155 void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
00156 {
00157     if (gotData)
00158     {
00159         // first, deal with data
00160 
00161         // only std::string, std::tm and Statement need special handling
00162         if (type_ == x_char)
00163         {
00164             std::vector<char> *vp
00165                 = static_cast<std::vector<char> *>(data_);
00166 
00167             std::vector<char> &v(*vp);
00168             char *pos = buf_;
00169             std::size_t const vsize = v.size();
00170             for (std::size_t i = 0; i != vsize; ++i)
00171             {
00172                 v[i] = *pos;
00173                 pos += colSize_;
00174             }
00175         }
00176         if (type_ == x_stdstring)
00177         {
00178             std::vector<std::string> *vp
00179                 = static_cast<std::vector<std::string> *>(data_);
00180 
00181             std::vector<std::string> &v(*vp);
00182 
00183             char *pos = buf_;
00184             std::size_t const vsize = v.size();
00185             for (std::size_t i = 0; i != vsize; ++i)
00186             {
00187                 v[i].assign(pos, strlen(pos));
00188                 pos += colSize_;
00189             }
00190         }
00191         else if (type_ == x_stdtm)
00192         {
00193             std::vector<std::tm> *vp
00194                 = static_cast<std::vector<std::tm> *>(data_);
00195 
00196             std::vector<std::tm> &v(*vp);
00197             char *pos = buf_;
00198             std::size_t const vsize = v.size();
00199             for (std::size_t i = 0; i != vsize; ++i)
00200             {
00201                 std::tm t;
00202 
00203                 TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
00204                 t.tm_isdst = -1;
00205                 t.tm_year = ts->year - 1900;
00206                 t.tm_mon = ts->month - 1;
00207                 t.tm_mday = ts->day;
00208                 t.tm_hour = ts->hour;
00209                 t.tm_min = ts->minute;
00210                 t.tm_sec = ts->second;
00211 
00212                 // normalize and compute the remaining fields
00213                 std::mktime(&t);
00214                 v[i] = t;
00215                 pos += colSize_;
00216             }
00217         }
00218 
00219         // then - deal with indicators
00220         if (ind != NULL)
00221         {
00222             std::size_t const indSize = statement_.get_number_of_rows();
00223             for (std::size_t i = 0; i != indSize; ++i)
00224             {
00225                 if (indHolderVec_[i] > 0)
00226                 {
00227                     ind[i] = i_ok;
00228                 }
00229                 else if (indHolderVec_[i] == SQL_NULL_DATA)
00230                 {
00231                     ind[i] = i_null;
00232                 }
00233                 else
00234                 {
00235                     ind[i] = i_truncated;
00236                 }
00237             }
00238         }
00239         else
00240         {
00241             std::size_t const indSize = statement_.get_number_of_rows();
00242             for (std::size_t i = 0; i != indSize; ++i)
00243             {
00244                 if (indHolderVec_[i] == SQL_NULL_DATA)
00245                 {
00246                     // fetched null and no indicator - programming error!
00247                     throw soci_error(
00248                         "Null value fetched and no indicator defined.");
00249                 }
00250             }
00251         }
00252     }
00253     else // gotData == false
00254     {
00255         // nothing to do here, vectors are truncated anyway
00256     }
00257 }
00258 
00259 void odbc_vector_into_type_backend::resize(std::size_t sz)
00260 {
00261     indHolderVec_.resize(sz);
00262     switch (type_)
00263     {
00264     // simple cases
00265     case x_char:
00266         {
00267             std::vector<char> *v = static_cast<std::vector<char> *>(data_);
00268             v->resize(sz);
00269         }
00270         break;
00271     case x_short:
00272         {
00273             std::vector<short> *v = static_cast<std::vector<short> *>(data_);
00274             v->resize(sz);
00275         }
00276         break;
00277     case x_integer:
00278         {
00279             std::vector<long> *v = static_cast<std::vector<long> *>(data_);
00280             v->resize(sz);
00281         }
00282         break;
00283     case x_unsigned_long:
00284         {
00285             std::vector<unsigned long> *v
00286                 = static_cast<std::vector<unsigned long> *>(data_);
00287             v->resize(sz);
00288         }
00289         break;
00290     case x_double:
00291         {
00292             std::vector<double> *v
00293                 = static_cast<std::vector<double> *>(data_);
00294             v->resize(sz);
00295         }
00296         break;
00297     case x_stdstring:
00298         {
00299             std::vector<std::string> *v
00300                 = static_cast<std::vector<std::string> *>(data_);
00301             v->resize(sz);
00302         }
00303         break;
00304     case x_stdtm:
00305         {
00306             std::vector<std::tm> *v
00307                 = static_cast<std::vector<std::tm> *>(data_);
00308             v->resize(sz);
00309         }
00310         break;
00311 
00312     case x_statement: break; // not supported
00313     case x_rowid:     break; // not supported
00314     case x_blob:      break; // not supported
00315     }
00316 }
00317 
00318 std::size_t odbc_vector_into_type_backend::size()
00319 {
00320     std::size_t sz = 0; // dummy initialization to please the compiler
00321     switch (type_)
00322     {
00323     // simple cases
00324     case x_char:
00325         {
00326             std::vector<char> *v = static_cast<std::vector<char> *>(data_);
00327             sz = v->size();
00328         }
00329         break;
00330     case x_short:
00331         {
00332             std::vector<short> *v = static_cast<std::vector<short> *>(data_);
00333             sz = v->size();
00334         }
00335         break;
00336     case x_integer:
00337         {
00338             std::vector<long> *v = static_cast<std::vector<long> *>(data_);
00339             sz = v->size();
00340         }
00341         break;
00342     case x_unsigned_long:
00343         {
00344             std::vector<unsigned long> *v
00345                 = static_cast<std::vector<unsigned long> *>(data_);
00346             sz = v->size();
00347         }
00348         break;
00349     case x_double:
00350         {
00351             std::vector<double> *v
00352                 = static_cast<std::vector<double> *>(data_);
00353             sz = v->size();
00354         }
00355         break;
00356     case x_stdstring:
00357         {
00358             std::vector<std::string> *v
00359                 = static_cast<std::vector<std::string> *>(data_);
00360             sz = v->size();
00361         }
00362         break;
00363     case x_stdtm:
00364         {
00365             std::vector<std::tm> *v
00366                 = static_cast<std::vector<std::tm> *>(data_);
00367             sz = v->size();
00368         }
00369         break;
00370 
00371     case x_statement: break; // not supported
00372     case x_rowid:     break; // not supported
00373     case x_blob:      break; // not supported
00374     }
00375 
00376     return sz;
00377 }
00378 
00379 void odbc_vector_into_type_backend::clean_up()
00380 {
00381     if (buf_ != NULL)
00382     {
00383         delete [] buf_;
00384         buf_ = NULL;
00385     }
00386 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
SourceForge Logo

Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1