aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-01-12 10:46:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-01-12 10:46:55 +0200
commitdf1fdb4f500308adf2fff1a08b2ef62bf5a88de7 (patch)
tree1a014a6207bba19a58a8b574c6bb00b881585d13
parentbbb153b9e576cdfdb59711f68d7f26a427a55041 (diff)
Detect and throw when object/view with long data is re-loaded from query result
-rw-r--r--odb/mssql/exceptions.cxx11
-rw-r--r--odb/mssql/exceptions.hxx6
-rw-r--r--odb/mssql/object-result.hxx2
-rw-r--r--odb/mssql/object-result.txx15
-rw-r--r--odb/mssql/statement.hxx9
-rw-r--r--odb/mssql/view-result.hxx1
-rw-r--r--odb/mssql/view-result.txx9
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<select_statement> statement_;
object_statements<object_type>& statements_;
+ bool can_load_;
bool use_copy_;
typename object_traits::image_type* image_copy_;
};
@@ -113,6 +114,7 @@ namespace odb
private:
details::shared_ptr<select_statement> statement_;
object_statements_no_id<object_type>& 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 <cassert>
#include <odb/callback.hxx>
-#include <odb/exceptions.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+#include <odb/mssql/exceptions.hxx> // long_data_reload
#include <odb/mssql/object-statements.hxx>
namespace odb
@@ -50,6 +51,9 @@ namespace odb
void object_result_impl<T>::
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<T>::
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<T>::
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<T>::
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<select_statement> statement_;
view_statements<view_type>& 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 <odb/callback.hxx>
-#include <odb/exceptions.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+#include <odb/mssql/exceptions.hxx> // long_data_reload
#include <odb/mssql/view-statements.hxx>
namespace odb
@@ -44,6 +45,9 @@ namespace odb
void view_result_impl<T>::
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<T>::
next ()
{
+ can_load_ = true;
this->current (pointer_type ());
typename view_traits::image_type& im (statements_.image ());