From 8d4d2568f356cb9beb1553bf58ad69c1c800b996 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 14 Aug 2014 09:37:06 +0200 Subject: Implement bulk database operation support for Oracle and SQL Server --- odb/exceptions.cxx | 236 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 1 deletion(-) (limited to 'odb/exceptions.cxx') diff --git a/odb/exceptions.cxx b/odb/exceptions.cxx index a5292bc..ca9e84c 100644 --- a/odb/exceptions.cxx +++ b/odb/exceptions.cxx @@ -2,7 +2,10 @@ // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include // std::strlen #include +#include + #include using namespace std; @@ -15,96 +18,192 @@ namespace odb return "NULL pointer"; } + null_pointer* null_pointer:: + clone () const + { + return new null_pointer (*this); + } + const char* already_in_transaction:: what () const throw () { return "transaction already in progress in this thread"; } + already_in_transaction* already_in_transaction:: + clone () const + { + return new already_in_transaction (*this); + } + const char* not_in_transaction:: what () const throw () { return "operation can only be performed in transaction"; } + not_in_transaction* not_in_transaction:: + clone () const + { + return new not_in_transaction (*this); + } + const char* transaction_already_finalized:: what () const throw () { return "transaction already committed or rolled back"; } + transaction_already_finalized* transaction_already_finalized:: + clone () const + { + return new transaction_already_finalized (*this); + } + const char* already_in_session:: what () const throw () { return "session already in effect in this thread"; } + already_in_session* already_in_session:: + clone () const + { + return new already_in_session (*this); + } + const char* not_in_session:: what () const throw () { return "session not in effect in this thread"; } + not_in_session* not_in_session:: + clone () const + { + return new not_in_session (*this); + } + const char* session_required:: what () const throw () { return "session required to load this object relationship"; } + session_required* session_required:: + clone () const + { + return new session_required (*this); + } + const char* deadlock:: what () const throw () { return "transaction aborted due to deadlock"; } + deadlock* deadlock:: + clone () const + { + return new deadlock (*this); + } + const char* connection_lost:: what () const throw () { return "connection to database lost"; } + connection_lost* connection_lost:: + clone () const + { + return new connection_lost (*this); + } + const char* timeout:: what () const throw () { return "database operation timeout"; } + timeout* timeout:: + clone () const + { + return new timeout (*this); + } + const char* object_not_persistent:: what () const throw () { return "object not persistent"; } + object_not_persistent* object_not_persistent:: + clone () const + { + return new object_not_persistent (*this); + } + const char* object_already_persistent:: what () const throw () { return "object already persistent"; } + object_already_persistent* object_already_persistent:: + clone () const + { + return new object_already_persistent (*this); + } + const char* object_changed:: what () const throw () { return "object changed concurrently"; } + object_changed* object_changed:: + clone () const + { + return new object_changed (*this); + } + const char* result_not_cached:: what () const throw () { return "query result is not cached"; } + result_not_cached* result_not_cached:: + clone () const + { + return new result_not_cached (*this); + } + const char* abstract_class:: what () const throw () { return "database operation on instance of abstract class"; } + abstract_class* abstract_class:: + clone () const + { + return new abstract_class (*this); + } + const char* no_type_info:: what () const throw () { return "no type information"; } + no_type_info* no_type_info:: + clone () const + { + return new no_type_info (*this); + } + prepared_already_cached:: prepared_already_cached (const char* name) : name_ (name) @@ -125,6 +224,12 @@ namespace odb return what_.c_str (); } + prepared_already_cached* prepared_already_cached:: + clone () const + { + return new prepared_already_cached (*this); + } + prepared_type_mismatch:: prepared_type_mismatch (const char* name) : name_ (name) @@ -145,8 +250,14 @@ namespace odb return what_.c_str (); } + prepared_type_mismatch* prepared_type_mismatch:: + clone () const + { + return new prepared_type_mismatch (*this); + } + unknown_schema:: - unknown_schema (const std::string& name) + unknown_schema (const string& name) : name_ (name) { what_ = "unknown database schema '"; @@ -165,6 +276,12 @@ namespace odb return what_.c_str (); } + unknown_schema* unknown_schema:: + clone () const + { + return new unknown_schema (*this); + } + unknown_schema_version:: unknown_schema_version (schema_version v) : version_ (v) @@ -186,15 +303,132 @@ namespace odb return what_.c_str (); } + unknown_schema_version* unknown_schema_version:: + clone () const + { + return new unknown_schema_version (*this); + } + const char* section_not_loaded:: what () const throw () { return "section is not loaded"; } + section_not_loaded* section_not_loaded:: + clone () const + { + return new section_not_loaded (*this); + } + const char* section_not_in_object:: what () const throw () { return "section instance is not part of an object (section was copied?)"; } + + section_not_in_object* section_not_in_object:: + clone () const + { + return new section_not_in_object (*this); + } + + // multiple_exceptions + // + multiple_exceptions:: + ~multiple_exceptions () throw () {} + + void multiple_exceptions:: + insert (size_t p, bool maybe, const odb::exception& e, bool fatal) + { + details::shared_ptr pe; + + if (common_exception_ti_ != typeid (e)) + pe.reset (e.clone ()); + else + { + if (common_exception_ == 0) + common_exception_.reset (e.clone ()); + + pe = common_exception_; + } + + set_.insert (value_type (delta_ + p, maybe, pe)); + fatal_ = fatal_ || fatal; + } + + const multiple_exceptions::value_type* multiple_exceptions:: + lookup (size_t p) const + { + p += delta_; // Called while populating multiple_exceptions. + + iterator i (set_.find (value_type (p))); + return i == set_.end () ? 0 : &*i; + } + + void multiple_exceptions:: + prepare () + { + current_ = 0; + delta_ = 0; + common_exception_.reset (); + + ostringstream os; + os << "multiple exceptions, " + << attempted_ << " element" << (attempted_ != 1 ? "s" : "") << + " attempted, " + << failed () << " failed" + << (fatal_ ? ", fatal" : "") << ":"; + + bool nl (true); + for (iterator i (begin ()); i != end ();) + { + size_t p (i->position ()); + const odb::exception& e (i->exception ()); + + os << (nl ? "\n" : ""); + + if (!i->maybe ()) + { + os << '[' << p << ']'; + ++i; + } + else + { + // In this case we will normally have a large number of maybe + // failures in a row (usually the whole batch). So let's try + // to represent them all as a single range. + // + size_t n (0); + for (++i; i != end () && i->maybe (); ++i) + { + assert (&e == &i->exception ()); // The same common exception. + n++; + } + + if (n == 0) + os << '[' << p << ']'; + else + os << '[' << p << '-' << (p + n) << "] (some)"; + } + + const char* w (e.what ()); + os << ' ' << w; + nl = (w[strlen (w) - 1] != '\n'); + } + + what_ = os.str (); + } + + const char* multiple_exceptions:: + what () const throw () + { + return what_.c_str (); + } + + multiple_exceptions* multiple_exceptions:: + clone () const + { + return new multiple_exceptions (*this); + } } -- cgit v1.1