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-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 #ifdef _MSC_VER
00017 // disables the warning about converting int to void*.  This is a 64 bit compatibility
00018 // warning, but odbc requires the value to be converted on this line
00019 // SQLSetStmtAttr(statement_.hstmt_, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
00020 #pragma warning(disable:4312)
00021 #endif
00022 
00023 
00024 using namespace soci;
00025 using namespace soci::details;
00026 
00027 void odbc_vector_use_type_backend::prepare_indicators(std::size_t size)
00028 {
00029     if (size == 0)
00030     {
00031          throw soci_error("Vectors of size 0 are not allowed.");
00032     }
00033 
00034     indHolderVec_.resize(size);
00035     indHolders_ = &indHolderVec_[0];
00036 }
00037 
00038 void odbc_vector_use_type_backend::prepare_for_bind(void *&data, SQLUINTEGER &size,
00039     SQLSMALLINT &sqlType, SQLSMALLINT &cType)
00040 {
00041     switch (type_)
00042     {    // simple cases
00043     case x_short:
00044         {
00045             sqlType = SQL_SMALLINT;
00046             cType = SQL_C_SSHORT;
00047             size = sizeof(short);
00048             std::vector<short> *vp = static_cast<std::vector<short> *>(data);
00049             std::vector<short> &v(*vp);
00050             prepare_indicators(v.size());
00051             data = &v[0];
00052         }
00053         break;
00054     case x_integer:
00055         {
00056             sqlType = SQL_INTEGER;
00057             cType = SQL_C_SLONG;
00058             size = sizeof(int);
00059             std::vector<int> *vp = static_cast<std::vector<int> *>(data);
00060             std::vector<int> &v(*vp);
00061             prepare_indicators(v.size());
00062             data = &v[0];
00063         }
00064         break;
00065     case x_unsigned_long:
00066         {
00067             sqlType = SQL_BIGINT;
00068             cType = SQL_C_ULONG;
00069             size = sizeof(unsigned long);
00070             std::vector<unsigned long> *vp
00071                  = static_cast<std::vector<unsigned long> *>(data);
00072             std::vector<unsigned long> &v(*vp);
00073             prepare_indicators(v.size());
00074             data = &v[0];
00075         }
00076         break;
00077     case x_double:
00078         {
00079             sqlType = SQL_DOUBLE;
00080             cType = SQL_C_DOUBLE;
00081             size = sizeof(double);
00082             std::vector<double> *vp = static_cast<std::vector<double> *>(data);
00083             std::vector<double> &v(*vp);
00084             prepare_indicators(v.size());
00085             data = &v[0];
00086         }
00087         break;
00088 
00089     // cases that require adjustments and buffer management
00090     case x_char:
00091         {
00092             std::vector<char> *vp
00093                 = static_cast<std::vector<char> *>(data);
00094             std::size_t const vsize = vp->size();
00095 
00096             prepare_indicators(vsize);
00097 
00098             size = sizeof(char) * 2;
00099             buf_ = new char[size * vsize];
00100 
00101             char *pos = buf_;
00102 
00103             for (std::size_t i = 0; i != vsize; ++i)
00104             {
00105                 *pos++ = (*vp)[i];
00106                 *pos++ = 0;
00107             }
00108 
00109             sqlType = SQL_CHAR;
00110             cType = SQL_C_CHAR;
00111             data = buf_;
00112         }
00113         break;
00114     case x_stdstring:
00115         {
00116             sqlType = SQL_CHAR;
00117             cType = SQL_C_CHAR;
00118 
00119             std::vector<std::string> *vp
00120                 = static_cast<std::vector<std::string> *>(data);
00121             std::vector<std::string> &v(*vp);
00122 
00123             std::size_t maxSize = 0;
00124             std::size_t const vecSize = v.size();
00125             prepare_indicators(vecSize);
00126             for (std::size_t i = 0; i != vecSize; ++i)
00127             {
00128                 std::size_t sz = v[i].length() + 1;  // add one for null
00129                 indHolderVec_[i] = static_cast<long>(sz);
00130                 maxSize = sz > maxSize ? sz : maxSize;
00131             }
00132 
00133             buf_ = new char[maxSize * vecSize];
00134             memset(buf_, 0, maxSize * vecSize);
00135 
00136             char *pos = buf_;
00137             for (std::size_t i = 0; i != vecSize; ++i)
00138             {
00139                 strncpy(pos, v[i].c_str(), v[i].length());
00140                 pos += maxSize;
00141             }
00142 
00143             data = buf_;
00144             size = static_cast<SQLINTEGER>(maxSize);
00145         }
00146         break;
00147     case x_stdtm:
00148         {
00149             std::vector<std::tm> *vp
00150                 = static_cast<std::vector<std::tm> *>(data);
00151 
00152             prepare_indicators(vp->size());
00153 
00154             buf_ = new char[sizeof(TIMESTAMP_STRUCT) * vp->size()];
00155 
00156             sqlType = SQL_TYPE_TIMESTAMP;
00157             cType = SQL_C_TYPE_TIMESTAMP;
00158             data = buf_;
00159             size = 19; // This number is not the size in bytes, but the number
00160                       // of characters in the date if it was written out
00161                       // yyyy-mm-dd hh:mm:ss
00162         }
00163         break;
00164 
00165     case x_statement: break; // not supported
00166     case x_rowid:     break; // not supported
00167     case x_blob:      break; // not supported
00168     }
00169 
00170     colSize_ = size;
00171 }
00172 
00173 void odbc_vector_use_type_backend::bind_helper(int &position, void *data, exchange_type type)
00174 {
00175     data_ = data; // for future reference
00176     type_ = type; // for future reference
00177 
00178     SQLSMALLINT sqlType;
00179     SQLSMALLINT cType;
00180     SQLUINTEGER size;
00181 
00182     prepare_for_bind(data, size, sqlType, cType);
00183 
00184     SQLINTEGER arraySize = (SQLINTEGER)indHolderVec_.size();
00185     SQLSetStmtAttr(statement_.hstmt_, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)arraySize, 0);
00186 
00187     SQLRETURN rc = SQLBindParameter(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++),
00188                                     SQL_PARAM_INPUT, cType, sqlType, size, 0,
00189                                     static_cast<SQLPOINTER>(data), size, indHolders_);
00190 
00191     if (is_odbc_error(rc))
00192     {
00193         throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_,
00194             "Error while binding value to column");
00195     }
00196 }
00197 
00198 void odbc_vector_use_type_backend::bind_by_pos(int &position,
00199         void *data, exchange_type type)
00200 {
00201     if (statement_.boundByName_)
00202     {
00203         throw soci_error(
00204          "Binding for use elements must be either by position or by name.");
00205     }
00206 
00207     bind_helper(position, data, type);
00208 
00209     statement_.boundByPos_ = true;
00210 }
00211 
00212 void odbc_vector_use_type_backend::bind_by_name(
00213     std::string const &name, void *data, exchange_type type)
00214 {
00215     if (statement_.boundByPos_)
00216     {
00217         throw soci_error(
00218          "Binding for use elements must be either by position or by name.");
00219     }
00220 
00221     int position = -1;
00222     int count = 1;
00223 
00224     for (std::vector<std::string>::iterator it = statement_.names_.begin();
00225          it != statement_.names_.end(); ++it)
00226     {
00227         if (*it == name)
00228         {
00229             position = count;
00230             break;
00231         }
00232         count++;
00233     }
00234 
00235     if (position != -1)
00236     {
00237         bind_helper(position, data, type);
00238     }
00239     else
00240     {
00241         std::ostringstream ss;
00242         ss << "Unable to find name '" << name << "' to bind to";
00243         throw soci_error(ss.str().c_str());
00244     }
00245 
00246     statement_.boundByName_ = true;
00247 }
00248 
00249 void odbc_vector_use_type_backend::pre_use(indicator const *ind)
00250 {
00251     // first deal with data
00252     if (type_ == x_stdtm)
00253     {
00254         std::vector<std::tm> *vp
00255              = static_cast<std::vector<std::tm> *>(data_);
00256 
00257         std::vector<std::tm> &v(*vp);
00258 
00259         char *pos = buf_;
00260         std::size_t const vsize = v.size();
00261         for (std::size_t i = 0; i != vsize; ++i)
00262         {
00263             std::tm t = v[i];
00264             TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos);
00265 
00266             ts->year = static_cast<SQLSMALLINT>(t.tm_year + 1900);
00267             ts->month = static_cast<SQLUSMALLINT>(t.tm_mon + 1);
00268             ts->day = static_cast<SQLUSMALLINT>(t.tm_mday);
00269             ts->hour = static_cast<SQLUSMALLINT>(t.tm_hour);
00270             ts->minute = static_cast<SQLUSMALLINT>(t.tm_min);
00271             ts->second = static_cast<SQLUSMALLINT>(t.tm_sec);
00272             ts->fraction = 0;
00273             pos += sizeof(TIMESTAMP_STRUCT);
00274         }
00275     }
00276 
00277     // then handle indicators
00278     if (ind != NULL)
00279     {
00280         std::size_t const vsize = size();
00281         for (std::size_t i = 0; i != vsize; ++i, ++ind)
00282         {
00283             if (*ind == i_null)
00284             {
00285                 indHolderVec_[i] = SQL_NULL_DATA; // null
00286             }
00287             else
00288             {
00289             // for strings we have already set the values
00290             if (type_ != x_stdstring)
00291                 {
00292                     indHolderVec_[i] = SQL_NTS;  // value is OK
00293                 }
00294             }
00295         }
00296     }
00297     else
00298     {
00299         // no indicators - treat all fields as OK
00300         std::size_t const vsize = size();
00301         for (std::size_t i = 0; i != vsize; ++i, ++ind)
00302         {
00303             // for strings we have already set the values
00304             if (type_ != x_stdstring)
00305             {
00306                 indHolderVec_[i] = SQL_NTS;  // value is OK
00307             }
00308         }
00309     }
00310 }
00311 
00312 std::size_t odbc_vector_use_type_backend::size()
00313 {
00314     std::size_t sz = 0; // dummy initialization to please the compiler
00315     switch (type_)
00316     {
00317     // simple cases
00318     case x_char:
00319         {
00320             std::vector<char> *vp = static_cast<std::vector<char> *>(data_);
00321             sz = vp->size();
00322         }
00323         break;
00324     case x_short:
00325         {
00326             std::vector<short> *vp = static_cast<std::vector<short> *>(data_);
00327             sz = vp->size();
00328         }
00329         break;
00330     case x_integer:
00331         {
00332             std::vector<int> *vp = static_cast<std::vector<int> *>(data_);
00333             sz = vp->size();
00334         }
00335         break;
00336     case x_unsigned_long:
00337         {
00338             std::vector<unsigned long> *vp
00339                 = static_cast<std::vector<unsigned long> *>(data_);
00340             sz = vp->size();
00341         }
00342         break;
00343     case x_double:
00344         {
00345             std::vector<double> *vp
00346                 = static_cast<std::vector<double> *>(data_);
00347             sz = vp->size();
00348         }
00349         break;
00350     case x_stdstring:
00351         {
00352             std::vector<std::string> *vp
00353                 = static_cast<std::vector<std::string> *>(data_);
00354             sz = vp->size();
00355         }
00356         break;
00357     case x_stdtm:
00358         {
00359             std::vector<std::tm> *vp
00360                 = static_cast<std::vector<std::tm> *>(data_);
00361             sz = vp->size();
00362         }
00363         break;
00364 
00365     case x_statement: break; // not supported
00366     case x_rowid:     break; // not supported
00367     case x_blob:      break; // not supported
00368     }
00369 
00370     return sz;
00371 }
00372 
00373 void odbc_vector_use_type_backend::clean_up()
00374 {
00375     if (buf_ != NULL)
00376     {
00377         delete [] buf_;
00378         buf_ = NULL;
00379     }
00380 }
 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