diff options
Diffstat (limited to 'odb/mysql/result.txx')
-rw-r--r-- | odb/mysql/result.txx | 95 |
1 files changed, 68 insertions, 27 deletions
diff --git a/odb/mysql/result.txx b/odb/mysql/result.txx index 4b18abc..e3ef10b 100644 --- a/odb/mysql/result.txx +++ b/odb/mysql/result.txx @@ -3,6 +3,7 @@ // copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file +#include <odb/exceptions.hxx> #include <odb/cache-traits.hxx> namespace odb @@ -21,15 +22,18 @@ namespace odb object_statements<object_type>& statements) : odb::result_impl<T> (statements.connection ().database ()), statement_ (statement), - statements_ (statements) + statements_ (statements), + count_ (0) { - next (); } template <typename T> void result_impl<T>:: load (object_type& obj) { + if (count_ > statement_->fetched ()) + fetch (); + // This is a top-level call so the statements cannot be locked. // assert (!statements_.locked ()); @@ -45,6 +49,9 @@ namespace odb typename result_impl<T>::id_type result_impl<T>:: load_id () { + if (count_ > statement_->fetched ()) + fetch (); + return object_traits::id (statements_.image ()); } @@ -54,8 +61,25 @@ namespace odb { this->current (pointer_type ()); - // If the result was cached the image can grow between calls - // to next() as a result of other statements execution. + // If we are cached, simply increment the position and + // postpone the actual row fetching until later. This way + // if the same object is loaded in between iteration, the + // image won't be messed up. + // + count_++; + + if (statement_->cached ()) + this->end_ = count_ > statement_->result_size (); + else + fetch (); + } + + template <typename T> + void result_impl<T>:: + fetch () + { + // If the result is cached, the image can grow between calls + // to fetch() as a result of other statements execution. // if (statement_->cached ()) { @@ -70,33 +94,41 @@ namespace odb } } - select_statement::result r (statement_->fetch ()); - - switch (r) + while (count_ > statement_->fetched ()) { - case select_statement::truncated: + select_statement::result r (statement_->fetch ()); + + switch (r) { - typename object_traits::image_type& im (statements_.image ()); - object_traits::grow (im, statements_.out_image_error ()); + case select_statement::truncated: + { + // Don't re-fetch data we are skipping. + // + if (count_ != statement_->fetched ()) + continue; + + typename object_traits::image_type& im (statements_.image ()); + object_traits::grow (im, statements_.out_image_error ()); - if (im.version != statements_.out_image_version ()) + if (im.version != statements_.out_image_version ()) + { + binding& b (statements_.out_image_binding ()); + object_traits::bind (b.bind, im, true); + statements_.out_image_version (im.version); + b.version++; + statement_->refetch (); + } + // Fall throught. + } + case select_statement::success: { - binding& b (statements_.out_image_binding ()); - object_traits::bind (b.bind, im, true); - statements_.out_image_version (im.version); - b.version++; - statement_->refetch (); + break; + } + case select_statement::no_data: + { + this->end_ = true; + break; } - // Fall throught. - } - case select_statement::success: - { - break; - } - case select_statement::no_data: - { - this->end_ = true; - break; } } } @@ -105,13 +137,22 @@ namespace odb void result_impl<T>:: cache () { - statement_->cache (); + if (!statement_->cached ()) + { + statement_->cache (); + + if (count_ >= statement_->result_size ()) + this->end_ = true; + } } template <typename T> std::size_t result_impl<T>:: size () { + if (!statement_->cached ()) + throw result_not_cached (); + return statement_->result_size (); } } |