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 #define SOCI_ODBC_SOURCE 00009 #include "soci-odbc.h" 00010 #include <cctype> 00011 #include <cstdio> 00012 #include <cstring> 00013 #include <ctime> 00014 #include <sstream> 00015 00016 using namespace soci; 00017 using namespace soci::details; 00018 00019 void odbc_vector_into_type_backend::prepare_indicators(std::size_t size) 00020 { 00021 if (size == 0) 00022 { 00023 throw soci_error("Vectors of size 0 are not allowed."); 00024 } 00025 00026 indHolderVec_.resize(size); 00027 indHolders_ = &indHolderVec_[0]; 00028 } 00029 00030 void odbc_vector_into_type_backend::define_by_pos( 00031 int &position, void *data, exchange_type type) 00032 { 00033 data_ = data; // for future reference 00034 type_ = type; // for future reference 00035 00036 SQLINTEGER size = 0; // also dummy 00037 00038 switch (type) 00039 { 00040 // simple cases 00041 case x_short: 00042 { 00043 odbcType_ = SQL_C_SSHORT; 00044 size = sizeof(short); 00045 std::vector<short> *vp = static_cast<std::vector<short> *>(data); 00046 std::vector<short> &v(*vp); 00047 prepare_indicators(v.size()); 00048 data = &v[0]; 00049 } 00050 break; 00051 case x_integer: 00052 { 00053 odbcType_ = SQL_C_SLONG; 00054 size = sizeof(long); 00055 std::vector<long> *vp = static_cast<std::vector<long> *>(data); 00056 std::vector<long> &v(*vp); 00057 prepare_indicators(v.size()); 00058 data = &v[0]; 00059 } 00060 break; 00061 case x_unsigned_long: 00062 { 00063 odbcType_ = SQL_C_ULONG; 00064 size = sizeof(unsigned long); 00065 std::vector<unsigned long> *vp 00066 = static_cast<std::vector<unsigned long> *>(data); 00067 std::vector<unsigned long> &v(*vp); 00068 prepare_indicators(v.size()); 00069 data = &v[0]; 00070 } 00071 break; 00072 case x_double: 00073 { 00074 odbcType_ = SQL_C_DOUBLE; 00075 size = sizeof(double); 00076 std::vector<double> *vp = static_cast<std::vector<double> *>(data); 00077 std::vector<double> &v(*vp); 00078 prepare_indicators(v.size()); 00079 data = &v[0]; 00080 } 00081 break; 00082 00083 // cases that require adjustments and buffer management 00084 00085 case x_char: 00086 { 00087 odbcType_ = SQL_C_CHAR; 00088 00089 std::vector<char> *v 00090 = static_cast<std::vector<char> *>(data); 00091 00092 prepare_indicators(v->size()); 00093 00094 size = sizeof(char) * 2; 00095 std::size_t bufSize = size * v->size(); 00096 00097 colSize_ = size; 00098 00099 buf_ = new char[bufSize]; 00100 data = buf_; 00101 } 00102 break; 00103 case x_stdstring: 00104 { 00105 odbcType_ = SQL_C_CHAR; 00106 std::vector<std::string> *v 00107 = static_cast<std::vector<std::string> *>(data); 00108 colSize_ = statement_.column_size(position) + 1; 00109 std::size_t bufSize = colSize_ * v->size(); 00110 buf_ = new char[bufSize]; 00111 00112 prepare_indicators(v->size()); 00113 00114 size = static_cast<SQLINTEGER>(colSize_); 00115 data = buf_; 00116 } 00117 break; 00118 case x_stdtm: 00119 { 00120 odbcType_ = SQL_C_TYPE_TIMESTAMP; 00121 std::vector<std::tm> *v 00122 = static_cast<std::vector<std::tm> *>(data); 00123 00124 prepare_indicators(v->size()); 00125 00126 size = sizeof(TIMESTAMP_STRUCT); 00127 colSize_ = size; 00128 00129 std::size_t bufSize = size * v->size(); 00130 00131 buf_ = new char[bufSize]; 00132 data = buf_; 00133 } 00134 break; 00135 00136 case x_statement: break; // not supported 00137 case x_rowid: break; // not supported 00138 case x_blob: break; // not supported 00139 } 00140 00141 SQLRETURN rc = SQLBindCol(statement_.hstmt_, static_cast<SQLUSMALLINT>(position++), 00142 odbcType_, data, size, indHolders_); 00143 if (is_odbc_error(rc)) 00144 { 00145 throw odbc_soci_error(SQL_HANDLE_STMT, statement_.hstmt_, 00146 "vector into type define by pos"); 00147 } 00148 } 00149 00150 void odbc_vector_into_type_backend::pre_fetch() 00151 { 00152 // nothing to do for the supported types 00153 } 00154 00155 void odbc_vector_into_type_backend::post_fetch(bool gotData, indicator *ind) 00156 { 00157 if (gotData) 00158 { 00159 // first, deal with data 00160 00161 // only std::string, std::tm and Statement need special handling 00162 if (type_ == x_char) 00163 { 00164 std::vector<char> *vp 00165 = static_cast<std::vector<char> *>(data_); 00166 00167 std::vector<char> &v(*vp); 00168 char *pos = buf_; 00169 std::size_t const vsize = v.size(); 00170 for (std::size_t i = 0; i != vsize; ++i) 00171 { 00172 v[i] = *pos; 00173 pos += colSize_; 00174 } 00175 } 00176 if (type_ == x_stdstring) 00177 { 00178 std::vector<std::string> *vp 00179 = static_cast<std::vector<std::string> *>(data_); 00180 00181 std::vector<std::string> &v(*vp); 00182 00183 char *pos = buf_; 00184 std::size_t const vsize = v.size(); 00185 for (std::size_t i = 0; i != vsize; ++i) 00186 { 00187 v[i].assign(pos, strlen(pos)); 00188 pos += colSize_; 00189 } 00190 } 00191 else if (type_ == x_stdtm) 00192 { 00193 std::vector<std::tm> *vp 00194 = static_cast<std::vector<std::tm> *>(data_); 00195 00196 std::vector<std::tm> &v(*vp); 00197 char *pos = buf_; 00198 std::size_t const vsize = v.size(); 00199 for (std::size_t i = 0; i != vsize; ++i) 00200 { 00201 std::tm t; 00202 00203 TIMESTAMP_STRUCT * ts = reinterpret_cast<TIMESTAMP_STRUCT*>(pos); 00204 t.tm_isdst = -1; 00205 t.tm_year = ts->year - 1900; 00206 t.tm_mon = ts->month - 1; 00207 t.tm_mday = ts->day; 00208 t.tm_hour = ts->hour; 00209 t.tm_min = ts->minute; 00210 t.tm_sec = ts->second; 00211 00212 // normalize and compute the remaining fields 00213 std::mktime(&t); 00214 v[i] = t; 00215 pos += colSize_; 00216 } 00217 } 00218 00219 // then - deal with indicators 00220 if (ind != NULL) 00221 { 00222 std::size_t const indSize = statement_.get_number_of_rows(); 00223 for (std::size_t i = 0; i != indSize; ++i) 00224 { 00225 if (indHolderVec_[i] > 0) 00226 { 00227 ind[i] = i_ok; 00228 } 00229 else if (indHolderVec_[i] == SQL_NULL_DATA) 00230 { 00231 ind[i] = i_null; 00232 } 00233 else 00234 { 00235 ind[i] = i_truncated; 00236 } 00237 } 00238 } 00239 else 00240 { 00241 std::size_t const indSize = statement_.get_number_of_rows(); 00242 for (std::size_t i = 0; i != indSize; ++i) 00243 { 00244 if (indHolderVec_[i] == SQL_NULL_DATA) 00245 { 00246 // fetched null and no indicator - programming error! 00247 throw soci_error( 00248 "Null value fetched and no indicator defined."); 00249 } 00250 } 00251 } 00252 } 00253 else // gotData == false 00254 { 00255 // nothing to do here, vectors are truncated anyway 00256 } 00257 } 00258 00259 void odbc_vector_into_type_backend::resize(std::size_t sz) 00260 { 00261 indHolderVec_.resize(sz); 00262 switch (type_) 00263 { 00264 // simple cases 00265 case x_char: 00266 { 00267 std::vector<char> *v = static_cast<std::vector<char> *>(data_); 00268 v->resize(sz); 00269 } 00270 break; 00271 case x_short: 00272 { 00273 std::vector<short> *v = static_cast<std::vector<short> *>(data_); 00274 v->resize(sz); 00275 } 00276 break; 00277 case x_integer: 00278 { 00279 std::vector<long> *v = static_cast<std::vector<long> *>(data_); 00280 v->resize(sz); 00281 } 00282 break; 00283 case x_unsigned_long: 00284 { 00285 std::vector<unsigned long> *v 00286 = static_cast<std::vector<unsigned long> *>(data_); 00287 v->resize(sz); 00288 } 00289 break; 00290 case x_double: 00291 { 00292 std::vector<double> *v 00293 = static_cast<std::vector<double> *>(data_); 00294 v->resize(sz); 00295 } 00296 break; 00297 case x_stdstring: 00298 { 00299 std::vector<std::string> *v 00300 = static_cast<std::vector<std::string> *>(data_); 00301 v->resize(sz); 00302 } 00303 break; 00304 case x_stdtm: 00305 { 00306 std::vector<std::tm> *v 00307 = static_cast<std::vector<std::tm> *>(data_); 00308 v->resize(sz); 00309 } 00310 break; 00311 00312 case x_statement: break; // not supported 00313 case x_rowid: break; // not supported 00314 case x_blob: break; // not supported 00315 } 00316 } 00317 00318 std::size_t odbc_vector_into_type_backend::size() 00319 { 00320 std::size_t sz = 0; // dummy initialization to please the compiler 00321 switch (type_) 00322 { 00323 // simple cases 00324 case x_char: 00325 { 00326 std::vector<char> *v = static_cast<std::vector<char> *>(data_); 00327 sz = v->size(); 00328 } 00329 break; 00330 case x_short: 00331 { 00332 std::vector<short> *v = static_cast<std::vector<short> *>(data_); 00333 sz = v->size(); 00334 } 00335 break; 00336 case x_integer: 00337 { 00338 std::vector<long> *v = static_cast<std::vector<long> *>(data_); 00339 sz = v->size(); 00340 } 00341 break; 00342 case x_unsigned_long: 00343 { 00344 std::vector<unsigned long> *v 00345 = static_cast<std::vector<unsigned long> *>(data_); 00346 sz = v->size(); 00347 } 00348 break; 00349 case x_double: 00350 { 00351 std::vector<double> *v 00352 = static_cast<std::vector<double> *>(data_); 00353 sz = v->size(); 00354 } 00355 break; 00356 case x_stdstring: 00357 { 00358 std::vector<std::string> *v 00359 = static_cast<std::vector<std::string> *>(data_); 00360 sz = v->size(); 00361 } 00362 break; 00363 case x_stdtm: 00364 { 00365 std::vector<std::tm> *v 00366 = static_cast<std::vector<std::tm> *>(data_); 00367 sz = v->size(); 00368 } 00369 break; 00370 00371 case x_statement: break; // not supported 00372 case x_rowid: break; // not supported 00373 case x_blob: break; // not supported 00374 } 00375 00376 return sz; 00377 } 00378 00379 void odbc_vector_into_type_backend::clean_up() 00380 { 00381 if (buf_ != NULL) 00382 { 00383 delete [] buf_; 00384 buf_ = NULL; 00385 } 00386 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1