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 #include "common.h" 00011 #include <libpq/libpq-fs.h> // libpq 00012 #include <cctype> 00013 #include <cstdio> 00014 #include <cstring> 00015 #include <ctime> 00016 #include <limits> 00017 #include <sstream> 00018 00019 #ifdef SOCI_PGSQL_NOPARAMS 00020 #define SOCI_PGSQL_NOBINDBYNAME 00021 #endif // SOCI_PGSQL_NOPARAMS 00022 00023 #ifdef _MSC_VER 00024 #pragma warning(disable:4355 4996) 00025 #define snprintf _snprintf 00026 #endif 00027 00028 using namespace soci; 00029 using namespace soci::details; 00030 using namespace soci::details::postgresql; 00031 00032 00033 void postgresql_vector_use_type_backend::bind_by_pos(int & position, 00034 void * data, exchange_type type) 00035 { 00036 data_ = data; 00037 type_ = type; 00038 position_ = position++; 00039 } 00040 00041 void postgresql_vector_use_type_backend::bind_by_name( 00042 std::string const & name, void * data, exchange_type type) 00043 { 00044 data_ = data; 00045 type_ = type; 00046 name_ = name; 00047 } 00048 00049 void postgresql_vector_use_type_backend::pre_use(indicator const * ind) 00050 { 00051 std::size_t const vsize = size(); 00052 for (size_t i = 0; i != vsize; ++i) 00053 { 00054 char * buf; 00055 00056 // the data in vector can be either i_ok or i_null 00057 if (ind != NULL && ind[i] == i_null) 00058 { 00059 buf = NULL; 00060 } 00061 else 00062 { 00063 // allocate and fill the buffer with text-formatted client data 00064 switch (type_) 00065 { 00066 case x_char: 00067 { 00068 std::vector<char> * pv 00069 = static_cast<std::vector<char> *>(data_); 00070 std::vector<char> & v = *pv; 00071 00072 buf = new char[2]; 00073 buf[0] = v[i]; 00074 buf[1] = '\0'; 00075 } 00076 break; 00077 case x_stdstring: 00078 { 00079 std::vector<std::string> * pv 00080 = static_cast<std::vector<std::string> *>(data_); 00081 std::vector<std::string> & v = *pv; 00082 00083 buf = new char[v[i].size() + 1]; 00084 std::strcpy(buf, v[i].c_str()); 00085 } 00086 break; 00087 case x_short: 00088 { 00089 std::vector<short> * pv 00090 = static_cast<std::vector<short> *>(data_); 00091 std::vector<short> & v = *pv; 00092 00093 std::size_t const bufSize 00094 = std::numeric_limits<short>::digits10 + 3; 00095 buf = new char[bufSize]; 00096 snprintf(buf, bufSize, "%d", static_cast<int>(v[i])); 00097 } 00098 break; 00099 case x_integer: 00100 { 00101 std::vector<int> * pv 00102 = static_cast<std::vector<int> *>(data_); 00103 std::vector<int> & v = *pv; 00104 00105 std::size_t const bufSize 00106 = std::numeric_limits<int>::digits10 + 3; 00107 buf = new char[bufSize]; 00108 snprintf(buf, bufSize, "%d", v[i]); 00109 } 00110 break; 00111 case x_unsigned_long: 00112 { 00113 std::vector<unsigned long> * pv 00114 = static_cast<std::vector<unsigned long> *>(data_); 00115 std::vector<unsigned long> & v = *pv; 00116 00117 std::size_t const bufSize 00118 = std::numeric_limits<unsigned long>::digits10 + 2; 00119 buf = new char[bufSize]; 00120 snprintf(buf, bufSize, "%lu", v[i]); 00121 } 00122 break; 00123 case x_long_long: 00124 { 00125 std::vector<long long> * pv 00126 = static_cast<std::vector<long long> *>(data_); 00127 std::vector<long long> & v = *pv; 00128 00129 std::size_t const bufSize 00130 = std::numeric_limits<long long>::digits10 + 3; 00131 buf = new char[bufSize]; 00132 snprintf(buf, bufSize, "%lld", v[i]); 00133 } 00134 break; 00135 case x_double: 00136 { 00137 // no need to overengineer it (KISS)... 00138 00139 std::vector<double> * pv 00140 = static_cast<std::vector<double> *>(data_); 00141 std::vector<double> & v = *pv; 00142 00143 std::size_t const bufSize = 100; 00144 buf = new char[bufSize]; 00145 00146 snprintf(buf, bufSize, "%.20g", v[i]); 00147 } 00148 break; 00149 case x_stdtm: 00150 { 00151 std::vector<std::tm> * pv 00152 = static_cast<std::vector<std::tm> *>(data_); 00153 std::vector<std::tm> & v = *pv; 00154 00155 std::size_t const bufSize = 20; 00156 buf = new char[bufSize]; 00157 00158 snprintf(buf, bufSize, "%d-%02d-%02d %02d:%02d:%02d", 00159 v[i].tm_year + 1900, v[i].tm_mon + 1, v[i].tm_mday, 00160 v[i].tm_hour, v[i].tm_min, v[i].tm_sec); 00161 } 00162 break; 00163 00164 default: 00165 throw soci_error( 00166 "Use vector element used with non-supported type."); 00167 } 00168 } 00169 00170 buffers_.push_back(buf); 00171 } 00172 00173 if (position_ > 0) 00174 { 00175 // binding by position 00176 statement_.useByPosBuffers_[position_] = &buffers_[0]; 00177 } 00178 else 00179 { 00180 // binding by name 00181 statement_.useByNameBuffers_[name_] = &buffers_[0]; 00182 } 00183 } 00184 00185 std::size_t postgresql_vector_use_type_backend::size() 00186 { 00187 std::size_t sz = 0; // dummy initialization to please the compiler 00188 switch (type_) 00189 { 00190 // simple cases 00191 case x_char: sz = get_vector_size<char> (data_); break; 00192 case x_short: sz = get_vector_size<short> (data_); break; 00193 case x_integer: sz = get_vector_size<int> (data_); break; 00194 case x_unsigned_long: sz = get_vector_size<unsigned long>(data_); break; 00195 case x_long_long: sz = get_vector_size<long long> (data_); break; 00196 case x_double: sz = get_vector_size<double> (data_); break; 00197 case x_stdstring: sz = get_vector_size<std::string> (data_); break; 00198 case x_stdtm: sz = get_vector_size<std::tm> (data_); break; 00199 00200 default: 00201 throw soci_error("Use vector element used with non-supported type."); 00202 } 00203 00204 return sz; 00205 } 00206 00207 void postgresql_vector_use_type_backend::clean_up() 00208 { 00209 std::size_t const bsize = buffers_.size(); 00210 for (std::size_t i = 0; i != bsize; ++i) 00211 { 00212 delete [] buffers_[i]; 00213 } 00214 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1