From e1fa2e2e2ef912d08095c8f4f90eb6b810f3c107 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 14 Nov 2014 16:24:50 +0200 Subject: Old interface compatibility and testing fixes Now all tests pass for both Oracle and SQL Server. --- odb/oracle/container-statements.hxx | 2 +- odb/oracle/no-id-object-statements.hxx | 2 +- odb/oracle/polymorphic-object-statements.hxx | 8 +- odb/oracle/section-statements.hxx | 3 +- odb/oracle/section-statements.txx | 2 +- odb/oracle/simple-object-statements.hxx | 45 ++++++----- odb/oracle/statement.cxx | 115 ++++++++++++++++++++------- odb/oracle/statement.hxx | 87 +++++++++++--------- 8 files changed, 172 insertions(+), 92 deletions(-) diff --git a/odb/oracle/container-statements.hxx b/odb/oracle/container-statements.hxx index ef1733d..a0a1742 100644 --- a/odb/oracle/container-statements.hxx +++ b/odb/oracle/container-statements.hxx @@ -122,7 +122,7 @@ namespace odb insert_text_, versioned_, // Process if versioned. insert_image_binding_, - false)); + 0)); return *insert_; } diff --git a/odb/oracle/no-id-object-statements.hxx b/odb/oracle/no-id-object-statements.hxx index 0be8dac..fe4d8d0 100644 --- a/odb/oracle/no-id-object-statements.hxx +++ b/odb/oracle/no-id-object-statements.hxx @@ -88,7 +88,7 @@ namespace odb object_traits::persist_statement, object_traits::versioned, // Process if versioned. insert_image_binding_, - false)); + 0)); return *persist_; } diff --git a/odb/oracle/polymorphic-object-statements.hxx b/odb/oracle/polymorphic-object-statements.hxx index 81ea3c3..58ecdaa 100644 --- a/odb/oracle/polymorphic-object-statements.hxx +++ b/odb/oracle/polymorphic-object-statements.hxx @@ -306,7 +306,7 @@ namespace odb object_traits::persist_statement, object_traits::versioned, // Process if versioned. insert_image_binding_, - false)); + 0)); return *persist_; } @@ -366,6 +366,7 @@ namespace odb return extra_statement_cache_.get ( conn_, image_, + id_image (), id_image_binding (), &id_image_binding ()); // Note, not id+version. } @@ -404,8 +405,9 @@ namespace odb root_statements_type& root_statements_; base_statements_type& base_statements_; - extra_statement_cache_ptr - extra_statement_cache_; + extra_statement_cache_ptr extra_statement_cache_; image_type image_; diff --git a/odb/oracle/section-statements.hxx b/odb/oracle/section-statements.hxx index 3d32b65..eb61cc1 100644 --- a/odb/oracle/section-statements.hxx +++ b/odb/oracle/section-statements.hxx @@ -36,6 +36,7 @@ namespace odb typedef ST traits; typedef typename traits::image_type image_type; + typedef typename traits::id_image_type id_image_type; typedef oracle::select_statement select_statement_type; typedef oracle::update_statement update_statement_type; @@ -43,7 +44,7 @@ namespace odb typedef oracle::connection connection_type; section_statements (connection_type&, - image_type&, + image_type&, id_image_type&, binding& id, binding& idv); connection_type& diff --git a/odb/oracle/section-statements.txx b/odb/oracle/section-statements.txx index 391550f..583b706 100644 --- a/odb/oracle/section-statements.txx +++ b/odb/oracle/section-statements.txx @@ -11,7 +11,7 @@ namespace odb template section_statements:: section_statements (connection_type& conn, - image_type& im, + image_type& im, id_image_type&, binding& id, binding& idv) : conn_ (conn), svm_ (0), diff --git a/odb/oracle/simple-object-statements.hxx b/odb/oracle/simple-object-statements.hxx index 18e4270..0ee263a 100644 --- a/odb/oracle/simple-object-statements.hxx +++ b/odb/oracle/simple-object-statements.hxx @@ -39,49 +39,56 @@ namespace odb // deleter function which will be initialized during allocation // (at that point we know that the cache class is defined). // - template + template struct extra_statement_cache_ptr { typedef I image_type; + typedef ID id_image_type; typedef oracle::connection connection_type; extra_statement_cache_ptr (): p_ (0) {} ~extra_statement_cache_ptr () { if (p_ != 0) - (this->*deleter_) (0, 0, 0, 0); + (this->*deleter_) (0, 0, 0, 0, 0); } T& - get (connection_type& c, image_type& im, binding& id, binding* idv) + get (connection_type& c, + image_type& im, id_image_type& idim, + binding& id, binding* idv) { if (p_ == 0) - allocate (&c, &im, &id, (idv != 0 ? idv : &id)); + allocate (&c, &im, &idim, &id, (idv != 0 ? idv : &id)); return *p_; } private: void - allocate (connection_type*, image_type*, binding*, binding*); + allocate (connection_type*, + image_type*, id_image_type*, + binding*, binding*); private: T* p_; void (extra_statement_cache_ptr::*deleter_) ( - connection_type*, image_type*, binding*, binding*); + connection_type*, image_type*, id_image_type*, binding*, binding*); }; - template - void extra_statement_cache_ptr:: - allocate (connection_type* c, image_type* im, binding* id, binding* idv) + template + void extra_statement_cache_ptr:: + allocate (connection_type* c, + image_type* im, id_image_type* idim, + binding* id, binding* idv) { // To reduce object code size, this function acts as both allocator // and deleter. // if (p_ == 0) { - p_ = new T (*c, *im, *id, *idv); - deleter_ = &extra_statement_cache_ptr::allocate; + p_ = new T (*c, *im, *idim, *id, *idv); + deleter_ = &extra_statement_cache_ptr::allocate; } else delete p_; @@ -395,8 +402,8 @@ namespace odb new (details::shared) delete_statement_type ( conn_, object_traits::erase_statement, - id_image_binding_, - true)); // Unique (0 or 1 affected rows). + true, // Unique (0 or 1 affected rows). + id_image_binding_)); return *erase_; } @@ -410,8 +417,7 @@ namespace odb new (details::shared) delete_statement_type ( conn_, object_traits::optimistic_erase_statement, - od_.id_image_binding_, - true)); // Unique (0 or 1 affected rows). + od_.id_image_binding_)); } return *od_.erase_; @@ -423,7 +429,9 @@ namespace odb extra_statement_cache () { return extra_statement_cache_.get ( - conn_, images_[0].obj, id_image_binding_, od_.id_image_binding ()); + conn_, + images_[0].obj, images_[0].id, + id_image_binding_, od_.id_image_binding ()); } public: @@ -470,8 +478,9 @@ namespace odb template friend class polymorphic_derived_object_statements; - extra_statement_cache_ptr - extra_statement_cache_; + extra_statement_cache_ptr extra_statement_cache_; // The UPDATE statement uses both the object and id image. Keep // them next to each other so that the same skip distance can diff --git a/odb/oracle/statement.cxx b/odb/oracle/statement.cxx index 27fa867..f4d9eef 100644 --- a/odb/oracle/statement.cxx +++ b/odb/oracle/statement.cxx @@ -1284,7 +1284,7 @@ namespace odb // Clear the status array. // - memset (status_, sizeof (status_), 0); + memset (status_, 0, n * sizeof (status_[0])); // @@ TODO allocate per batch stmt (maybe lazily here if NULL). // @@ -1314,7 +1314,7 @@ namespace odb if (r == OCI_ERROR || r == OCI_INVALID_HANDLE) translate_error (err1, r); - cerr << "NUM_DML_ERRORS: " << errors << endl; + //cerr << "NUM_DML_ERRORS: " << errors << endl; errors_ = errors; if (errors != 0) @@ -1393,7 +1393,7 @@ namespace odb rows = static_cast (n); } - cerr << "total: " << rows << endl; + //cerr << "total: " << rows << endl; if (n_ > 1) // Batch. { @@ -1869,12 +1869,11 @@ namespace odb // the last extracted size after OCIStmtExecute() below. Thanks, // Oracle! // - if (it != 0) - { - *reinterpret_cast ( - reinterpret_cast (b.size) + (it - 1) * skip) = - static_cast (st.ret_size_); - } + if (st.ret_prev_ != 0) + *st.ret_prev_ = static_cast (st.ret_size_); + + st.ret_prev_ = reinterpret_cast ( + reinterpret_cast (b.size) + it * skip); *size = &st.ret_size_; } @@ -1983,6 +1982,9 @@ namespace odb { OCIError* err (conn_.error_handle ()); + if (ret_ != 0) + ret_prev_ = 0; + // Ignore ORA-00001 error code, see fetch() below for details. // sword r (bulk_statement::execute (n, mex, (ret_ == 0 ? 1 : 0))); @@ -1995,34 +1997,25 @@ namespace odb sb4 e; OCIErrorGet (err, 1, 0, &e, 0, 0, OCI_HTYPE_ERROR); fetch (r, e); + + if (result_) // If fetch() hasn't translated the error. + translate_error (err, r, &conn_, 0, mex_); // Can return. + return n_; } // Store the last returned id size (see odb_oracle_returning_out() // for details). // - if (ret_ != 0) - { - size_t n (n_); - - // Find the index of the last sucessefully processed parameter set. - // - if (n != 1) - for (; n != 0 && status_[n - 1] != 0; --n) ; - - if (n != 0) // They all might have failed. - { - *reinterpret_cast ( - reinterpret_cast ( - ret_->bind[0].size) + (n - 1) * ret_->skip) = - static_cast (ret_size_); - } - } + if (ret_ != 0 && ret_prev_ != 0) + *ret_prev_ = static_cast (ret_size_); if (status_ == 0) // Non-batch mode. fetch (OCI_SUCCESS, 0); else + { fetch (status_[i_] == 0 ? OCI_SUCCESS : OCI_ERROR, status_[i_]); + } return n_; } @@ -2055,6 +2048,23 @@ namespace odb update_statement:: update_statement (connection_type& conn, const string& text, + bool process, + binding& param) + : bulk_statement (conn, + text, statement_update, + (process ? ¶m : 0), false, + param.batch, param.status), + unique_ (false) + { + assert (param.batch == 1); // Specify unique_hint explicitly. + + if (!empty ()) + bind_param (param.bind, param.count, param.batch, param.skip); + } + + update_statement:: + update_statement (connection_type& conn, + const string& text, bool unique, bool process, binding& param) @@ -2071,6 +2081,23 @@ namespace odb update_statement:: update_statement (connection_type& conn, const char* text, + bool process, + binding& param) + : bulk_statement (conn, + text, statement_update, + (process ? ¶m : 0), false, + param.batch, param.status), + unique_ (false) + { + assert (param.batch == 1); // Specify unique_hint explicitly. + + if (!empty ()) + bind_param (param.bind, param.count, param.batch, param.skip); + } + + update_statement:: + update_statement (connection_type& conn, + const char* text, bool unique, bool process, binding& param) @@ -2130,8 +2157,22 @@ namespace odb delete_statement:: delete_statement (connection_type& conn, const string& text, - binding& param, - bool unique) + binding& param) + : bulk_statement (conn, + text, statement_delete, + 0, false, + param.batch, param.status), + unique_ (false) + { + assert (param.batch == 1); // Specify unique_hint explicitly. + bind_param (param.bind, param.count, param.batch, param.skip); + } + + delete_statement:: + delete_statement (connection_type& conn, + const string& text, + bool unique, + binding& param) : bulk_statement (conn, text, statement_delete, 0, false, @@ -2144,8 +2185,22 @@ namespace odb delete_statement:: delete_statement (connection_type& conn, const char* text, - binding& param, - bool unique) + binding& param) + : bulk_statement (conn, + text, statement_delete, + 0, false, + param.batch, param.status), + unique_ (false) + { + assert (param.batch == 1); // Specify unique_hint explicitly. + bind_param (param.bind, param.count, param.batch, param.skip); + } + + delete_statement:: + delete_statement (connection_type& conn, + const char* text, + bool unique, + binding& param) : bulk_statement (conn, text, statement_delete, 0, false, diff --git a/odb/oracle/statement.hxx b/odb/oracle/statement.hxx index db032fa..f90efa3 100644 --- a/odb/oracle/statement.hxx +++ b/odb/oracle/statement.hxx @@ -317,45 +317,25 @@ namespace odb // Return the number of parameter sets (out of n) that were attempted. // std::size_t - execute (std::size_t n = 1, multiple_exceptions* = 0); + execute (std::size_t n, multiple_exceptions*); // Return true if successful and false if this row is a duplicate. // All other errors are reported via exceptions. // bool - result (std::size_t i = 0); + result (std::size_t i); + + bool + execute () + { + execute (1, 0); + return result (0); + } private: insert_statement (const insert_statement&); insert_statement& operator= (const insert_statement&); - /* - @@ RM - - // Only OCI versions 11.2 and greater support conversion of the internal - // Oracle type NUMBER to an external 64-bit integer type. If we detect - // version 11.2 or greater we provide an unsigned long long image. - // Otherwise, we revert to using a NUMBER image and manipulate it using - // the custom conversion algorithms found in details/number.hxx. - // - public: - struct id_bind_type - { - union - { - struct - { - char buffer[21]; - ub4 size; - } number; - - unsigned long long integer; - } id; - - sb2 indicator; - }; - */ - private: void init (binding& param); @@ -366,6 +346,7 @@ namespace odb public: // For odb_oracle_returning_*(). binding* ret_; ub4 ret_size_; // You don't want to know (see statement.cxx). + ub2* ret_prev_; private: bool result_; @@ -394,12 +375,22 @@ namespace odb // update_statement (connection_type& conn, const std::string& text, + bool process_text, + binding& param); + + update_statement (connection_type& conn, + const std::string& text, bool unique_hint, bool process_text, binding& param); update_statement (connection_type& conn, const char* text, + bool process_text, + binding& param); + + update_statement (connection_type& conn, + const char* text, bool unique_hint, bool process_text, binding& param); @@ -407,7 +398,7 @@ namespace odb // Return the number of parameter sets (out of n) that were attempted. // std::size_t - execute (std::size_t n = 1, multiple_exceptions* = 0); + execute (std::size_t n, multiple_exceptions*); // Return the number of rows affected (deleted) by the parameter // set. If this is a batch (n > 1 in execute() call above) and it @@ -418,7 +409,14 @@ namespace odb using bulk_statement::result_unknown; unsigned long long - result (std::size_t i = 0); + result (std::size_t i); + + unsigned long long + execute () + { + execute (1, 0); + return result (0); + } private: update_statement (const update_statement&); @@ -452,18 +450,26 @@ namespace odb // delete_statement (connection_type& conn, const std::string& text, - binding& param, - bool unique_hint = false); + binding& param); + + delete_statement (connection_type& conn, + const std::string& text, + bool unique_hint, + binding& param); delete_statement (connection_type& conn, const char* text, - binding& param, - bool unique_hint = false); + binding& param); + + delete_statement (connection_type& conn, + const char* text, + bool unique_hint, + binding& param); // Return the number of parameter sets (out of n) that were attempted. // std::size_t - execute (std::size_t n = 1, multiple_exceptions* = 0); + execute (std::size_t n, multiple_exceptions*); // Return the number of rows affected (deleted) by the parameter // set. If this is a batch (n > 1 in execute() call above) and it @@ -474,7 +480,14 @@ namespace odb using bulk_statement::result_unknown; unsigned long long - result (std::size_t i = 0); + result (std::size_t i); + + unsigned long long + execute () + { + execute (1, 0); + return result (0); + } private: delete_statement (const delete_statement&); -- cgit v1.1