From d44d7c96d38453d5a971b813be4c6635bf0b38fb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 17 Nov 2014 13:35:21 +0200 Subject: Implement bulk database operation support for Oracle and SQL Server --- odb/mysql/container-statements.hxx | 1 + odb/mysql/database.hxx | 4 +++ odb/mysql/database.ixx | 7 +++++ odb/mysql/exceptions.cxx | 12 ++++++++ odb/mysql/exceptions.hxx | 6 ++++ odb/mysql/no-id-object-statements.hxx | 1 + odb/mysql/polymorphic-object-statements.hxx | 7 +++-- odb/mysql/section-statements.hxx | 3 +- odb/mysql/section-statements.txx | 2 +- odb/mysql/simple-object-statements.hxx | 39 ++++++++++++++++--------- odb/mysql/statement.cxx | 44 +++++++++++++++++++++++------ odb/mysql/statement.hxx | 9 +++--- 12 files changed, 104 insertions(+), 31 deletions(-) diff --git a/odb/mysql/container-statements.hxx b/odb/mysql/container-statements.hxx index be86cda..191d9f6 100644 --- a/odb/mysql/container-statements.hxx +++ b/odb/mysql/container-statements.hxx @@ -128,6 +128,7 @@ namespace odb insert_text_, versioned_, // Process if versioned. insert_image_binding_, + 0, false)); return *insert_; diff --git a/odb/mysql/database.hxx b/odb/mysql/database.hxx index 8d11e72..9192138 100644 --- a/odb/mysql/database.hxx +++ b/odb/mysql/database.hxx @@ -180,6 +180,10 @@ namespace odb template typename object_traits::id_type + persist (const T& object); + + template + typename object_traits::id_type persist (T* obj_ptr); template class P> diff --git a/odb/mysql/database.ixx b/odb/mysql/database.ixx index 09fc641..68aecec 100644 --- a/odb/mysql/database.ixx +++ b/odb/mysql/database.ixx @@ -27,6 +27,13 @@ namespace odb template inline typename object_traits::id_type database:: + persist (const T& obj) + { + return persist_ (obj); + } + + template + inline typename object_traits::id_type database:: persist (T* p) { typedef typename object_traits::pointer_type object_pointer; diff --git a/odb/mysql/exceptions.cxx b/odb/mysql/exceptions.cxx index ddf5ce8..8e2375a 100644 --- a/odb/mysql/exceptions.cxx +++ b/odb/mysql/exceptions.cxx @@ -36,6 +36,12 @@ namespace odb return what_.c_str (); } + database_exception* database_exception:: + clone () const + { + return new database_exception (*this); + } + // // cli_exception // @@ -56,5 +62,11 @@ namespace odb { return what_.c_str (); } + + cli_exception* cli_exception:: + clone () const + { + return new cli_exception (*this); + } } } diff --git a/odb/mysql/exceptions.hxx b/odb/mysql/exceptions.hxx index 824f678..ea4e493 100644 --- a/odb/mysql/exceptions.hxx +++ b/odb/mysql/exceptions.hxx @@ -49,6 +49,9 @@ namespace odb virtual const char* what () const throw (); + virtual database_exception* + clone () const; + private: unsigned int error_; std::string sqlstate_; @@ -64,6 +67,9 @@ namespace odb virtual const char* what () const throw (); + virtual cli_exception* + clone () const; + private: std::string what_; }; diff --git a/odb/mysql/no-id-object-statements.hxx b/odb/mysql/no-id-object-statements.hxx index 0da7368..b2c5ce2 100644 --- a/odb/mysql/no-id-object-statements.hxx +++ b/odb/mysql/no-id-object-statements.hxx @@ -88,6 +88,7 @@ namespace odb object_traits::persist_statement, object_traits::versioned, // Process if versioned. insert_image_binding_, + 0, false)); return *persist_; diff --git a/odb/mysql/polymorphic-object-statements.hxx b/odb/mysql/polymorphic-object-statements.hxx index 63662df..1607926 100644 --- a/odb/mysql/polymorphic-object-statements.hxx +++ b/odb/mysql/polymorphic-object-statements.hxx @@ -314,6 +314,7 @@ namespace odb object_traits::persist_statement, object_traits::versioned, // Process if versioned. insert_image_binding_, + 0, false)); return *persist_; @@ -376,6 +377,7 @@ namespace odb return extra_statement_cache_.get ( conn_, image_, + id_image (), id_image_binding (), &id_image_binding ()); // Note, not id+version. } @@ -414,8 +416,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/mysql/section-statements.hxx b/odb/mysql/section-statements.hxx index bc83942..c4e83ac 100644 --- a/odb/mysql/section-statements.hxx +++ b/odb/mysql/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 mysql::select_statement select_statement_type; typedef mysql::update_statement update_statement_type; @@ -43,7 +44,7 @@ namespace odb typedef mysql::connection connection_type; section_statements (connection_type&, - image_type&, + image_type&, id_image_type&, binding& id, binding& idv); connection_type& diff --git a/odb/mysql/section-statements.txx b/odb/mysql/section-statements.txx index 61bfafe..78fb183 100644 --- a/odb/mysql/section-statements.txx +++ b/odb/mysql/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/mysql/simple-object-statements.hxx b/odb/mysql/simple-object-statements.hxx index 1ce8472..f5d52c0 100644 --- a/odb/mysql/simple-object-statements.hxx +++ b/odb/mysql/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 mysql::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_; @@ -353,6 +360,7 @@ namespace odb object_traits::persist_statement, object_traits::versioned, // Process if versioned. insert_image_binding_, + (object_traits::auto_id ? &id_image_binding_ : 0), false)); return *persist_; @@ -426,7 +434,9 @@ namespace odb extra_statement_cache () { return extra_statement_cache_.get ( - conn_, image_, id_image_binding_, od_.id_image_binding ()); + conn_, + image_, id_image_, + id_image_binding_, od_.id_image_binding ()); } public: @@ -472,8 +482,9 @@ namespace odb template friend class polymorphic_derived_object_statements; - extra_statement_cache_ptr - extra_statement_cache_; + extra_statement_cache_ptr extra_statement_cache_; image_type image_; diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx index 4b80913..85732de 100644 --- a/odb/mysql/statement.cxx +++ b/odb/mysql/statement.cxx @@ -564,12 +564,14 @@ namespace odb insert_statement (connection_type& conn, const string& text, bool process, - binding& param) + binding& param, + binding* returning) : statement (conn, text, statement_insert, (process ? ¶m : 0), false), param_ (param), - param_version_ (0) + param_version_ (0), + returning_ (returning) { } @@ -578,13 +580,15 @@ namespace odb const char* text, bool process, binding& param, + binding* returning, bool copy_text) : statement (conn, text, statement_insert, (process ? ¶m : 0), false, copy_text), param_ (param), - param_version_ (0) + param_version_ (0), + returning_ (returning) { } @@ -625,13 +629,35 @@ namespace odb translate_error (conn_, stmt_); } - return true; - } + if (returning_ != 0) + { + unsigned long long i (mysql_stmt_insert_id (stmt_)); - unsigned long long insert_statement:: - id () - { - return static_cast (mysql_stmt_insert_id (stmt_)); + MYSQL_BIND& b (returning_->bind[0]); + void* v (b.buffer); + + switch (b.buffer_type) + { + case MYSQL_TYPE_TINY: + *static_cast (v) = static_cast (i); + break; + case MYSQL_TYPE_SHORT: + *static_cast (v) = static_cast (i); + break; + case MYSQL_TYPE_LONG: + *static_cast (v) = static_cast (i); + break; + case MYSQL_TYPE_LONGLONG: + *static_cast (v) = i; + break; + default: + assert (false); // Auto id column type is not an integer. + } + + *b.is_null = false; + } + + return true; } // update_statement diff --git a/odb/mysql/statement.hxx b/odb/mysql/statement.hxx index 3e7afad..faf8e01 100644 --- a/odb/mysql/statement.hxx +++ b/odb/mysql/statement.hxx @@ -238,12 +238,14 @@ namespace odb insert_statement (connection_type& conn, const std::string& text, bool process_text, - binding& param); + binding& param, + binding* returning); insert_statement (connection_type& conn, const char* text, bool process_text, binding& param, + binding* returning, bool copy_text = true); // Return true if successful and false if the row is a duplicate. @@ -252,9 +254,6 @@ namespace odb bool execute (); - unsigned long long - id (); - private: insert_statement (const insert_statement&); insert_statement& operator= (const insert_statement&); @@ -262,6 +261,8 @@ namespace odb private: binding& param_; std::size_t param_version_; + + binding* returning_; }; class LIBODB_MYSQL_EXPORT update_statement: public statement -- cgit v1.1