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-2007 Maciej Sobczak, Stephen Hutton
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_ORACLE_SOURCE
00009 #include "soci-oracle.h"
00010 #include "error.h"
00011 //
00012 #if defined(SOCI_HEADERS_BURIED)
00013 #       include <soci/core/statement.h>
00014 #else
00015 #       include <statement.h>
00016 #endif
00017 //
00018 #include <cctype>
00019 #include <cstdio>
00020 #include <cstring>
00021 #include <cstdlib>
00022 #include <ctime>
00023 #include <sstream>
00024 
00025 #ifdef _MSC_VER
00026 #pragma warning(disable:4355)
00027 #endif
00028 
00029 using namespace soci;
00030 using namespace soci::details;
00031 using namespace soci::details::oracle;
00032 
00033 void oracle_vector_into_type_backend::prepare_indicators(std::size_t size)
00034 {
00035     if (size == 0)
00036     {
00037          throw soci_error("Vectors of size 0 are not allowed.");
00038     }
00039 
00040     indOCIHolderVec_.resize(size);
00041     indOCIHolders_ = &indOCIHolderVec_[0];
00042 
00043     sizes_.resize(size);
00044     rCodes_.resize(size);
00045 }
00046 
00047 void oracle_vector_into_type_backend::define_by_pos(
00048     int &position, void *data, exchange_type type)
00049 {
00050     data_ = data; // for future reference
00051     type_ = type; // for future reference
00052 
00053     ub2 oracleType = 0; // dummy initialization to please the compiler
00054     sb4 size = 0;       // also dummy
00055 
00056     switch (type)
00057     {
00058     // simple cases
00059     case x_char:
00060         {
00061             oracleType = SQLT_AFC;
00062             size = sizeof(char);
00063             std::vector<char> *vp = static_cast<std::vector<char> *>(data);
00064             std::vector<char> &v(*vp);
00065             prepare_indicators(v.size());
00066             data = &v[0];
00067         }
00068         break;
00069     case x_short:
00070         {
00071             oracleType = SQLT_INT;
00072             size = sizeof(short);
00073             std::vector<short> *vp = static_cast<std::vector<short> *>(data);
00074             std::vector<short> &v(*vp);
00075             prepare_indicators(v.size());
00076             data = &v[0];
00077         }
00078         break;
00079     case x_integer:
00080         {
00081             oracleType = SQLT_INT;
00082             size = sizeof(int);
00083             std::vector<int> *vp = static_cast<std::vector<int> *>(data);
00084             std::vector<int> &v(*vp);
00085             prepare_indicators(v.size());
00086             data = &v[0];
00087         }
00088         break;
00089     case x_unsigned_long:
00090         {
00091             oracleType = SQLT_UIN;
00092             size = sizeof(unsigned long);
00093             std::vector<unsigned long> *vp
00094                 = static_cast<std::vector<unsigned long> *>(data);
00095             std::vector<unsigned long> &v(*vp);
00096             prepare_indicators(v.size());
00097             data = &v[0];
00098         }
00099         break;
00100     case x_double:
00101         {
00102             oracleType = SQLT_FLT;
00103             size = sizeof(double);
00104             std::vector<double> *vp = static_cast<std::vector<double> *>(data);
00105             std::vector<double> &v(*vp);
00106             prepare_indicators(v.size());
00107             data = &v[0];
00108         }
00109         break;
00110 
00111     // cases that require adjustments and buffer management
00112 
00113     case x_long_long:
00114         {
00115             oracleType = SQLT_STR;
00116             std::vector<long long> *v
00117                 = static_cast<std::vector<long long> *>(data);
00118             colSize_ = 100; // arbitrary buffer size for each entry
00119             std::size_t const bufSize = colSize_ * v->size();
00120             buf_ = new char[bufSize];
00121 
00122             prepare_indicators(v->size());
00123 
00124             size = static_cast<sb4>(colSize_);
00125             data = buf_;
00126         }
00127         break;
00128     case x_stdstring:
00129         {
00130             oracleType = SQLT_CHR;
00131             std::vector<std::string> *v
00132                 = static_cast<std::vector<std::string> *>(data);
00133             colSize_ = statement_.column_size(position) + 1;
00134             std::size_t bufSize = colSize_ * v->size();
00135             buf_ = new char[bufSize];
00136 
00137             prepare_indicators(v->size());
00138 
00139             size = static_cast<sb4>(colSize_);
00140             data = buf_;
00141         }
00142         break;
00143     case x_stdtm:
00144         {
00145             oracleType = SQLT_DAT;
00146             std::vector<std::tm> *v
00147                 = static_cast<std::vector<std::tm> *>(data);
00148 
00149             prepare_indicators(v->size());
00150 
00151             size = 7; // 7 is the size of SQLT_DAT
00152             std::size_t bufSize = size * v->size();
00153 
00154             buf_ = new char[bufSize];
00155             data = buf_;
00156         }
00157         break;
00158 
00159     case x_statement: break; // not supported
00160     case x_rowid:     break; // not supported
00161     case x_blob:      break; // not supported
00162     }
00163 
00164     sword res = OCIDefineByPos(statement_.stmtp_, &defnp_,
00165         statement_.session_.errhp_,
00166         position++, data, size, oracleType,
00167         indOCIHolders_, &sizes_[0], &rCodes_[0], OCI_DEFAULT);
00168     if (res != OCI_SUCCESS)
00169     {
00170         throw_oracle_soci_error(res, statement_.session_.errhp_);
00171     }
00172 }
00173 
00174 void oracle_vector_into_type_backend::pre_fetch()
00175 {
00176     // nothing to do for the supported types
00177 }
00178 
00179 void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator *ind)
00180 {
00181     if (gotData)
00182     {
00183         // first, deal with data
00184 
00185         // only std::string, std::tm, long long and Statement need special handling
00186         if (type_ == x_stdstring)
00187         {
00188             std::vector<std::string> *vp
00189                 = static_cast<std::vector<std::string> *>(data_);
00190 
00191             std::vector<std::string> &v(*vp);
00192 
00193             char *pos = buf_;
00194             std::size_t const vsize = v.size();
00195             for (std::size_t i = 0; i != vsize; ++i)
00196             {
00197                 if (indOCIHolderVec_[i] != -1)
00198                 {
00199                     v[i].assign(pos, sizes_[i]);
00200                 }
00201                 pos += colSize_;
00202             }
00203         }
00204         else if (type_ == x_long_long)
00205         {
00206             std::vector<long long> *vp
00207                 = static_cast<std::vector<long long> *>(data_);
00208 
00209             std::vector<long long> &v(*vp);
00210 
00211             char *pos = buf_;
00212             std::size_t const vsize = v.size();
00213             for (std::size_t i = 0; i != vsize; ++i)
00214             {
00215                 if (indOCIHolderVec_[i] != -1)
00216                 {
00217                     v[i] = strtoll(pos, NULL, 10);
00218                 }
00219                 pos += colSize_;
00220             }
00221         }
00222         else if (type_ == x_stdtm)
00223         {
00224             std::vector<std::tm> *vp
00225                 = static_cast<std::vector<std::tm> *>(data_);
00226 
00227             std::vector<std::tm> &v(*vp);
00228 
00229             ub1 *pos = reinterpret_cast<ub1*>(buf_);
00230             std::size_t const vsize = v.size();
00231             for (std::size_t i = 0; i != vsize; ++i)
00232             {
00233                 if (indOCIHolderVec_[i] == -1)
00234                 {
00235                      pos += 7; // size of SQLT_DAT
00236                 }
00237                 else
00238                 {
00239                     std::tm t;
00240                     t.tm_isdst = -1;
00241 
00242                     t.tm_year = (*pos++ - 100) * 100;
00243                     t.tm_year += *pos++ - 2000;
00244                     t.tm_mon = *pos++ - 1;
00245                     t.tm_mday = *pos++;
00246                     t.tm_hour = *pos++ - 1;
00247                     t.tm_min = *pos++ - 1;
00248                     t.tm_sec = *pos++ - 1;
00249 
00250                     // normalize and compute the remaining fields
00251                     std::mktime(&t);
00252                     v[i] = t;
00253                 }
00254             }
00255         }
00256         else if (type_ == x_statement)
00257         {
00258             statement *st = static_cast<statement *>(data_);
00259             st->define_and_bind();
00260         }
00261 
00262         // then - deal with indicators
00263         if (ind != NULL)
00264         {
00265             std::size_t const indSize = statement_.get_number_of_rows();
00266             for (std::size_t i = 0; i != indSize; ++i)
00267             {
00268                 if (indOCIHolderVec_[i] == 0)
00269                 {
00270                     ind[i] = i_ok;
00271                 }
00272                 else if (indOCIHolderVec_[i] == -1)
00273                 {
00274                     ind[i] = i_null;
00275                 }
00276                 else
00277                 {
00278                     ind[i] = i_truncated;
00279                 }
00280             }
00281         }
00282         else
00283         {
00284             std::size_t const indSize = indOCIHolderVec_.size();
00285             for (std::size_t i = 0; i != indSize; ++i)
00286             {
00287                 if (indOCIHolderVec_[i] == -1)
00288                 {
00289                     // fetched null and no indicator - programming error!
00290                     throw soci_error(
00291                         "Null value fetched and no indicator defined.");
00292                 }
00293             }
00294         }
00295     }
00296     else // gotData == false
00297     {
00298         // nothing to do here, vectors are truncated anyway
00299     }
00300 }
00301 
00302 void oracle_vector_into_type_backend::resize(std::size_t sz)
00303 {
00304     switch (type_)
00305     {
00306     // simple cases
00307     case x_char:
00308         {
00309             std::vector<char> *v = static_cast<std::vector<char> *>(data_);
00310             v->resize(sz);
00311         }
00312         break;
00313     case x_short:
00314         {
00315             std::vector<short> *v = static_cast<std::vector<short> *>(data_);
00316             v->resize(sz);
00317         }
00318         break;
00319     case x_integer:
00320         {
00321             std::vector<int> *v = static_cast<std::vector<int> *>(data_);
00322             v->resize(sz);
00323         }
00324         break;
00325     case x_unsigned_long:
00326         {
00327             std::vector<unsigned long> *v
00328                 = static_cast<std::vector<unsigned long> *>(data_);
00329             v->resize(sz);
00330         }
00331         break;
00332     case x_long_long:
00333         {
00334             std::vector<long long> *v
00335                 = static_cast<std::vector<long long> *>(data_);
00336             v->resize(sz);
00337         }
00338         break;
00339     case x_double:
00340         {
00341             std::vector<double> *v
00342                 = static_cast<std::vector<double> *>(data_);
00343             v->resize(sz);
00344         }
00345         break;
00346     case x_stdstring:
00347         {
00348             std::vector<std::string> *v
00349                 = static_cast<std::vector<std::string> *>(data_);
00350             v->resize(sz);
00351         }
00352         break;
00353     case x_stdtm:
00354         {
00355             std::vector<std::tm> *v
00356                 = static_cast<std::vector<std::tm> *>(data_);
00357             v->resize(sz);
00358         }
00359         break;
00360 
00361     case x_statement: break; // not supported
00362     case x_rowid:     break; // not supported
00363     case x_blob:      break; // not supported
00364     }
00365 }
00366 
00367 std::size_t oracle_vector_into_type_backend::size()
00368 {
00369     std::size_t sz = 0; // dummy initialization to please the compiler
00370     switch (type_)
00371     {
00372     // simple cases
00373     case x_char:
00374         {
00375             std::vector<char> *v = static_cast<std::vector<char> *>(data_);
00376             sz = v->size();
00377         }
00378         break;
00379     case x_short:
00380         {
00381             std::vector<short> *v = static_cast<std::vector<short> *>(data_);
00382             sz = v->size();
00383         }
00384         break;
00385     case x_integer:
00386         {
00387             std::vector<int> *v = static_cast<std::vector<int> *>(data_);
00388             sz = v->size();
00389         }
00390         break;
00391     case x_unsigned_long:
00392         {
00393             std::vector<unsigned long> *v
00394                 = static_cast<std::vector<unsigned long> *>(data_);
00395             sz = v->size();
00396         }
00397         break;
00398     case x_long_long:
00399         {
00400             std::vector<long long> *v
00401                 = static_cast<std::vector<long long> *>(data_);
00402             sz = v->size();
00403         }
00404         break;
00405     case x_double:
00406         {
00407             std::vector<double> *v
00408                 = static_cast<std::vector<double> *>(data_);
00409             sz = v->size();
00410         }
00411         break;
00412     case x_stdstring:
00413         {
00414             std::vector<std::string> *v
00415                 = static_cast<std::vector<std::string> *>(data_);
00416             sz = v->size();
00417         }
00418         break;
00419     case x_stdtm:
00420         {
00421             std::vector<std::tm> *v
00422                 = static_cast<std::vector<std::tm> *>(data_);
00423             sz = v->size();
00424         }
00425         break;
00426 
00427     case x_statement: break; // not supported
00428     case x_rowid:     break; // not supported
00429     case x_blob:      break; // not supported
00430     }
00431 
00432     return sz;
00433 }
00434 
00435 void oracle_vector_into_type_backend::clean_up()
00436 {
00437     if (defnp_ != NULL)
00438     {
00439         OCIHandleFree(defnp_, OCI_HTYPE_DEFINE);
00440         defnp_ = NULL;
00441     }
00442 
00443     if (buf_ != NULL)
00444     {
00445         delete [] buf_;
00446         buf_ = NULL;
00447     }
00448 }
 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