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 <sstream> 00017 00018 #ifdef SOCI_PGSQL_NOPARAMS 00019 #define SOCI_PGSQL_NOBINDBYNAME 00020 #endif // SOCI_PGSQL_NOPARAMS 00021 00022 using namespace soci; 00023 using namespace soci::details; 00024 using namespace soci::details::postgresql; 00025 00026 00027 void postgresql_vector_into_type_backend::define_by_pos( 00028 int & position, void * data, exchange_type type) 00029 { 00030 data_ = data; 00031 type_ = type; 00032 position_ = position++; 00033 } 00034 00035 void postgresql_vector_into_type_backend::pre_fetch() 00036 { 00037 // nothing to do here 00038 } 00039 00040 namespace // anonymous 00041 { 00042 00043 template <typename T> 00044 void set_invector_(void * p, int indx, T const & val) 00045 { 00046 std::vector<T> * dest = 00047 static_cast<std::vector<T> *>(p); 00048 00049 std::vector<T> & v = *dest; 00050 v[indx] = val; 00051 } 00052 00053 } // namespace anonymous 00054 00055 void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) 00056 { 00057 if (gotData) 00058 { 00059 // Here, rowsToConsume_ in the Statement object designates 00060 // the number of rows that need to be put in the user's buffers. 00061 00062 // postgresql_ column positions start at 0 00063 int const pos = position_ - 1; 00064 00065 int const endRow = statement_.currentRow_ + statement_.rowsToConsume_; 00066 00067 for (int curRow = statement_.currentRow_, i = 0; 00068 curRow != endRow; ++curRow, ++i) 00069 { 00070 // first, deal with indicators 00071 if (PQgetisnull(statement_.result_, curRow, pos) != 0) 00072 { 00073 if (ind == NULL) 00074 { 00075 throw soci_error( 00076 "Null value fetched and no indicator defined."); 00077 } 00078 00079 ind[i] = i_null; 00080 00081 // no need to convert data if it is null, go to next row 00082 continue; 00083 } 00084 else 00085 { 00086 if (ind != NULL) 00087 { 00088 ind[i] = i_ok; 00089 } 00090 } 00091 00092 // buffer with data retrieved from server, in text format 00093 char * buf = PQgetvalue(statement_.result_, curRow, pos); 00094 00095 switch (type_) 00096 { 00097 case x_char: 00098 set_invector_(data_, i, *buf); 00099 break; 00100 case x_stdstring: 00101 set_invector_<std::string>(data_, i, buf); 00102 break; 00103 case x_short: 00104 { 00105 short const val = string_to_integer<short>(buf); 00106 set_invector_(data_, i, val); 00107 } 00108 break; 00109 case x_integer: 00110 { 00111 int const val = string_to_integer<int>(buf); 00112 set_invector_(data_, i, val); 00113 } 00114 break; 00115 case x_unsigned_long: 00116 { 00117 unsigned long const val = 00118 string_to_unsigned_integer<unsigned long>(buf); 00119 set_invector_(data_, i, val); 00120 } 00121 break; 00122 case x_long_long: 00123 { 00124 long long const val = string_to_integer<long long>(buf); 00125 set_invector_(data_, i, val); 00126 } 00127 break; 00128 case x_double: 00129 { 00130 double const val = string_to_double(buf); 00131 set_invector_(data_, i, val); 00132 } 00133 break; 00134 case x_stdtm: 00135 { 00136 // attempt to parse the string and convert to std::tm 00137 std::tm t; 00138 parse_std_tm(buf, t); 00139 00140 set_invector_(data_, i, t); 00141 } 00142 break; 00143 00144 default: 00145 throw soci_error("Into element used with non-supported type."); 00146 } 00147 } 00148 } 00149 else // no data retrieved 00150 { 00151 // nothing to do, into vectors are already truncated 00152 } 00153 } 00154 00155 namespace // anonymous 00156 { 00157 00158 template <typename T> 00159 void resizevector_(void * p, std::size_t sz) 00160 { 00161 std::vector<T> * v = static_cast<std::vector<T> *>(p); 00162 v->resize(sz); 00163 } 00164 00165 } // namespace anonymous 00166 00167 void postgresql_vector_into_type_backend::resize(std::size_t sz) 00168 { 00169 switch (type_) 00170 { 00171 // simple cases 00172 case x_char: resizevector_<char> (data_, sz); break; 00173 case x_short: resizevector_<short> (data_, sz); break; 00174 case x_integer: resizevector_<int> (data_, sz); break; 00175 case x_unsigned_long: resizevector_<unsigned long>(data_, sz); break; 00176 case x_long_long: resizevector_<long long> (data_, sz); break; 00177 case x_double: resizevector_<double> (data_, sz); break; 00178 case x_stdstring: resizevector_<std::string> (data_, sz); break; 00179 case x_stdtm: resizevector_<std::tm> (data_, sz); break; 00180 00181 default: 00182 throw soci_error("Into vector element used with non-supported type."); 00183 } 00184 } 00185 00186 std::size_t postgresql_vector_into_type_backend::size() 00187 { 00188 std::size_t sz = 0; // dummy initialization to please the compiler 00189 switch (type_) 00190 { 00191 // simple cases 00192 case x_char: sz = get_vector_size<char> (data_); break; 00193 case x_short: sz = get_vector_size<short> (data_); break; 00194 case x_integer: sz = get_vector_size<int> (data_); break; 00195 case x_unsigned_long: sz = get_vector_size<unsigned long>(data_); break; 00196 case x_long_long: sz = get_vector_size<long long> (data_); break; 00197 case x_double: sz = get_vector_size<double> (data_); break; 00198 case x_stdstring: sz = get_vector_size<std::string> (data_); break; 00199 case x_stdtm: sz = get_vector_size<std::tm> (data_); break; 00200 00201 default: 00202 throw soci_error("Into vector element used with non-supported type."); 00203 } 00204 00205 return sz; 00206 } 00207 00208 void postgresql_vector_into_type_backend::clean_up() 00209 { 00210 // nothing to do here 00211 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1