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-2008 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_POSTGRESQL_SOURCE
00009 #include "soci-postgresql.h"
00010 //
00011 #if defined(SOCI_HEADERS_BURIED)
00012 #       include <soci/core/blob.h>
00013 #       include <soci/core/rowid.h>
00014 #else
00015 #       include <blob.h>
00016 #       include <rowid.h>
00017 #endif
00018 //
00019 #include <libpq/libpq-fs.h> // libpq (PostGreSQL client)
00020 #include <cctype>
00021 #include <cstdio>
00022 #include <cstring>
00023 #include <ctime>
00024 #include <limits>
00025 #include <sstream>
00026 
00027 #ifdef SOCI_PGSQL_NOPARAMS
00028 #define SOCI_PGSQL_NOBINDBYNAME
00029 #endif // SOCI_PGSQL_NOPARAMS
00030 
00031 #ifdef _MSC_VER
00032 #pragma warning(disable:4355 4996)
00033 #define snprintf _snprintf
00034 #endif
00035 
00036 using namespace soci;
00037 using namespace soci::details;
00038 
00039 
00040 void postgresql_standard_use_type_backend::bind_by_pos(
00041     int & position, void * data, exchange_type type, bool /* readOnly */)
00042 {
00043     // readOnly is ignored, because PostgreSQL does not support
00044     // any data to be written back to used (bound) objects.
00045 
00046     data_ = data;
00047     type_ = type;
00048     position_ = position++;
00049 }
00050 
00051 void postgresql_standard_use_type_backend::bind_by_name(
00052     std::string const & name, void * data, exchange_type type, bool /* readOnly */)
00053 {
00054     // readOnly is ignored, because PostgreSQL does not support
00055     // any data to be written back to used (bound) objects.
00056 
00057     data_ = data;
00058     type_ = type;
00059     name_ = name;
00060 }
00061 
00062 void postgresql_standard_use_type_backend::pre_use(indicator const * ind)
00063 {
00064     if (ind != NULL && *ind == i_null)
00065     {
00066         // leave the working buffer as NULL
00067     }
00068     else
00069     {
00070         // allocate and fill the buffer with text-formatted client data
00071         switch (type_)
00072         {
00073         case x_char:
00074             {
00075                 buf_ = new char[2];
00076                 buf_[0] = *static_cast<char *>(data_);
00077                 buf_[1] = '\0';
00078             }
00079             break;
00080         case x_stdstring:
00081             {
00082                 std::string * s = static_cast<std::string *>(data_);
00083                 buf_ = new char[s->size() + 1];
00084                 std::strcpy(buf_, s->c_str());
00085             }
00086             break;
00087         case x_short:
00088             {
00089                 std::size_t const bufSize
00090                     = std::numeric_limits<short>::digits10 + 3;
00091                 buf_ = new char[bufSize];
00092                 snprintf(buf_, bufSize, "%d",
00093                     static_cast<int>(*static_cast<short *>(data_)));
00094             }
00095             break;
00096         case x_integer:
00097             {
00098                 std::size_t const bufSize
00099                     = std::numeric_limits<int>::digits10 + 3;
00100                 buf_ = new char[bufSize];
00101                 snprintf(buf_, bufSize, "%d",
00102                     *static_cast<int *>(data_));
00103             }
00104             break;
00105         case x_unsigned_long:
00106             {
00107                 std::size_t const bufSize
00108                     = std::numeric_limits<unsigned long>::digits10 + 2;
00109                 buf_ = new char[bufSize];
00110                 snprintf(buf_, bufSize, "%lu",
00111                     *static_cast<unsigned long *>(data_));
00112             }
00113             break;
00114         case x_long_long:
00115             {
00116                 std::size_t const bufSize
00117                     = std::numeric_limits<long long>::digits10 + 3;
00118                 buf_ = new char[bufSize];
00119                 snprintf(buf_, bufSize, "%lld",
00120                     *static_cast<long long *>(data_));
00121             }
00122             break;
00123         case x_double:
00124             {
00125                 // no need to overengineer it (KISS)...
00126 
00127                 std::size_t const bufSize = 100;
00128                 buf_ = new char[bufSize];
00129 
00130                 snprintf(buf_, bufSize, "%.20g",
00131                     *static_cast<double *>(data_));
00132             }
00133             break;
00134         case x_stdtm:
00135             {
00136                 std::size_t const bufSize = 20;
00137                 buf_ = new char[bufSize];
00138 
00139                 std::tm * t = static_cast<std::tm *>(data_);
00140                 snprintf(buf_, bufSize, "%d-%02d-%02d %02d:%02d:%02d",
00141                     t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
00142                     t->tm_hour, t->tm_min, t->tm_sec);
00143             }
00144             break;
00145         case x_rowid:
00146             {
00147                 // RowID is internally identical to unsigned long
00148 
00149                 rowid * rid = static_cast<rowid *>(data_);
00150                 postgresql_rowid_backend * rbe
00151                     = static_cast<postgresql_rowid_backend *>(
00152                         rid->get_backend());
00153 
00154                 std::size_t const bufSize
00155                     = std::numeric_limits<unsigned long>::digits10 + 2;
00156                 buf_ = new char[bufSize];
00157 
00158                 snprintf(buf_, bufSize, "%lu", rbe->value_);
00159             }
00160             break;
00161         case x_blob:
00162             {
00163                 blob * b = static_cast<blob *>(data_);
00164                 postgresql_blob_backend * bbe =
00165                     static_cast<postgresql_blob_backend *>(b->get_backend());
00166 
00167                 std::size_t const bufSize
00168                     = std::numeric_limits<unsigned long>::digits10 + 2;
00169                 buf_ = new char[bufSize];
00170                 snprintf(buf_, bufSize, "%lu", bbe->oid_);
00171             }
00172             break;
00173 
00174         default:
00175             throw soci_error("Use element used with non-supported type.");
00176         }
00177     }
00178 
00179     if (position_ > 0)
00180     {
00181         // binding by position
00182         statement_.useByPosBuffers_[position_] = &buf_;
00183     }
00184     else
00185     {
00186         // binding by name
00187         statement_.useByNameBuffers_[name_] = &buf_;
00188     }
00189 }
00190 
00191 void postgresql_standard_use_type_backend::post_use(
00192     bool /* gotData */, indicator * /* ind */)
00193 {
00194     // PostgreSQL does not support any data moving back the same channel,
00195     // so there is nothing to do here.
00196     // In particular, there is nothing to protect, because both const and non-const
00197     // objects will never be modified.
00198 
00199     // clean up the working buffer, it might be allocated anew in
00200     // the next run of preUse
00201     clean_up();
00202 }
00203 
00204 void postgresql_standard_use_type_backend::clean_up()
00205 {
00206     if (buf_ != NULL)
00207     {
00208         delete [] buf_;
00209         buf_ = NULL;
00210     }
00211 }
 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