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 #include <cctype> 00012 #include <cstdio> 00013 #include <cstring> 00014 #include <ctime> 00015 #include <sstream> 00016 00017 #ifdef _MSC_VER 00018 #pragma warning(disable:4355) 00019 #endif 00020 00021 using namespace soci; 00022 using namespace soci::details; 00023 using namespace soci::details::oracle; 00024 00025 void oracle_vector_use_type_backend::prepare_indicators(std::size_t size) 00026 { 00027 if (size == 0) 00028 { 00029 throw soci_error("Vectors of size 0 are not allowed."); 00030 } 00031 00032 indOCIHolderVec_.resize(size); 00033 indOCIHolders_ = &indOCIHolderVec_[0]; 00034 } 00035 00036 void oracle_vector_use_type_backend::prepare_for_bind( 00037 void *&data, sb4 &size, ub2 &oracleType) 00038 { 00039 switch (type_) 00040 { 00041 // simple cases 00042 case x_char: 00043 { 00044 oracleType = SQLT_AFC; 00045 size = sizeof(char); 00046 std::vector<char> *vp = static_cast<std::vector<char> *>(data); 00047 std::vector<char> &v(*vp); 00048 prepare_indicators(v.size()); 00049 data = &v[0]; 00050 } 00051 break; 00052 case x_short: 00053 { 00054 oracleType = SQLT_INT; 00055 size = sizeof(short); 00056 std::vector<short> *vp = static_cast<std::vector<short> *>(data); 00057 std::vector<short> &v(*vp); 00058 prepare_indicators(v.size()); 00059 data = &v[0]; 00060 } 00061 break; 00062 case x_integer: 00063 { 00064 oracleType = SQLT_INT; 00065 size = sizeof(int); 00066 std::vector<int> *vp = static_cast<std::vector<int> *>(data); 00067 std::vector<int> &v(*vp); 00068 prepare_indicators(v.size()); 00069 data = &v[0]; 00070 } 00071 break; 00072 case x_unsigned_long: 00073 { 00074 oracleType = SQLT_UIN; 00075 size = sizeof(unsigned long); 00076 std::vector<unsigned long> *vp 00077 = static_cast<std::vector<unsigned long> *>(data); 00078 std::vector<unsigned long> &v(*vp); 00079 prepare_indicators(v.size()); 00080 data = &v[0]; 00081 } 00082 break; 00083 case x_double: 00084 { 00085 oracleType = SQLT_FLT; 00086 size = sizeof(double); 00087 std::vector<double> *vp = static_cast<std::vector<double> *>(data); 00088 std::vector<double> &v(*vp); 00089 prepare_indicators(v.size()); 00090 data = &v[0]; 00091 } 00092 break; 00093 00094 // cases that require adjustments and buffer management 00095 00096 case x_long_long: 00097 { 00098 std::vector<long long> *vp 00099 = static_cast<std::vector<long long> *>(data); 00100 std::vector<long long> &v(*vp); 00101 00102 std::size_t const vecSize = v.size(); 00103 std::size_t const entrySize = 100; // arbitrary 00104 std::size_t const bufSize = entrySize * vecSize; 00105 buf_ = new char[bufSize]; 00106 00107 oracleType = SQLT_STR; 00108 data = buf_; 00109 size = entrySize; 00110 00111 prepare_indicators(vecSize); 00112 } 00113 break; 00114 case x_stdstring: 00115 { 00116 std::vector<std::string> *vp 00117 = static_cast<std::vector<std::string> *>(data); 00118 std::vector<std::string> &v(*vp); 00119 00120 std::size_t maxSize = 0; 00121 std::size_t const vecSize = v.size(); 00122 prepare_indicators(vecSize); 00123 for (std::size_t i = 0; i != vecSize; ++i) 00124 { 00125 std::size_t sz = v[i].length(); 00126 sizes_.push_back(static_cast<ub2>(sz)); 00127 maxSize = sz > maxSize ? sz : maxSize; 00128 } 00129 00130 buf_ = new char[maxSize * vecSize]; 00131 char *pos = buf_; 00132 for (std::size_t i = 0; i != vecSize; ++i) 00133 { 00134 strncpy(pos, v[i].c_str(), v[i].length()); 00135 pos += maxSize; 00136 } 00137 00138 oracleType = SQLT_CHR; 00139 data = buf_; 00140 size = static_cast<sb4>(maxSize); 00141 } 00142 break; 00143 case x_stdtm: 00144 { 00145 std::vector<std::tm> *vp 00146 = static_cast<std::vector<std::tm> *>(data); 00147 00148 prepare_indicators(vp->size()); 00149 00150 sb4 const dlen = 7; // size of SQLT_DAT 00151 buf_ = new char[dlen * vp->size()]; 00152 00153 oracleType = SQLT_DAT; 00154 data = buf_; 00155 size = dlen; 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 00165 void oracle_vector_use_type_backend::bind_by_pos(int &position, 00166 void *data, exchange_type type) 00167 { 00168 data_ = data; // for future reference 00169 type_ = type; // for future reference 00170 00171 ub2 oracleType; 00172 sb4 size; 00173 00174 prepare_for_bind(data, size, oracleType); 00175 00176 ub2 *sizesP = 0; // used only for std::string 00177 if (type == x_stdstring) 00178 { 00179 sizesP = &sizes_[0]; 00180 } 00181 00182 sword res = OCIBindByPos(statement_.stmtp_, &bindp_, 00183 statement_.session_.errhp_, 00184 position++, data, size, oracleType, 00185 indOCIHolders_, sizesP, 0, 0, 0, OCI_DEFAULT); 00186 if (res != OCI_SUCCESS) 00187 { 00188 throw_oracle_soci_error(res, statement_.session_.errhp_); 00189 } 00190 } 00191 00192 void oracle_vector_use_type_backend::bind_by_name( 00193 std::string const &name, void *data, exchange_type type) 00194 { 00195 data_ = data; // for future reference 00196 type_ = type; // for future reference 00197 00198 ub2 oracleType; 00199 sb4 size; 00200 00201 prepare_for_bind(data, size, oracleType); 00202 00203 ub2 *sizesP = 0; // used only for std::string 00204 if (type == x_stdstring) 00205 { 00206 sizesP = &sizes_[0]; 00207 } 00208 00209 sword res = OCIBindByName(statement_.stmtp_, &bindp_, 00210 statement_.session_.errhp_, 00211 reinterpret_cast<text*>(const_cast<char*>(name.c_str())), 00212 static_cast<sb4>(name.size()), 00213 data, size, oracleType, 00214 indOCIHolders_, sizesP, 0, 0, 0, OCI_DEFAULT); 00215 if (res != OCI_SUCCESS) 00216 { 00217 throw_oracle_soci_error(res, statement_.session_.errhp_); 00218 } 00219 } 00220 00221 void oracle_vector_use_type_backend::pre_use(indicator const *ind) 00222 { 00223 // first deal with data 00224 if (type_ == x_stdstring) 00225 { 00226 // nothing to do - it's already done during bind 00227 // (and it's probably impossible to separate them, because 00228 // changes in the string size could not be handled here) 00229 } 00230 else if (type_ == x_long_long) 00231 { 00232 std::vector<long long> *vp 00233 = static_cast<std::vector<long long> *>(data_); 00234 std::vector<long long> &v(*vp); 00235 00236 char *pos = buf_; 00237 std::size_t const entrySize = 100; // arbitrary, but consistent 00238 std::size_t const vecSize = v.size(); 00239 for (std::size_t i = 0; i != vecSize; ++i) 00240 { 00241 snprintf(pos, entrySize, "%lld", v[i]); 00242 pos += entrySize; 00243 } 00244 } 00245 else if (type_ == x_stdtm) 00246 { 00247 std::vector<std::tm> *vp 00248 = static_cast<std::vector<std::tm> *>(data_); 00249 std::vector<std::tm> &v(*vp); 00250 00251 ub1* pos = reinterpret_cast<ub1*>(buf_); 00252 std::size_t const vsize = v.size(); 00253 for (std::size_t i = 0; i != vsize; ++i) 00254 { 00255 *pos++ = static_cast<ub1>(100 + (1900 + v[i].tm_year) / 100); 00256 *pos++ = static_cast<ub1>(100 + v[i].tm_year % 100); 00257 *pos++ = static_cast<ub1>(v[i].tm_mon + 1); 00258 *pos++ = static_cast<ub1>(v[i].tm_mday); 00259 *pos++ = static_cast<ub1>(v[i].tm_hour + 1); 00260 *pos++ = static_cast<ub1>(v[i].tm_min + 1); 00261 *pos++ = static_cast<ub1>(v[i].tm_sec + 1); 00262 } 00263 } 00264 00265 // then handle indicators 00266 if (ind != NULL) 00267 { 00268 std::size_t const vsize = size(); 00269 for (std::size_t i = 0; i != vsize; ++i, ++ind) 00270 { 00271 if (*ind == i_null) 00272 { 00273 indOCIHolderVec_[i] = -1; // null 00274 } 00275 else 00276 { 00277 indOCIHolderVec_[i] = 0; // value is OK 00278 } 00279 } 00280 } 00281 else 00282 { 00283 // no indicators - treat all fields as OK 00284 std::size_t const vsize = size(); 00285 for (std::size_t i = 0; i != vsize; ++i, ++ind) 00286 { 00287 indOCIHolderVec_[i] = 0; // value is OK 00288 } 00289 } 00290 } 00291 00292 std::size_t oracle_vector_use_type_backend::size() 00293 { 00294 std::size_t sz = 0; // dummy initialization to please the compiler 00295 switch (type_) 00296 { 00297 // simple cases 00298 case x_char: 00299 { 00300 std::vector<char> *vp = static_cast<std::vector<char> *>(data_); 00301 sz = vp->size(); 00302 } 00303 break; 00304 case x_short: 00305 { 00306 std::vector<short> *vp = static_cast<std::vector<short> *>(data_); 00307 sz = vp->size(); 00308 } 00309 break; 00310 case x_integer: 00311 { 00312 std::vector<int> *vp = static_cast<std::vector<int> *>(data_); 00313 sz = vp->size(); 00314 } 00315 break; 00316 case x_unsigned_long: 00317 { 00318 std::vector<unsigned long> *vp 00319 = static_cast<std::vector<unsigned long> *>(data_); 00320 sz = vp->size(); 00321 } 00322 break; 00323 case x_long_long: 00324 { 00325 std::vector<long long> *vp 00326 = static_cast<std::vector<long long> *>(data_); 00327 sz = vp->size(); 00328 } 00329 break; 00330 case x_double: 00331 { 00332 std::vector<double> *vp 00333 = static_cast<std::vector<double> *>(data_); 00334 sz = vp->size(); 00335 } 00336 break; 00337 case x_stdstring: 00338 { 00339 std::vector<std::string> *vp 00340 = static_cast<std::vector<std::string> *>(data_); 00341 sz = vp->size(); 00342 } 00343 break; 00344 case x_stdtm: 00345 { 00346 std::vector<std::tm> *vp 00347 = static_cast<std::vector<std::tm> *>(data_); 00348 sz = vp->size(); 00349 } 00350 break; 00351 00352 case x_statement: break; // not supported 00353 case x_rowid: break; // not supported 00354 case x_blob: break; // not supported 00355 } 00356 00357 return sz; 00358 } 00359 00360 void oracle_vector_use_type_backend::clean_up() 00361 { 00362 if (buf_ != NULL) 00363 { 00364 delete [] buf_; 00365 buf_ = NULL; 00366 } 00367 00368 if (bindp_ != NULL) 00369 { 00370 OCIHandleFree(bindp_, OCI_HTYPE_DEFINE); 00371 bindp_ = NULL; 00372 } 00373 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1