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

standard-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 
00009 #include "soci-sqlite3.h"
00010 //
00011 #if defined(SOCI_HEADERS_BURIED)
00012 #       include <soci/core/rowid.h>
00013 #       include <soci/core/blob.h>
00014 #else
00015 #       include <rowid.h>
00016 #       include <blob.h>
00017 #endif
00018 //
00019 // STL
00020 #include <cstring>
00021 #include <ctime>
00022 #include <limits>
00023 #include <cstdio>
00024 #include <sstream>
00025 #include <string>
00026 
00027 #ifdef _MSC_VER
00028 #pragma warning(disable:4355 4996)
00029 #define snprintf _snprintf
00030 #endif
00031 
00032 using namespace soci;
00033 using namespace soci::details;
00034 
00035 void sqlite3_standard_use_type_backend::bind_by_pos(int & position, void * data,
00036     exchange_type type, bool readOnly)
00037 {
00038     if (statement_.boundByName_)
00039     {
00040         throw soci_error(
00041          "Binding for use elements must be either by position or by name.");
00042     }
00043 
00044     data_ = data;
00045     type_ = type;
00046     position_ = position++;
00047 
00048     statement_.boundByPos_ = true;
00049 }
00050 
00051 void sqlite3_standard_use_type_backend::bind_by_name(std::string const & name,
00052     void * data, exchange_type type, bool readOnly)
00053 {
00054     if (statement_.boundByPos_)
00055     {
00056         throw soci_error(
00057          "Binding for use elements must be either by position or by name.");
00058     }
00059 
00060     data_ = data;
00061     type_ = type;
00062     name_ = ":" + name;
00063 
00064     statement_.resetIfNeeded();
00065     position_ = sqlite3_bind_parameter_index(statement_.stmt_, name_.c_str());
00066 
00067     if (0 == position_)
00068     {
00069         std::ostringstream ss;
00070         ss << "Cannot bind to (by name) " << name_;
00071         throw soci_error(ss.str());
00072     }
00073     statement_.boundByName_ = true;
00074 }
00075 
00076 void sqlite3_standard_use_type_backend::pre_use(indicator const * ind)
00077 {
00078     statement_.useData_.resize(1);
00079     int pos = position_ - 1;
00080 
00081     if (statement_.useData_[0].size() < static_cast<std::size_t>(position_))
00082     {
00083         statement_.useData_[0].resize(position_);
00084     }
00085 
00086     if (ind != NULL && *ind == i_null)
00087     {
00088         statement_.useData_[0][pos].isNull_ = true;
00089         statement_.useData_[0][pos].data_ = "";
00090         statement_.useData_[0][pos].blobBuf_ = 0;
00091         statement_.useData_[0][pos].blobSize_ = 0;
00092     }
00093     else
00094     {
00095         // allocate and fill the buffer with text-formatted client data
00096         switch (type_)
00097         {
00098         case x_char:
00099         {
00100             buf_ = new char[2];
00101             buf_[0] = *static_cast<char*>(data_);
00102             buf_[1] = '\0';
00103         }
00104         break;
00105         case x_stdstring:
00106         {
00107             std::string *s = static_cast<std::string *>(data_);
00108             buf_ = new char[s->size() + 1];
00109             std::strcpy(buf_, s->c_str());
00110         }
00111         break;
00112         case x_short:
00113         {
00114             std::size_t const bufSize
00115             = std::numeric_limits<short>::digits10 + 3;
00116             buf_ = new char[bufSize];
00117             snprintf(buf_, bufSize, "%d",
00118                           static_cast<int>(*static_cast<short*>(data_)));
00119         }
00120         break;
00121         case x_integer:
00122         {
00123             std::size_t const bufSize
00124             = std::numeric_limits<int>::digits10 + 3;
00125             buf_ = new char[bufSize];
00126             snprintf(buf_, bufSize, "%d",
00127                           *static_cast<int*>(data_));
00128         }
00129         break;
00130         case x_unsigned_long:
00131         {
00132             std::size_t const bufSize
00133             = std::numeric_limits<unsigned long>::digits10 + 2;
00134             buf_ = new char[bufSize];
00135             snprintf(buf_, bufSize, "%lu",
00136                           *static_cast<unsigned long*>(data_));
00137         }
00138         break;
00139         case x_long_long:
00140         {
00141             std::size_t const bufSize
00142             = std::numeric_limits<long long>::digits10 + 3;
00143             buf_ = new char[bufSize];
00144             snprintf(buf_, bufSize, "%lld",
00145                           *static_cast<long long *>(data_));
00146         }
00147         break;
00148         case x_double:
00149         {
00150             // no need to overengineer it (KISS)...
00151 
00152             std::size_t const bufSize = 100;
00153             buf_ = new char[bufSize];
00154 
00155             snprintf(buf_, bufSize, "%.20g",
00156                           *static_cast<double*>(data_));
00157         }
00158         break;
00159         case x_stdtm:
00160         {
00161             std::size_t const bufSize = 20;
00162             buf_ = new char[bufSize];
00163 
00164             std::tm *t = static_cast<std::tm *>(data_);
00165             snprintf(buf_, bufSize, "%d-%02d-%02d %02d:%02d:%02d",
00166                           t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
00167                           t->tm_hour, t->tm_min, t->tm_sec);
00168         }
00169         break;
00170         case x_rowid:
00171         {
00172             // RowID is internally identical to unsigned long
00173 
00174             rowid *rid = static_cast<rowid *>(data_);
00175             sqlite3_rowid_backend *rbe = static_cast<sqlite3_rowid_backend *>(rid->get_backend());
00176 
00177             std::size_t const bufSize
00178             = std::numeric_limits<unsigned long>::digits10 + 2;
00179             buf_ = new char[bufSize];
00180 
00181             snprintf(buf_, bufSize, "%lu", rbe->value_);
00182         }
00183         break;
00184         case x_blob:
00185         {
00186             blob *b = static_cast<blob *>(data_);
00187             sqlite3_blob_backend *bbe =
00188                 static_cast<sqlite3_blob_backend *>(b->get_backend());
00189 
00190             std::size_t len = bbe->get_len();
00191             buf_ = new char[len];
00192             bbe->read(0, buf_, len);
00193             statement_.useData_[0][pos].blobBuf_ = buf_;
00194             statement_.useData_[0][pos].blobSize_ = len;
00195         }
00196         break;
00197 
00198         default:
00199             throw soci_error("Use element used with non-supported type.");
00200         }
00201 
00202         statement_.useData_[0][pos].isNull_ = false;
00203         if (type_ != x_blob)
00204         {
00205             statement_.useData_[0][pos].blobBuf_ = 0;
00206             statement_.useData_[0][pos].blobSize_ = 0;
00207             statement_.useData_[0][pos].data_ = buf_;
00208         }
00209     }
00210 }
00211 
00212 void sqlite3_standard_use_type_backend::post_use(
00213     bool /* gotData */, indicator * /* ind */)
00214 {
00215     // TODO: Is it possible to have the bound element being overwritten
00216     // by the database?
00217     // If not, then nothing to do here, please remove this comment.
00218     // If yes, then use the value of the readOnly parameter:
00219     // - true:  the given object should not be modified and the backend
00220     //          should detect if the modification was performed on the
00221     //          isolated buffer and throw an exception if the buffer was modified
00222     //          (this indicates logic error, because the user used const object
00223     //          and executed a query that attempted to modified it)
00224     // - false: the modification should be propagated to the given object.
00225     // ...
00226 
00227     // clean up the working buffer, it might be allocated anew in
00228     // the next run of preUse
00229     clean_up();
00230 }
00231 
00232 void sqlite3_standard_use_type_backend::clean_up()
00233 {
00234     if (buf_ != NULL)
00235     {
00236         delete [] buf_;
00237         buf_ = NULL;
00238     }
00239 }
 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