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

vector-use-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 #include <cctype>
00012 #include <cstdio>
00013 #include <cstring>
00014 #include <ctime>
00015 #include <sstream>
00016 
00017 #ifdef _MSC_VER
00018 #pragma warning(disable:4355)
00019 #endif
00020 
00021 using namespace soci;
00022 using namespace soci::details;
00023 using namespace soci::details::oracle;
00024 
00025 void oracle_vector_use_type_backend::prepare_indicators(std::size_t size)
00026 {
00027     if (size == 0)
00028     {
00029          throw soci_error("Vectors of size 0 are not allowed.");
00030     }
00031 
00032     indOCIHolderVec_.resize(size);
00033     indOCIHolders_ = &indOCIHolderVec_[0];
00034 }
00035 
00036 void oracle_vector_use_type_backend::prepare_for_bind(
00037     void *&data, sb4 &size, ub2 &oracleType)
00038 {
00039     switch (type_)
00040     {
00041     // simple cases
00042     case x_char:
00043         {
00044             oracleType = SQLT_AFC;
00045             size = sizeof(char);
00046             std::vector<char> *vp = static_cast<std::vector<char> *>(data);
00047             std::vector<char> &v(*vp);
00048             prepare_indicators(v.size());
00049             data = &v[0];
00050         }
00051         break;
00052     case x_short:
00053         {
00054             oracleType = SQLT_INT;
00055             size = sizeof(short);
00056             std::vector<short> *vp = static_cast<std::vector<short> *>(data);
00057             std::vector<short> &v(*vp);
00058             prepare_indicators(v.size());
00059             data = &v[0];
00060         }
00061         break;
00062     case x_integer:
00063         {
00064             oracleType = SQLT_INT;
00065             size = sizeof(int);
00066             std::vector<int> *vp = static_cast<std::vector<int> *>(data);
00067             std::vector<int> &v(*vp);
00068             prepare_indicators(v.size());
00069             data = &v[0];
00070         }
00071         break;
00072     case x_unsigned_long:
00073         {
00074             oracleType = SQLT_UIN;
00075             size = sizeof(unsigned long);
00076             std::vector<unsigned long> *vp
00077                 = static_cast<std::vector<unsigned long> *>(data);
00078             std::vector<unsigned long> &v(*vp);
00079             prepare_indicators(v.size());
00080             data = &v[0];
00081         }
00082         break;
00083     case x_double:
00084         {
00085             oracleType = SQLT_FLT;
00086             size = sizeof(double);
00087             std::vector<double> *vp = static_cast<std::vector<double> *>(data);
00088             std::vector<double> &v(*vp);
00089             prepare_indicators(v.size());
00090             data = &v[0];
00091         }
00092         break;
00093 
00094     // cases that require adjustments and buffer management
00095 
00096     case x_long_long:
00097         {
00098             std::vector<long long> *vp
00099                 = static_cast<std::vector<long long> *>(data);
00100             std::vector<long long> &v(*vp);
00101 
00102             std::size_t const vecSize = v.size();
00103             std::size_t const entrySize = 100; // arbitrary
00104             std::size_t const bufSize = entrySize * vecSize;
00105             buf_ = new char[bufSize];
00106 
00107             oracleType = SQLT_STR;
00108             data = buf_;
00109             size = entrySize;
00110 
00111             prepare_indicators(vecSize);
00112         }
00113         break;
00114     case x_stdstring:
00115         {
00116             std::vector<std::string> *vp
00117                 = static_cast<std::vector<std::string> *>(data);
00118             std::vector<std::string> &v(*vp);
00119 
00120             std::size_t maxSize = 0;
00121             std::size_t const vecSize = v.size();
00122             prepare_indicators(vecSize);
00123             for (std::size_t i = 0; i != vecSize; ++i)
00124             {
00125                 std::size_t sz = v[i].length();
00126                 sizes_.push_back(static_cast<ub2>(sz));
00127                 maxSize = sz > maxSize ? sz : maxSize;
00128             }
00129 
00130             buf_ = new char[maxSize * vecSize];
00131             char *pos = buf_;
00132             for (std::size_t i = 0; i != vecSize; ++i)
00133             {
00134                 strncpy(pos, v[i].c_str(), v[i].length());
00135                 pos += maxSize;
00136             }
00137 
00138             oracleType = SQLT_CHR;
00139             data = buf_;
00140             size = static_cast<sb4>(maxSize);
00141         }
00142         break;
00143     case x_stdtm:
00144         {
00145             std::vector<std::tm> *vp
00146                 = static_cast<std::vector<std::tm> *>(data);
00147 
00148             prepare_indicators(vp->size());
00149 
00150             sb4 const dlen = 7; // size of SQLT_DAT
00151             buf_ = new char[dlen * vp->size()];
00152 
00153             oracleType = SQLT_DAT;
00154             data = buf_;
00155             size = dlen;
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 
00165 void oracle_vector_use_type_backend::bind_by_pos(int &position,
00166         void *data, exchange_type type)
00167 {
00168     data_ = data; // for future reference
00169     type_ = type; // for future reference
00170 
00171     ub2 oracleType;
00172     sb4 size;
00173 
00174     prepare_for_bind(data, size, oracleType);
00175 
00176     ub2 *sizesP = 0; // used only for std::string
00177     if (type == x_stdstring)
00178     {
00179         sizesP = &sizes_[0];
00180     }
00181 
00182     sword res = OCIBindByPos(statement_.stmtp_, &bindp_,
00183         statement_.session_.errhp_,
00184         position++, data, size, oracleType,
00185         indOCIHolders_, sizesP, 0, 0, 0, OCI_DEFAULT);
00186     if (res != OCI_SUCCESS)
00187     {
00188         throw_oracle_soci_error(res, statement_.session_.errhp_);
00189     }
00190 }
00191 
00192 void oracle_vector_use_type_backend::bind_by_name(
00193     std::string const &name, void *data, exchange_type type)
00194 {
00195     data_ = data; // for future reference
00196     type_ = type; // for future reference
00197 
00198     ub2 oracleType;
00199     sb4 size;
00200 
00201     prepare_for_bind(data, size, oracleType);
00202 
00203     ub2 *sizesP = 0; // used only for std::string
00204     if (type == x_stdstring)
00205     {
00206         sizesP = &sizes_[0];
00207     }
00208 
00209     sword res = OCIBindByName(statement_.stmtp_, &bindp_,
00210         statement_.session_.errhp_,
00211         reinterpret_cast<text*>(const_cast<char*>(name.c_str())),
00212         static_cast<sb4>(name.size()),
00213         data, size, oracleType,
00214         indOCIHolders_, sizesP, 0, 0, 0, OCI_DEFAULT);
00215     if (res != OCI_SUCCESS)
00216     {
00217         throw_oracle_soci_error(res, statement_.session_.errhp_);
00218     }
00219 }
00220 
00221 void oracle_vector_use_type_backend::pre_use(indicator const *ind)
00222 {
00223     // first deal with data
00224     if (type_ == x_stdstring)
00225     {
00226         // nothing to do - it's already done during bind
00227         // (and it's probably impossible to separate them, because
00228         // changes in the string size could not be handled here)
00229     }
00230     else if (type_ == x_long_long)
00231     {
00232         std::vector<long long> *vp
00233             = static_cast<std::vector<long long> *>(data_);
00234         std::vector<long long> &v(*vp);
00235 
00236         char *pos = buf_;
00237         std::size_t const entrySize = 100; // arbitrary, but consistent
00238         std::size_t const vecSize = v.size();
00239         for (std::size_t i = 0; i != vecSize; ++i)
00240         {
00241             snprintf(pos, entrySize, "%lld", v[i]);
00242             pos += entrySize;
00243         }
00244     }
00245     else if (type_ == x_stdtm)
00246     {
00247         std::vector<std::tm> *vp
00248             = static_cast<std::vector<std::tm> *>(data_);
00249         std::vector<std::tm> &v(*vp);
00250 
00251         ub1* pos = reinterpret_cast<ub1*>(buf_);
00252         std::size_t const vsize = v.size();
00253         for (std::size_t i = 0; i != vsize; ++i)
00254         {
00255             *pos++ = static_cast<ub1>(100 + (1900 + v[i].tm_year) / 100);
00256             *pos++ = static_cast<ub1>(100 + v[i].tm_year % 100);
00257             *pos++ = static_cast<ub1>(v[i].tm_mon + 1);
00258             *pos++ = static_cast<ub1>(v[i].tm_mday);
00259             *pos++ = static_cast<ub1>(v[i].tm_hour + 1);
00260             *pos++ = static_cast<ub1>(v[i].tm_min + 1);
00261             *pos++ = static_cast<ub1>(v[i].tm_sec + 1);
00262         }
00263     }
00264 
00265     // then handle indicators
00266     if (ind != NULL)
00267     {
00268         std::size_t const vsize = size();
00269         for (std::size_t i = 0; i != vsize; ++i, ++ind)
00270         {
00271             if (*ind == i_null)
00272             {
00273                 indOCIHolderVec_[i] = -1; // null
00274             }
00275             else
00276             {
00277                 indOCIHolderVec_[i] = 0;  // value is OK
00278             }
00279         }
00280     }
00281     else
00282     {
00283         // no indicators - treat all fields as OK
00284         std::size_t const vsize = size();
00285         for (std::size_t i = 0; i != vsize; ++i, ++ind)
00286         {
00287             indOCIHolderVec_[i] = 0;  // value is OK
00288         }
00289     }
00290 }
00291 
00292 std::size_t oracle_vector_use_type_backend::size()
00293 {
00294     std::size_t sz = 0; // dummy initialization to please the compiler
00295     switch (type_)
00296     {
00297     // simple cases
00298     case x_char:
00299         {
00300             std::vector<char> *vp = static_cast<std::vector<char> *>(data_);
00301             sz = vp->size();
00302         }
00303         break;
00304     case x_short:
00305         {
00306             std::vector<short> *vp = static_cast<std::vector<short> *>(data_);
00307             sz = vp->size();
00308         }
00309         break;
00310     case x_integer:
00311         {
00312             std::vector<int> *vp = static_cast<std::vector<int> *>(data_);
00313             sz = vp->size();
00314         }
00315         break;
00316     case x_unsigned_long:
00317         {
00318             std::vector<unsigned long> *vp
00319                 = static_cast<std::vector<unsigned long> *>(data_);
00320             sz = vp->size();
00321         }
00322         break;
00323     case x_long_long:
00324         {
00325             std::vector<long long> *vp
00326                 = static_cast<std::vector<long long> *>(data_);
00327             sz = vp->size();
00328         }
00329         break;
00330     case x_double:
00331         {
00332             std::vector<double> *vp
00333                 = static_cast<std::vector<double> *>(data_);
00334             sz = vp->size();
00335         }
00336         break;
00337     case x_stdstring:
00338         {
00339             std::vector<std::string> *vp
00340                 = static_cast<std::vector<std::string> *>(data_);
00341             sz = vp->size();
00342         }
00343         break;
00344     case x_stdtm:
00345         {
00346             std::vector<std::tm> *vp
00347                 = static_cast<std::vector<std::tm> *>(data_);
00348             sz = vp->size();
00349         }
00350         break;
00351 
00352     case x_statement: break; // not supported
00353     case x_rowid:     break; // not supported
00354     case x_blob:      break; // not supported
00355     }
00356 
00357     return sz;
00358 }
00359 
00360 void oracle_vector_use_type_backend::clean_up()
00361 {
00362     if (buf_ != NULL)
00363     {
00364         delete [] buf_;
00365         buf_ = NULL;
00366     }
00367 
00368     if (bindp_ != NULL)
00369     {
00370         OCIHandleFree(bindp_, OCI_HTYPE_DEFINE);
00371         bindp_ = NULL;
00372     }
00373 }
 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