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 00010 #include "soci-oracle.h" 00011 #include "error.h" 00012 // 00013 #if defined(SOCI_HEADERS_BURIED) 00014 # include <soci/core/soci-backend.h> 00015 #else 00016 # include <soci-backend.h> 00017 #endif 00018 // 00019 #include <cctype> 00020 #include <cstdio> 00021 #include <cstring> 00022 #include <ctime> 00023 #include <limits> 00024 #include <sstream> 00025 00026 #ifdef _MSC_VER 00027 #pragma warning(disable:4355) 00028 #endif 00029 00030 using namespace soci; 00031 using namespace soci::details; 00032 using namespace soci::details::oracle; 00033 00034 oracle_statement_backend::oracle_statement_backend(oracle_session_backend &session) 00035 : session_(session), stmtp_(NULL), boundByName_(false), boundByPos_(false), 00036 noData_(false) 00037 { 00038 } 00039 00040 void oracle_statement_backend::alloc() 00041 { 00042 sword res = OCIHandleAlloc(session_.envhp_, 00043 reinterpret_cast<dvoid**>(&stmtp_), 00044 OCI_HTYPE_STMT, 0, 0); 00045 if (res != OCI_SUCCESS) 00046 { 00047 throw soci_error("Cannot allocate statement handle"); 00048 } 00049 } 00050 00051 void oracle_statement_backend::clean_up() 00052 { 00053 // deallocate statement handle 00054 if (stmtp_ != NULL) 00055 { 00056 OCIHandleFree(stmtp_, OCI_HTYPE_STMT); 00057 stmtp_ = NULL; 00058 } 00059 00060 boundByName_ = false; 00061 boundByPos_ = false; 00062 } 00063 00064 void oracle_statement_backend::prepare(std::string const &query, 00065 statement_type /* eType */) 00066 { 00067 sb4 stmtLen = static_cast<sb4>(query.size()); 00068 sword res = OCIStmtPrepare(stmtp_, 00069 session_.errhp_, 00070 reinterpret_cast<text*>(const_cast<char*>(query.c_str())), 00071 stmtLen, OCI_V7_SYNTAX, OCI_DEFAULT); 00072 if (res != OCI_SUCCESS) 00073 { 00074 throw_oracle_soci_error(res, session_.errhp_); 00075 } 00076 } 00077 00078 statement_backend::exec_fetch_result oracle_statement_backend::execute(int number) 00079 { 00080 sword res = OCIStmtExecute(session_.svchp_, stmtp_, session_.errhp_, 00081 static_cast<ub4>(number), 0, 0, 0, OCI_DEFAULT); 00082 00083 if (res == OCI_SUCCESS || res == OCI_SUCCESS_WITH_INFO) 00084 { 00085 return ef_success; 00086 } 00087 else if (res == OCI_NO_DATA) 00088 { 00089 noData_ = true; 00090 return ef_no_data; 00091 } 00092 else 00093 { 00094 throw_oracle_soci_error(res, session_.errhp_); 00095 return ef_no_data; // unreachable dummy return to please the compiler 00096 } 00097 } 00098 00099 statement_backend::exec_fetch_result oracle_statement_backend::fetch(int number) 00100 { 00101 if (noData_) 00102 { 00103 return ef_no_data; 00104 } 00105 00106 sword res = OCIStmtFetch(stmtp_, session_.errhp_, 00107 static_cast<ub4>(number), OCI_FETCH_NEXT, OCI_DEFAULT); 00108 00109 if (res == OCI_SUCCESS || res == OCI_SUCCESS_WITH_INFO) 00110 { 00111 return ef_success; 00112 } 00113 else if (res == OCI_NO_DATA) 00114 { 00115 noData_ = true; 00116 return ef_no_data; 00117 } 00118 else 00119 { 00120 throw_oracle_soci_error(res, session_.errhp_); 00121 return ef_no_data; // unreachable dummy return to please the compiler 00122 } 00123 } 00124 00125 int oracle_statement_backend::get_number_of_rows() 00126 { 00127 int rows; 00128 sword res = OCIAttrGet(static_cast<dvoid*>(stmtp_), 00129 static_cast<ub4>(OCI_HTYPE_STMT), static_cast<dvoid*>(&rows), 00130 0, static_cast<ub4>(OCI_ATTR_ROWS_FETCHED), session_.errhp_); 00131 00132 if (res != OCI_SUCCESS) 00133 { 00134 throw_oracle_soci_error(res, session_.errhp_); 00135 } 00136 00137 return rows; 00138 } 00139 00140 std::string oracle_statement_backend::rewrite_for_procedure_call( 00141 std::string const &query) 00142 { 00143 std::string newQuery("begin "); 00144 newQuery += query; 00145 newQuery += "; end;"; 00146 return newQuery; 00147 } 00148 00149 int oracle_statement_backend::prepare_for_describe() 00150 { 00151 sword res = OCIStmtExecute(session_.svchp_, stmtp_, session_.errhp_, 00152 1, 0, 0, 0, OCI_DESCRIBE_ONLY); 00153 if (res != OCI_SUCCESS) 00154 { 00155 throw_oracle_soci_error(res, session_.errhp_); 00156 } 00157 00158 int cols; 00159 res = OCIAttrGet(static_cast<dvoid*>(stmtp_), 00160 static_cast<ub4>(OCI_HTYPE_STMT), static_cast<dvoid*>(&cols), 00161 0, static_cast<ub4>(OCI_ATTR_PARAM_COUNT), session_.errhp_); 00162 00163 if (res != OCI_SUCCESS) 00164 { 00165 throw_oracle_soci_error(res, session_.errhp_); 00166 } 00167 00168 return cols; 00169 } 00170 00171 void oracle_statement_backend::describe_column(int colNum, data_type &type, 00172 std::string &columnName) 00173 { 00174 int size; 00175 int precision; 00176 int scale; 00177 00178 ub2 dbtype; 00179 text* dbname; 00180 ub4 nameLength; 00181 00182 ub2 dbsize; 00183 sb2 dbprec; 00184 ub1 dbscale; //sb2 in some versions of Oracle? 00185 00186 // Get the column handle 00187 OCIParam* colhd; 00188 sword res = OCIParamGet(reinterpret_cast<dvoid*>(stmtp_), 00189 static_cast<ub4>(OCI_HTYPE_STMT), 00190 reinterpret_cast<OCIError*>(session_.errhp_), 00191 reinterpret_cast<dvoid**>(&colhd), 00192 static_cast<ub4>(colNum)); 00193 if (res != OCI_SUCCESS) 00194 { 00195 throw_oracle_soci_error(res, session_.errhp_); 00196 } 00197 00198 // Get the column name 00199 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00200 static_cast<ub4>(OCI_DTYPE_PARAM), 00201 reinterpret_cast<dvoid**>(&dbname), 00202 reinterpret_cast<ub4*>(&nameLength), 00203 static_cast<ub4>(OCI_ATTR_NAME), 00204 reinterpret_cast<OCIError*>(session_.errhp_)); 00205 if (res != OCI_SUCCESS) 00206 { 00207 throw_oracle_soci_error(res, session_.errhp_); 00208 } 00209 00210 // Get the column type 00211 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00212 static_cast<ub4>(OCI_DTYPE_PARAM), 00213 reinterpret_cast<dvoid*>(&dbtype), 00214 0, 00215 static_cast<ub4>(OCI_ATTR_DATA_TYPE), 00216 reinterpret_cast<OCIError*>(session_.errhp_)); 00217 if (res != OCI_SUCCESS) 00218 { 00219 throw_oracle_soci_error(res, session_.errhp_); 00220 } 00221 00222 // get the data size 00223 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00224 static_cast<ub4>(OCI_DTYPE_PARAM), 00225 reinterpret_cast<dvoid*>(&dbsize), 00226 0, 00227 static_cast<ub4>(OCI_ATTR_DATA_SIZE), 00228 reinterpret_cast<OCIError*>(session_.errhp_)); 00229 if (res != OCI_SUCCESS) 00230 { 00231 throw_oracle_soci_error(res, session_.errhp_); 00232 } 00233 00234 // get the precision 00235 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00236 static_cast<ub4>(OCI_DTYPE_PARAM), 00237 reinterpret_cast<dvoid*>(&dbprec), 00238 0, 00239 static_cast<ub4>(OCI_ATTR_PRECISION), 00240 reinterpret_cast<OCIError*>(session_.errhp_)); 00241 if (res != OCI_SUCCESS) 00242 { 00243 throw_oracle_soci_error(res, session_.errhp_); 00244 } 00245 00246 // get the scale 00247 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00248 static_cast<ub4>(OCI_DTYPE_PARAM), 00249 reinterpret_cast<dvoid*>(&dbscale), 00250 0, 00251 static_cast<ub4>(OCI_ATTR_SCALE), 00252 reinterpret_cast<OCIError*>(session_.errhp_)); 00253 if (res != OCI_SUCCESS) 00254 { 00255 throw_oracle_soci_error(res, session_.errhp_); 00256 } 00257 00258 columnName.assign(dbname, dbname + nameLength); 00259 size = static_cast<int>(dbsize); 00260 precision = static_cast<int>(dbprec); 00261 scale = static_cast<int>(dbscale); 00262 00263 switch (dbtype) 00264 { 00265 case SQLT_CHR: 00266 case SQLT_AFC: 00267 type = dt_string; 00268 break; 00269 case SQLT_NUM: 00270 if (scale > 0) 00271 { 00272 type = dt_double; 00273 } 00274 else if (precision < std::numeric_limits<int>::digits10) 00275 { 00276 type = dt_integer; 00277 } 00278 else 00279 { 00280 type = dt_long_long; 00281 } 00282 break; 00283 case SQLT_DAT: 00284 type = dt_date; 00285 break; 00286 } 00287 } 00288 00289 std::size_t oracle_statement_backend::column_size(int position) 00290 { 00291 // Note: we may want to optimize so that the OCI_DESCRIBE_ONLY call 00292 // happens only once per statement. 00293 // Possibly use existing statement::describe() / make column prop 00294 // access lazy at same time 00295 00296 int colSize(0); 00297 00298 sword res = OCIStmtExecute(session_.svchp_, stmtp_, 00299 session_.errhp_, 1, 0, 0, 0, OCI_DESCRIBE_ONLY); 00300 if (res != OCI_SUCCESS) 00301 { 00302 throw_oracle_soci_error(res, session_.errhp_); 00303 } 00304 00305 // Get The Column Handle 00306 OCIParam* colhd; 00307 res = OCIParamGet(reinterpret_cast<dvoid*>(stmtp_), 00308 static_cast<ub4>(OCI_HTYPE_STMT), 00309 reinterpret_cast<OCIError*>(session_.errhp_), 00310 reinterpret_cast<dvoid**>(&colhd), 00311 static_cast<ub4>(position)); 00312 if (res != OCI_SUCCESS) 00313 { 00314 throw_oracle_soci_error(res, session_.errhp_); 00315 } 00316 00317 // Get The Data Size 00318 res = OCIAttrGet(reinterpret_cast<dvoid*>(colhd), 00319 static_cast<ub4>(OCI_DTYPE_PARAM), 00320 reinterpret_cast<dvoid*>(&colSize), 00321 0, 00322 static_cast<ub4>(OCI_ATTR_DATA_SIZE), 00323 reinterpret_cast<OCIError*>(session_.errhp_)); 00324 if (res != OCI_SUCCESS) 00325 { 00326 throw_oracle_soci_error(res, session_.errhp_); 00327 } 00328 00329 return static_cast<std::size_t>(colSize); 00330 }
Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1