From 658a2f07b47ed80bd3ca35edd7380493c326daa3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 27 Oct 2011 15:16:49 +0200 Subject: Add support for persistent classes without object ids New pragma id (object). New test: common/no-id. --- odb/object-result.hxx | 262 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 227 insertions(+), 35 deletions(-) (limited to 'odb/object-result.hxx') diff --git a/odb/object-result.hxx b/odb/object-result.hxx index 4c25962..e4d28ee 100644 --- a/odb/object-result.hxx +++ b/odb/object-result.hxx @@ -20,30 +20,158 @@ namespace odb { template - class result_impl: public details::shared_base + class object_result_impl; + + template + class object_result_impl_no_id; + + template + class object_result_iterator; + + template ::id_type> + struct object_result_impl_selector + { + typedef object_result_impl type; + }; + + template + struct object_result_impl_selector + { + typedef object_result_impl_no_id type; + }; + + // Implementation for objects with object id. + // + template + class object_result_impl: public details::shared_base { public: virtual - ~result_impl (); + ~object_result_impl (); protected: + typedef odb::database database_type; + + // In result_impl, T is always non-const and the same as object_type. + // + typedef T object_type; + typedef odb::object_traits object_traits; + typedef typename object_traits::id_type id_type; + + typedef typename object_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + friend class result; friend class result; friend class result_iterator; friend class result_iterator; + friend class object_result_iterator; + friend class object_result_iterator; + + protected: + object_result_impl (database_type& db) + : begin_ (true), end_ (false), db_ (db), current_ () + { + } + + database_type& + database () const + { + return db_; + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current (); + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + virtual void + load (object_type&) = 0; + + virtual id_type + load_id () = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: + void + current (pointer_type p) + { + current_ = p; + guard_.reset (current_); + } + + bool begin_; + bool end_; + + private: + database_type& db_; + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + // Implementation for objects without object id. + // + template + class object_result_impl_no_id: public details::shared_base + { + public: + virtual + ~object_result_impl_no_id (); + protected: typedef odb::database database_type; // In result_impl, T is always non-const and the same as object_type. // typedef T object_type; typedef odb::object_traits object_traits; - typedef typename object_traits::id_type id_type; typedef typename object_traits::pointer_type pointer_type; typedef odb::pointer_traits pointer_traits; - result_impl (database_type& db) + friend class result; + friend class result; + friend class result_iterator; + friend class result_iterator; + friend class object_result_iterator; + friend class object_result_iterator; + + protected: + object_result_impl_no_id (database_type& db) : begin_ (true), end_ (false), db_ (db), current_ () { } @@ -88,9 +216,6 @@ namespace odb virtual void load (object_type&) = 0; - virtual id_type - load_id () = 0; - virtual void next () = 0; @@ -117,8 +242,85 @@ namespace odb typename pointer_traits::guard guard_; }; + // + // result_iterator + // + + template + class object_result_iterator + { + public: + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::id_type id_type; + + typedef object_result_impl result_impl_type; + + public: + object_result_iterator (result_impl_type* res) + : res_ (res) + { + } + + public: + typename object_traits::pointer_type + load () + { + typename object_traits::pointer_type r (res_->current ()); + res_->release (); + return r; + } + + void + load (object_type&); + + protected: + result_impl_type* res_; + }; + template - class result_iterator + class object_result_iterator + { + public: + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + + typedef object_result_impl_no_id result_impl_type; + + public: + object_result_iterator (result_impl_type* res) + : res_ (res) + { + } + + public: + typename object_traits::pointer_type + load () + { + typename object_traits::pointer_type r (res_->current ()); + res_->release (); + return r; + } + + void + load (object_type& obj) + { + // Objects without ids are not stored in session cache. + // + if (!res_->end ()) + res_->load (obj); + } + + protected: + result_impl_type* res_; + }; + + template + class result_iterator: public object_result_iterator< + T, + typename object_traits::id_type> { public: typedef T value_type; @@ -129,15 +331,14 @@ namespace odb // T can be const T while object_type is always non-const. // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::id_type id_type; - - typedef result_impl result_impl_type; + typedef + object_result_iterator::id_type> + base_type; public: explicit - result_iterator (result_impl_type* res = 0) - : res_ (res) + result_iterator (typename base_type::result_impl_type* res = 0) + : base_type (res) { } @@ -147,7 +348,7 @@ namespace odb reference operator* () const { - return pointer_traits::get_ref (res_->current ()); + return pointer_traits::get_ref (this->res_->current ()); } // Our value_type is already a pointer so return it instead of @@ -157,13 +358,13 @@ namespace odb pointer operator-> () const { - return pointer_traits::get_ptr (res_->current ()); + return pointer_traits::get_ptr (this->res_->current ()); } result_iterator& operator++ () { - res_->next (); + this->res_->next (); return *this; } @@ -172,27 +373,16 @@ namespace odb { // All non-end iterators for a result object move together. // - res_->next (); + this->res_->next (); return *this; } public: - typename object_traits::pointer_type - load () - { - typename object_traits::pointer_type r (res_->current ()); - res_->release (); - return r; - } - - void - load (object_type&); - - public: bool equal (result_iterator j) const { - return (res_ ? res_->end () : true) == (j.res_ ? j.res_->end () : true); + return (this->res_ ? this->res_->end () : true) == + (j.res_ ? j.res_->end () : true); } private: @@ -200,10 +390,10 @@ namespace odb // result_impl. // typedef - odb::pointer_traits::pointer_type> + odb::pointer_traits< + typename object_traits< + typename base_type::object_type>::pointer_type> pointer_traits; - - result_impl_type* res_; }; // @@ -217,7 +407,9 @@ namespace odb // T can be const T while object_type is always non-const. // typedef typename object_traits::object_type object_type; - typedef result_impl result_impl_type; + typedef + typename object_result_impl_selector::type + result_impl_type; }; } -- cgit v1.1