From df1fdb4f500308adf2fff1a08b2ef62bf5a88de7 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 12 Jan 2012 10:46:55 +0200 Subject: Detect and throw when object/view with long data is re-loaded from query result --- odb/mssql/exceptions.cxx | 11 +++++++++++ odb/mssql/exceptions.hxx | 6 ++++++ odb/mssql/object-result.hxx | 2 ++ odb/mssql/object-result.txx | 15 ++++++++++++--- odb/mssql/statement.hxx | 9 +++++++-- odb/mssql/view-result.hxx | 1 + odb/mssql/view-result.txx | 9 +++++++-- 7 files changed, 46 insertions(+), 7 deletions(-) diff --git a/odb/mssql/exceptions.cxx b/odb/mssql/exceptions.cxx index 1b415a7..f14fc59 100644 --- a/odb/mssql/exceptions.cxx +++ b/odb/mssql/exceptions.cxx @@ -78,5 +78,16 @@ namespace odb { return what_.c_str (); } + + // + // long_data_reload + // + + const char* long_data_reload:: + what () const throw () + { + return "attempt to re-load object or view with long data " + "from query result"; + } } } diff --git a/odb/mssql/exceptions.hxx b/odb/mssql/exceptions.hxx index 3e7a845..b31a83d 100644 --- a/odb/mssql/exceptions.hxx +++ b/odb/mssql/exceptions.hxx @@ -108,6 +108,12 @@ namespace odb private: std::string what_; }; + + struct LIBODB_MSSQL_EXPORT long_data_reload: odb::exception + { + virtual const char* + what () const throw (); + }; } } diff --git a/odb/mssql/object-result.hxx b/odb/mssql/object-result.hxx index 9eaa4f5..6380993 100644 --- a/odb/mssql/object-result.hxx +++ b/odb/mssql/object-result.hxx @@ -67,6 +67,7 @@ namespace odb private: details::shared_ptr statement_; object_statements& statements_; + bool can_load_; bool use_copy_; typename object_traits::image_type* image_copy_; }; @@ -113,6 +114,7 @@ namespace odb private: details::shared_ptr statement_; object_statements_no_id& statements_; + bool can_load_; bool use_copy_; typename object_traits::image_type* image_copy_; }; diff --git a/odb/mssql/object-result.txx b/odb/mssql/object-result.txx index 338f78a..161978e 100644 --- a/odb/mssql/object-result.txx +++ b/odb/mssql/object-result.txx @@ -6,8 +6,9 @@ #include #include -#include +#include // result_not_cached +#include // long_data_reload #include namespace odb @@ -50,6 +51,9 @@ namespace odb void object_result_impl:: load (object_type& obj, bool) { + if (!can_load_) + throw long_data_reload (); + // This is a top-level call so the statements cannot be locked. // assert (!statements_.locked ()); @@ -66,7 +70,7 @@ namespace odb // If we are using a copy, make sure the callback information for // long data also comes from the copy. // - statement_->stream_result ( + can_load_ = !statement_->stream_result ( use_copy_ ? &statements_.image () : 0, use_copy_ ? image_copy_ : 0); @@ -103,6 +107,7 @@ namespace odb void object_result_impl:: next () { + can_load_ = true; this->current (pointer_type ()); typename object_traits::image_type& im (statements_.image ()); @@ -200,6 +205,9 @@ namespace odb void object_result_impl_no_id:: load (object_type& obj) { + if (!can_load_) + throw long_data_reload (); + odb::database& db (this->database ()); object_traits::callback (db, obj, callback_event::pre_load); @@ -211,7 +219,7 @@ namespace odb // If we are using a copy, make sure the callback information for // long data also comes from the copy. // - statement_->stream_result ( + can_load_ = !statement_->stream_result ( use_copy_ ? &statements_.image () : 0, use_copy_ ? image_copy_ : 0); @@ -222,6 +230,7 @@ namespace odb void object_result_impl_no_id:: next () { + can_load_ = true; this->current (pointer_type ()); typename object_traits::image_type& im (statements_.image ()); diff --git a/odb/mssql/statement.hxx b/odb/mssql/statement.hxx index 3bea55f..6eacec6 100644 --- a/odb/mssql/statement.hxx +++ b/odb/mssql/statement.hxx @@ -122,15 +122,20 @@ namespace odb result fetch (); - void + // Return true if any long data was streamed. + // + bool stream_result (void* old_base = 0, void* new_base = 0) { - if (first_long_ != result_.count) + bool ld (first_long_ != result_.count); + + if (ld) statement::stream_result (result_.bind, first_long_, result_.count, old_base, new_base); + return ld; } void diff --git a/odb/mssql/view-result.hxx b/odb/mssql/view-result.hxx index e4a523a..cf3dde1 100644 --- a/odb/mssql/view-result.hxx +++ b/odb/mssql/view-result.hxx @@ -63,6 +63,7 @@ namespace odb private: details::shared_ptr statement_; view_statements& statements_; + bool can_load_; bool use_copy_; typename view_traits::image_type* image_copy_; }; diff --git a/odb/mssql/view-result.txx b/odb/mssql/view-result.txx index 4b5053d..3d86206 100644 --- a/odb/mssql/view-result.txx +++ b/odb/mssql/view-result.txx @@ -4,8 +4,9 @@ // license : ODB NCUEL; see accompanying LICENSE file #include -#include +#include // result_not_cached +#include // long_data_reload #include namespace odb @@ -44,6 +45,9 @@ namespace odb void view_result_impl:: load (view_type& view) { + if (!can_load_) + throw long_data_reload (); + odb::database& db (this->database ()); view_traits::callback (db, view, callback_event::pre_load); @@ -55,7 +59,7 @@ namespace odb // If we are using a copy, make sure the callback information for // long data also comes from the copy. // - statement_->stream_result ( + can_load_ = !statement_->stream_result ( use_copy_ ? &statements_.image () : 0, use_copy_ ? image_copy_ : 0); @@ -66,6 +70,7 @@ namespace odb void view_result_impl:: next () { + can_load_ = true; this->current (pointer_type ()); typename view_traits::image_type& im (statements_.image ()); -- cgit v1.1