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 // 00012 #if defined(SOCI_HEADERS_BURIED) 00013 # include <soci/core/blob.h> 00014 # include <soci/core/rowid.h> 00015 #else 00016 # include <blob.h> 00017 # include <rowid.h> 00018 #endif 00019 // 00020 #include <libpq/libpq-fs.h> // libpq (PostGreSQL client) 00021 #include <cctype> 00022 #include <cstdio> 00023 #include <cstring> 00024 #include <cstdlib> 00025 #include <ctime> 00026 #include <sstream> 00027 00028 #ifdef SOCI_PGSQL_NOPARAMS 00029 #define SOCI_PGSQL_NOBINDBYNAME 00030 #endif // SOCI_PGSQL_NOPARAMS 00031 00032 using namespace soci; 00033 using namespace soci::details; 00034 using namespace soci::details::postgresql; 00035 00036 00037 void postgresql_standard_into_type_backend::define_by_pos( 00038 int & position, void * data, exchange_type type) 00039 { 00040 data_ = data; 00041 type_ = type; 00042 position_ = position++; 00043 } 00044 00045 void postgresql_standard_into_type_backend::pre_fetch() 00046 { 00047 // nothing to do here 00048 } 00049 00050 void postgresql_standard_into_type_backend::post_fetch( 00051 bool gotData, bool calledFromFetch, indicator * ind) 00052 { 00053 if (calledFromFetch == true && gotData == false) 00054 { 00055 // this is a normal end-of-rowset condition, 00056 // no need to do anything (fetch() will return false) 00057 return; 00058 } 00059 00060 if (gotData) 00061 { 00062 // postgresql_ positions start at 0 00063 int const pos = position_ - 1; 00064 00065 // first, deal with indicators 00066 if (PQgetisnull(statement_.result_, statement_.currentRow_, pos) != 0) 00067 { 00068 if (ind == NULL) 00069 { 00070 throw soci_error( 00071 "Null value fetched and no indicator defined."); 00072 } 00073 00074 *ind = i_null; 00075 00076 // no need to convert data if it is null 00077 return; 00078 } 00079 else 00080 { 00081 if (ind != NULL) 00082 { 00083 *ind = i_ok; 00084 } 00085 } 00086 00087 // raw data, in text format 00088 char const * buf = PQgetvalue(statement_.result_, 00089 statement_.currentRow_, pos); 00090 00091 switch (type_) 00092 { 00093 case x_char: 00094 { 00095 char * dest = static_cast<char *>(data_); 00096 *dest = *buf; 00097 } 00098 break; 00099 case x_stdstring: 00100 { 00101 std::string * dest = static_cast<std::string *>(data_); 00102 dest->assign(buf); 00103 } 00104 break; 00105 case x_short: 00106 { 00107 short * dest = static_cast<short *>(data_); 00108 *dest = string_to_integer<short>(buf); 00109 } 00110 break; 00111 case x_integer: 00112 { 00113 int * dest = static_cast<int *>(data_); 00114 *dest = string_to_integer<int>(buf); 00115 } 00116 break; 00117 case x_unsigned_long: 00118 { 00119 unsigned long * dest = static_cast<unsigned long *>(data_); 00120 *dest = string_to_unsigned_integer<unsigned long>(buf); 00121 } 00122 break; 00123 case x_long_long: 00124 { 00125 long long * dest = static_cast<long long *>(data_); 00126 *dest = string_to_integer<long long>(buf); 00127 } 00128 break; 00129 case x_double: 00130 { 00131 double * dest = static_cast<double *>(data_); 00132 *dest = string_to_double(buf); 00133 } 00134 break; 00135 case x_stdtm: 00136 { 00137 // attempt to parse the string and convert to std::tm 00138 std::tm * dest = static_cast<std::tm *>(data_); 00139 parse_std_tm(buf, *dest); 00140 } 00141 break; 00142 case x_rowid: 00143 { 00144 // RowID is internally identical to unsigned long 00145 00146 rowid * rid = static_cast<rowid *>(data_); 00147 postgresql_rowid_backend * rbe 00148 = static_cast<postgresql_rowid_backend *>( 00149 rid->get_backend()); 00150 00151 rbe->value_ = string_to_unsigned_integer<unsigned long>(buf); 00152 } 00153 break; 00154 case x_blob: 00155 { 00156 unsigned long oid = 00157 string_to_unsigned_integer<unsigned long>(buf); 00158 00159 int fd = lo_open(statement_.session_.conn_, oid, 00160 INV_READ | INV_WRITE); 00161 if (fd == -1) 00162 { 00163 throw soci_error("Cannot open the blob object."); 00164 } 00165 00166 blob * b = static_cast<blob *>(data_); 00167 postgresql_blob_backend * bbe 00168 = static_cast<postgresql_blob_backend *>(b->get_backend()); 00169 00170 if (bbe->fd_ != -1) 00171 { 00172 lo_close(statement_.session_.conn_, bbe->fd_); 00173 } 00174 00175 bbe->fd_ = fd; 00176 bbe->oid_ = oid; 00177 } 00178 break; 00179 00180 default: 00181 throw soci_error("Into element used with non-supported type."); 00182 } 00183 } 00184 } 00185 00186 void postgresql_standard_into_type_backend::clean_up() 00187 { 00188 // nothing to do here 00189 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1