SOCI Logo Get SOCI at SourceForge.net. Fast, secure and Free Open Source software downloads

statement.cpp

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
SourceForge Logo

Generated on Sun Oct 3 2010 17:42:16 for EXTRAS-SOCI by Doxygen 1.7.1