00001 // 00002 // Copyright (C) 2004-2007 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_ORACLE_SOURCE 00009 #include "soci-oracle.h" 00010 #include "error.h" 00011 // 00012 #if defined(SOCI_HEADERS_BURIED) 00013 # include <soci/core/statement.h> 00014 #else 00015 # include <statement.h> 00016 #endif 00017 // 00018 #include <cctype> 00019 #include <cstdio> 00020 #include <cstring> 00021 #include <cstdlib> 00022 #include <ctime> 00023 #include <sstream> 00024 00025 #ifdef _MSC_VER 00026 #pragma warning(disable:4355) 00027 #endif 00028 00029 using namespace soci; 00030 using namespace soci::details; 00031 using namespace soci::details::oracle; 00032 00033 void oracle_vector_into_type_backend::prepare_indicators(std::size_t size) 00034 { 00035 if (size == 0) 00036 { 00037 throw soci_error("Vectors of size 0 are not allowed."); 00038 } 00039 00040 indOCIHolderVec_.resize(size); 00041 indOCIHolders_ = &indOCIHolderVec_[0]; 00042 00043 sizes_.resize(size); 00044 rCodes_.resize(size); 00045 } 00046 00047 void oracle_vector_into_type_backend::define_by_pos( 00048 int &position, void *data, exchange_type type) 00049 { 00050 data_ = data; // for future reference 00051 type_ = type; // for future reference 00052 00053 ub2 oracleType = 0; // dummy initialization to please the compiler 00054 sb4 size = 0; // also dummy 00055 00056 switch (type) 00057 { 00058 // simple cases 00059 case x_char: 00060 { 00061 oracleType = SQLT_AFC; 00062 size = sizeof(char); 00063 std::vector<char> *vp = static_cast<std::vector<char> *>(data); 00064 std::vector<char> &v(*vp); 00065 prepare_indicators(v.size()); 00066 data = &v[0]; 00067 } 00068 break; 00069 case x_short: 00070 { 00071 oracleType = SQLT_INT; 00072 size = sizeof(short); 00073 std::vector<short> *vp = static_cast<std::vector<short> *>(data); 00074 std::vector<short> &v(*vp); 00075 prepare_indicators(v.size()); 00076 data = &v[0]; 00077 } 00078 break; 00079 case x_integer: 00080 { 00081 oracleType = SQLT_INT; 00082 size = sizeof(int); 00083 std::vector<int> *vp = static_cast<std::vector<int> *>(data); 00084 std::vector<int> &v(*vp); 00085 prepare_indicators(v.size()); 00086 data = &v[0]; 00087 } 00088 break; 00089 case x_unsigned_long: 00090 { 00091 oracleType = SQLT_UIN; 00092 size = sizeof(unsigned long); 00093 std::vector<unsigned long> *vp 00094 = static_cast<std::vector<unsigned long> *>(data); 00095 std::vector<unsigned long> &v(*vp); 00096 prepare_indicators(v.size()); 00097 data = &v[0]; 00098 } 00099 break; 00100 case x_double: 00101 { 00102 oracleType = SQLT_FLT; 00103 size = sizeof(double); 00104 std::vector<double> *vp = static_cast<std::vector<double> *>(data); 00105 std::vector<double> &v(*vp); 00106 prepare_indicators(v.size()); 00107 data = &v[0]; 00108 } 00109 break; 00110 00111 // cases that require adjustments and buffer management 00112 00113 case x_long_long: 00114 { 00115 oracleType = SQLT_STR; 00116 std::vector<long long> *v 00117 = static_cast<std::vector<long long> *>(data); 00118 colSize_ = 100; // arbitrary buffer size for each entry 00119 std::size_t const bufSize = colSize_ * v->size(); 00120 buf_ = new char[bufSize]; 00121 00122 prepare_indicators(v->size()); 00123 00124 size = static_cast<sb4>(colSize_); 00125 data = buf_; 00126 } 00127 break; 00128 case x_stdstring: 00129 { 00130 oracleType = SQLT_CHR; 00131 std::vector<std::string> *v 00132 = static_cast<std::vector<std::string> *>(data); 00133 colSize_ = statement_.column_size(position) + 1; 00134 std::size_t bufSize = colSize_ * v->size(); 00135 buf_ = new char[bufSize]; 00136 00137 prepare_indicators(v->size()); 00138 00139 size = static_cast<sb4>(colSize_); 00140 data = buf_; 00141 } 00142 break; 00143 case x_stdtm: 00144 { 00145 oracleType = SQLT_DAT; 00146 std::vector<std::tm> *v 00147 = static_cast<std::vector<std::tm> *>(data); 00148 00149 prepare_indicators(v->size()); 00150 00151 size = 7; // 7 is the size of SQLT_DAT 00152 std::size_t bufSize = size * v->size(); 00153 00154 buf_ = new char[bufSize]; 00155 data = buf_; 00156 } 00157 break; 00158 00159 case x_statement: break; // not supported 00160 case x_rowid: break; // not supported 00161 case x_blob: break; // not supported 00162 } 00163 00164 sword res = OCIDefineByPos(statement_.stmtp_, &defnp_, 00165 statement_.session_.errhp_, 00166 position++, data, size, oracleType, 00167 indOCIHolders_, &sizes_[0], &rCodes_[0], OCI_DEFAULT); 00168 if (res != OCI_SUCCESS) 00169 { 00170 throw_oracle_soci_error(res, statement_.session_.errhp_); 00171 } 00172 } 00173 00174 void oracle_vector_into_type_backend::pre_fetch() 00175 { 00176 // nothing to do for the supported types 00177 } 00178 00179 void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator *ind) 00180 { 00181 if (gotData) 00182 { 00183 // first, deal with data 00184 00185 // only std::string, std::tm, long long and Statement need special handling 00186 if (type_ == x_stdstring) 00187 { 00188 std::vector<std::string> *vp 00189 = static_cast<std::vector<std::string> *>(data_); 00190 00191 std::vector<std::string> &v(*vp); 00192 00193 char *pos = buf_; 00194 std::size_t const vsize = v.size(); 00195 for (std::size_t i = 0; i != vsize; ++i) 00196 { 00197 if (indOCIHolderVec_[i] != -1) 00198 { 00199 v[i].assign(pos, sizes_[i]); 00200 } 00201 pos += colSize_; 00202 } 00203 } 00204 else if (type_ == x_long_long) 00205 { 00206 std::vector<long long> *vp 00207 = static_cast<std::vector<long long> *>(data_); 00208 00209 std::vector<long long> &v(*vp); 00210 00211 char *pos = buf_; 00212 std::size_t const vsize = v.size(); 00213 for (std::size_t i = 0; i != vsize; ++i) 00214 { 00215 if (indOCIHolderVec_[i] != -1) 00216 { 00217 v[i] = strtoll(pos, NULL, 10); 00218 } 00219 pos += colSize_; 00220 } 00221 } 00222 else if (type_ == x_stdtm) 00223 { 00224 std::vector<std::tm> *vp 00225 = static_cast<std::vector<std::tm> *>(data_); 00226 00227 std::vector<std::tm> &v(*vp); 00228 00229 ub1 *pos = reinterpret_cast<ub1*>(buf_); 00230 std::size_t const vsize = v.size(); 00231 for (std::size_t i = 0; i != vsize; ++i) 00232 { 00233 if (indOCIHolderVec_[i] == -1) 00234 { 00235 pos += 7; // size of SQLT_DAT 00236 } 00237 else 00238 { 00239 std::tm t; 00240 t.tm_isdst = -1; 00241 00242 t.tm_year = (*pos++ - 100) * 100; 00243 t.tm_year += *pos++ - 2000; 00244 t.tm_mon = *pos++ - 1; 00245 t.tm_mday = *pos++; 00246 t.tm_hour = *pos++ - 1; 00247 t.tm_min = *pos++ - 1; 00248 t.tm_sec = *pos++ - 1; 00249 00250 // normalize and compute the remaining fields 00251 std::mktime(&t); 00252 v[i] = t; 00253 } 00254 } 00255 } 00256 else if (type_ == x_statement) 00257 { 00258 statement *st = static_cast<statement *>(data_); 00259 st->define_and_bind(); 00260 } 00261 00262 // then - deal with indicators 00263 if (ind != NULL) 00264 { 00265 std::size_t const indSize = statement_.get_number_of_rows(); 00266 for (std::size_t i = 0; i != indSize; ++i) 00267 { 00268 if (indOCIHolderVec_[i] == 0) 00269 { 00270 ind[i] = i_ok; 00271 } 00272 else if (indOCIHolderVec_[i] == -1) 00273 { 00274 ind[i] = i_null; 00275 } 00276 else 00277 { 00278 ind[i] = i_truncated; 00279 } 00280 } 00281 } 00282 else 00283 { 00284 std::size_t const indSize = indOCIHolderVec_.size(); 00285 for (std::size_t i = 0; i != indSize; ++i) 00286 { 00287 if (indOCIHolderVec_[i] == -1) 00288 { 00289 // fetched null and no indicator - programming error! 00290 throw soci_error( 00291 "Null value fetched and no indicator defined."); 00292 } 00293 } 00294 } 00295 } 00296 else // gotData == false 00297 { 00298 // nothing to do here, vectors are truncated anyway 00299 } 00300 } 00301 00302 void oracle_vector_into_type_backend::resize(std::size_t sz) 00303 { 00304 switch (type_) 00305 { 00306 // simple cases 00307 case x_char: 00308 { 00309 std::vector<char> *v = static_cast<std::vector<char> *>(data_); 00310 v->resize(sz); 00311 } 00312 break; 00313 case x_short: 00314 { 00315 std::vector<short> *v = static_cast<std::vector<short> *>(data_); 00316 v->resize(sz); 00317 } 00318 break; 00319 case x_integer: 00320 { 00321 std::vector<int> *v = static_cast<std::vector<int> *>(data_); 00322 v->resize(sz); 00323 } 00324 break; 00325 case x_unsigned_long: 00326 { 00327 std::vector<unsigned long> *v 00328 = static_cast<std::vector<unsigned long> *>(data_); 00329 v->resize(sz); 00330 } 00331 break; 00332 case x_long_long: 00333 { 00334 std::vector<long long> *v 00335 = static_cast<std::vector<long long> *>(data_); 00336 v->resize(sz); 00337 } 00338 break; 00339 case x_double: 00340 { 00341 std::vector<double> *v 00342 = static_cast<std::vector<double> *>(data_); 00343 v->resize(sz); 00344 } 00345 break; 00346 case x_stdstring: 00347 { 00348 std::vector<std::string> *v 00349 = static_cast<std::vector<std::string> *>(data_); 00350 v->resize(sz); 00351 } 00352 break; 00353 case x_stdtm: 00354 { 00355 std::vector<std::tm> *v 00356 = static_cast<std::vector<std::tm> *>(data_); 00357 v->resize(sz); 00358 } 00359 break; 00360 00361 case x_statement: break; // not supported 00362 case x_rowid: break; // not supported 00363 case x_blob: break; // not supported 00364 } 00365 } 00366 00367 std::size_t oracle_vector_into_type_backend::size() 00368 { 00369 std::size_t sz = 0; // dummy initialization to please the compiler 00370 switch (type_) 00371 { 00372 // simple cases 00373 case x_char: 00374 { 00375 std::vector<char> *v = static_cast<std::vector<char> *>(data_); 00376 sz = v->size(); 00377 } 00378 break; 00379 case x_short: 00380 { 00381 std::vector<short> *v = static_cast<std::vector<short> *>(data_); 00382 sz = v->size(); 00383 } 00384 break; 00385 case x_integer: 00386 { 00387 std::vector<int> *v = static_cast<std::vector<int> *>(data_); 00388 sz = v->size(); 00389 } 00390 break; 00391 case x_unsigned_long: 00392 { 00393 std::vector<unsigned long> *v 00394 = static_cast<std::vector<unsigned long> *>(data_); 00395 sz = v->size(); 00396 } 00397 break; 00398 case x_long_long: 00399 { 00400 std::vector<long long> *v 00401 = static_cast<std::vector<long long> *>(data_); 00402 sz = v->size(); 00403 } 00404 break; 00405 case x_double: 00406 { 00407 std::vector<double> *v 00408 = static_cast<std::vector<double> *>(data_); 00409 sz = v->size(); 00410 } 00411 break; 00412 case x_stdstring: 00413 { 00414 std::vector<std::string> *v 00415 = static_cast<std::vector<std::string> *>(data_); 00416 sz = v->size(); 00417 } 00418 break; 00419 case x_stdtm: 00420 { 00421 std::vector<std::tm> *v 00422 = static_cast<std::vector<std::tm> *>(data_); 00423 sz = v->size(); 00424 } 00425 break; 00426 00427 case x_statement: break; // not supported 00428 case x_rowid: break; // not supported 00429 case x_blob: break; // not supported 00430 } 00431 00432 return sz; 00433 } 00434 00435 void oracle_vector_into_type_backend::clean_up() 00436 { 00437 if (defnp_ != NULL) 00438 { 00439 OCIHandleFree(defnp_, OCI_HTYPE_DEFINE); 00440 defnp_ = NULL; 00441 } 00442 00443 if (buf_ != NULL) 00444 { 00445 delete [] buf_; 00446 buf_ = NULL; 00447 } 00448 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1