aboutsummaryrefslogtreecommitdiff
path: root/odb/object-result.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-10-27 15:16:49 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-10-27 15:16:49 +0200
commit658a2f07b47ed80bd3ca35edd7380493c326daa3 (patch)
tree9df443d8820a2a53f6b8839adc36cde0c723f5cd /odb/object-result.hxx
parentac2c76e2412ff332022215b71bb106c8ea6dd3d0 (diff)
Add support for persistent classes without object ids
New pragma id (object). New test: common/no-id.
Diffstat (limited to 'odb/object-result.hxx')
-rw-r--r--odb/object-result.hxx262
1 files changed, 227 insertions, 35 deletions
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 <typename T>
- class result_impl<T, class_object>: public details::shared_base
+ class object_result_impl;
+
+ template <typename T>
+ class object_result_impl_no_id;
+
+ template <typename T, typename ID>
+ class object_result_iterator;
+
+ template <typename T, typename ID = typename object_traits<T>::id_type>
+ struct object_result_impl_selector
+ {
+ typedef object_result_impl<T> type;
+ };
+
+ template <typename T>
+ struct object_result_impl_selector<T, void>
+ {
+ typedef object_result_impl_no_id<T> type;
+ };
+
+ // Implementation for objects with object id.
+ //
+ template <typename T>
+ 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_type> object_traits;
+ typedef typename object_traits::id_type id_type;
+
+ typedef typename object_traits::pointer_type pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
friend class result<T>;
friend class result<const T>;
friend class result_iterator<T, class_object>;
friend class result_iterator<const T, class_object>;
+ friend class object_result_iterator<T, id_type>;
+ friend class object_result_iterator<const T, id_type>;
+
+ 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 <typename T>
+ 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_type> object_traits;
- typedef typename object_traits::id_type id_type;
typedef typename object_traits::pointer_type pointer_type;
typedef odb::pointer_traits<pointer_type> pointer_traits;
- result_impl (database_type& db)
+ friend class result<T>;
+ friend class result<const T>;
+ friend class result_iterator<T, class_object>;
+ friend class result_iterator<const T, class_object>;
+ friend class object_result_iterator<T, void>;
+ friend class object_result_iterator<const T, void>;
+
+ 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 <typename T, typename ID>
+ class object_result_iterator
+ {
+ public:
+ // T can be const T while object_type is always non-const.
+ //
+ typedef typename object_traits<T>::object_type object_type;
+ typedef typename object_traits<T>::id_type id_type;
+
+ typedef object_result_impl<object_type> result_impl_type;
+
+ public:
+ object_result_iterator (result_impl_type* res)
+ : res_ (res)
+ {
+ }
+
+ public:
+ typename object_traits<T>::pointer_type
+ load ()
+ {
+ typename object_traits<T>::pointer_type r (res_->current ());
+ res_->release ();
+ return r;
+ }
+
+ void
+ load (object_type&);
+
+ protected:
+ result_impl_type* res_;
+ };
+
template <typename T>
- class result_iterator<T, class_object>
+ class object_result_iterator<T, void>
+ {
+ public:
+ // T can be const T while object_type is always non-const.
+ //
+ typedef typename object_traits<T>::object_type object_type;
+
+ typedef object_result_impl_no_id<object_type> result_impl_type;
+
+ public:
+ object_result_iterator (result_impl_type* res)
+ : res_ (res)
+ {
+ }
+
+ public:
+ typename object_traits<T>::pointer_type
+ load ()
+ {
+ typename object_traits<T>::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 <typename T>
+ class result_iterator<T, class_object>: public object_result_iterator<
+ T,
+ typename object_traits<T>::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<T>::object_type object_type;
- typedef typename object_traits<T>::id_type id_type;
-
- typedef result_impl<object_type, class_object> result_impl_type;
+ typedef
+ object_result_iterator<T, typename object_traits<T>::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<T>::pointer_type
- load ()
- {
- typename object_traits<T>::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<typename object_traits<object_type>::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<T>::object_type object_type;
- typedef result_impl<object_type, class_object> result_impl_type;
+ typedef
+ typename object_result_impl_selector<object_type>::type
+ result_impl_type;
};
}