aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:00 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:00 +0200
commit1896d36996ab48ed7271e855d7e32b4e61f64896 (patch)
tree6d085eb0349d23bc26fe101b2451235939f17d40
parentc2be6303f97e470960ee77805128c46d3ea5c102 (diff)
Polymorphic inheritance support
-rw-r--r--odb/cache-traits.hxx322
-rw-r--r--odb/database.ixx88
-rw-r--r--odb/database.txx162
-rw-r--r--odb/exceptions.cxx12
-rw-r--r--odb/exceptions.hxx17
-rw-r--r--odb/forward.hxx14
-rw-r--r--odb/no-id-object-result.hxx191
-rw-r--r--odb/no-id-object-result.txx28
-rw-r--r--odb/object-result.hxx358
-rw-r--r--odb/object-result.txx112
-rw-r--r--odb/pointer-traits.hxx89
-rw-r--r--odb/polymorphic-info.hxx118
-rw-r--r--odb/polymorphic-map.hxx244
-rw-r--r--odb/polymorphic-map.ixx20
-rw-r--r--odb/polymorphic-map.txx72
-rw-r--r--odb/polymorphic-object-result.hxx233
-rw-r--r--odb/polymorphic-object-result.txx76
-rw-r--r--odb/query.hxx15
-rw-r--r--odb/result.hxx9
-rw-r--r--odb/session.txx2
-rw-r--r--odb/simple-object-result.hxx210
-rw-r--r--odb/simple-object-result.txx65
-rw-r--r--odb/tr1/pointer-traits.hxx16
-rw-r--r--odb/traits.hxx2
-rw-r--r--odb/view-result.hxx1
25 files changed, 1725 insertions, 751 deletions
diff --git a/odb/cache-traits.hxx b/odb/cache-traits.hxx
index 6f5e14a..1e5ccdb 100644
--- a/odb/cache-traits.hxx
+++ b/odb/cache-traits.hxx
@@ -14,34 +14,154 @@
namespace odb
{
- // Caching traits for objects passed by pointer.
+ // pointer_cache_type
//
- template <typename P, typename ID, pointer_kind kind>
- struct pointer_cache_traits_impl;
+ // Used to convert an object pointer to the canonical form (non-const),
+ // suitable for insertion into the cache.
+ //
+ template <typename P,
+ typename E = typename pointer_traits<P>::element_type,
+ typename O = typename object_traits<E>::object_type,
+ pointer_kind pk = pointer_traits<P>::kind>
+ struct pointer_cache_type
+ {
+ typedef typename object_traits<O>::pointer_type pointer_type;
+
+ static pointer_type
+ convert (const P& p)
+ {
+ return pointer_traits<P>::const_pointer_cast (p);
+ }
+ };
+
+ template <typename P, typename T, pointer_kind pk>
+ struct pointer_cache_type<P, T, T, pk>
+ {
+ // If element_type and object_type are the same, then it is already
+ // the canonical pointer.
+ //
+ static const P&
+ convert (const P& p) {return p;}
+ };
+
+ template <typename P, typename E, typename O>
+ struct pointer_cache_type<P, E, O, pk_unique>
+ {
+ // If the pointer is unique, then casting it can transfer ownership.
+ // So return null pointer, which will be ignored down the chain.
+ //
+ typedef typename object_traits<O>::pointer_type pointer_type;
+
+ static pointer_type
+ convert (const P&) {return pointer_type ();}
+ };
+
+ template <typename P, typename T>
+ struct pointer_cache_type<P, T, T, pk_unique>
+ {
+ typedef typename object_traits<T>::pointer_type pointer_type;
+
+ static pointer_type
+ convert (const P&) {return pointer_type ();}
+ };
+
+ // reference_cache_type
+ //
+ // Used to convert an object reference to the canonical form (non-const),
+ // suitable for insertion into the cache.
+ //
+ template <typename T,
+ typename O = typename object_traits<T>::object_type>
+ struct reference_cache_type
+ {
+ static O&
+ convert (T& r)
+ {
+ return const_cast<O&> (r);
+ }
+ };
+
+ template <typename T>
+ struct reference_cache_type<T, T>
+ {
+ // If the types are the same, then it is already the canonical form.
+ //
+ static T&
+ convert (T& r) {return r;}
+ };
+
+ // pointer_cache_traits
+ //
+ // Caching traits for objects passed by pointer. P should be the canonical
+ // pointer (non-const).
+ //
+ template <typename P>
+ struct no_id_pointer_cache_traits
+ {
+ typedef P pointer_type;
+ struct position_type {};
+
+ static position_type
+ insert (odb::database&, const pointer_type&)
+ {
+ return position_type ();
+ }
+ };
template <typename P>
- struct pointer_cache_traits: pointer_cache_traits_impl<
- P,
- typename object_traits<typename pointer_traits<P>::element_type>::id_type,
- pointer_traits<P>::kind>
+ struct no_op_pointer_cache_traits
{
+ typedef P pointer_type;
+ typedef typename pointer_traits<pointer_type>::element_type object_type;
+ typedef typename object_traits<object_type>::id_type id_type;
+ struct position_type {};
+
+ struct insert_guard
+ {
+ insert_guard () {}
+ insert_guard (const position_type&) {}
+
+ position_type
+ position () const {return position_type ();}
+
+ void
+ release () {}
+
+ void
+ reset (const position_type&) {}
+ };
+
+ static position_type
+ insert (odb::database&, const id_type&, const pointer_type&)
+ {
+ return position_type ();
+ }
+
+ static position_type
+ insert (odb::database&, const pointer_type&) {return position_type ();}
+
+ static pointer_type
+ find (odb::database&, const id_type&) {return pointer_type ();}
+
+ static void
+ erase (odb::database&, const id_type&) {}
+
+ static void
+ erase (const position_type&) {}
};
- template <typename P, typename ID, pointer_kind kind>
+ template <typename P, pointer_kind pk>
struct pointer_cache_traits_impl
{
typedef P pointer_type;
typedef odb::pointer_traits<pointer_type> pointer_traits;
- typedef typename pointer_traits::element_type element_type;
-
- // element_type can be const while object_type is always non-const.
- //
- typedef typename object_traits<element_type>::object_type object_type;
- typedef typename object_traits<element_type>::id_type id_type;
+ typedef typename pointer_traits::element_type object_type;
+ typedef typename object_traits<object_type>::id_type id_type;
typedef session::object_position<object_type> position_type;
struct insert_guard
{
+ insert_guard () {}
insert_guard (const position_type& pos): pos_ (pos) {}
~insert_guard () {erase (pos_);}
@@ -51,6 +171,11 @@ namespace odb
void
release () {pos_.map_ = 0;}
+ // Note: doesn't call erase() on the old position (assumes not set).
+ //
+ void
+ reset (const position_type& pos) {pos_ = pos;}
+
private:
position_type pos_;
};
@@ -65,12 +190,7 @@ namespace odb
insert (odb::database& db, const id_type& id, const pointer_type& p)
{
if (session::has_current ())
- {
- // Cast away constness if any.
- //
- return session::current ().insert<object_type> (
- db, id, pointer_traits::cast (p));
- }
+ return session::current ().insert<object_type> (db, id, p);
else
return position_type ();
}
@@ -109,102 +229,45 @@ namespace odb
}
};
- template <typename P, pointer_kind kind>
- struct pointer_cache_traits_impl<P, void, kind>
- {
- typedef P pointer_type;
- struct position_type {};
-
- static position_type
- insert (odb::database&, const pointer_type&)
- {
- return position_type ();
- }
- };
-
// Unique pointers don't work with the object cache.
//
- template <typename P, typename ID>
- struct pointer_cache_traits_impl<P, ID, pk_unique>
- {
- typedef P pointer_type;
- typedef typename pointer_traits<pointer_type>::element_type element_type;
- typedef typename object_traits<element_type>::id_type id_type;
- struct position_type {};
-
- struct insert_guard
- {
- insert_guard (const position_type&) {}
-
- position_type
- position () const {return position_type ();}
-
- void
- release () {}
- };
-
- static position_type
- insert (odb::database&, const id_type&, const pointer_type&)
- {
- return position_type ();
- }
-
- static position_type
- insert (odb::database&, const pointer_type&)
- {
- return position_type ();
- }
-
- static pointer_type
- find (odb::database&, const id_type&) { return pointer_type (); }
-
- static void
- erase (odb::database&, const id_type&) {}
-
- static void
- erase (const position_type&) {}
- };
+ template <typename P>
+ struct pointer_cache_traits_impl<P, pk_unique>:
+ no_op_pointer_cache_traits<P> {};
template <typename P>
- struct pointer_cache_traits_impl<P, void, pk_unique>
+ struct pointer_cache_traits:
+ pointer_cache_traits_impl<P, pointer_traits<P>::kind> {};
+
+ // reference_cache_traits
+ //
+ // Caching traits for objects passed by reference. T should be the
+ // canonical object type (non-const). Only if the object pointer
+ // kind is raw do we add the object to the session.
+ //
+ template <typename T>
+ struct no_id_reference_cache_traits
{
- typedef P pointer_type;
+ typedef T object_type;
struct position_type {};
static position_type
- insert (odb::database&, const pointer_type&)
+ insert (odb::database&, object_type&)
{
return position_type ();
}
};
- // Caching traits for objects passed by reference. Only if the object
- // pointer kind is raw do we add the object to the session.
- //
- template <typename T, typename ID, pointer_kind kind>
- struct reference_cache_traits_impl;
-
template <typename T>
- struct reference_cache_traits: reference_cache_traits_impl<
- T,
- typename object_traits<T>::id_type,
- pointer_traits<typename object_traits<T>::pointer_type>::kind>
+ struct no_op_reference_cache_traits
{
- };
-
- template <typename T, typename ID, pointer_kind kind>
- struct reference_cache_traits_impl
- {
- typedef T element_type;
- typedef typename object_traits<element_type>::pointer_type pointer_type;
- typedef typename object_traits<element_type>::id_type id_type;
-
- typedef
- typename pointer_cache_traits<pointer_type>::position_type
- position_type;
+ typedef T object_type;
+ typedef typename object_traits<object_type>::id_type id_type;
+ struct position_type {};
struct insert_guard
{
+ insert_guard () {}
insert_guard (const position_type&) {}
position_type
@@ -212,76 +275,57 @@ namespace odb
void
release () {}
+
+ void
+ reset () {}
};
static position_type
- insert (odb::database&, const id_type&, element_type&)
+ insert (odb::database&, const id_type&, object_type&)
{
return position_type ();
}
static position_type
- insert (odb::database&, element_type&)
+ insert (odb::database&, object_type&)
{
return position_type ();
}
};
- template <typename T, pointer_kind kind>
- struct reference_cache_traits_impl<T, void, kind>
- {
- typedef T element_type;
- struct position_type {};
-
- static position_type
- insert (odb::database&, element_type&)
- {
- return position_type ();
- }
- };
+ template <typename T, pointer_kind pk>
+ struct reference_cache_traits_impl: no_op_reference_cache_traits<T> {};
- template <typename T, typename ID>
- struct reference_cache_traits_impl<T, ID, pk_raw>
+ template <typename T>
+ struct reference_cache_traits_impl<T, pk_raw>
{
- typedef T element_type;
- typedef typename object_traits<element_type>::pointer_type pointer_type;
- typedef typename object_traits<element_type>::id_type id_type;
-
- typedef
- typename pointer_cache_traits<pointer_type>::position_type
- position_type;
+ typedef T object_type;
+ typedef typename object_traits<object_type>::pointer_type pointer_type;
+ typedef typename object_traits<object_type>::id_type id_type;
- typedef
- typename pointer_cache_traits<pointer_type>::insert_guard
- insert_guard;
+ typedef pointer_cache_traits<pointer_type> pointer_traits;
+ typedef typename pointer_traits::position_type position_type;
+ typedef typename pointer_traits::insert_guard insert_guard;
static position_type
- insert (odb::database& db, const id_type& id, element_type& obj)
+ insert (odb::database& db, const id_type& id, object_type& obj)
{
pointer_type p (&obj);
- return pointer_cache_traits<pointer_type>::insert (db, id, p);
+ return pointer_traits::insert (db, id, p);
}
static position_type
- insert (odb::database& db, element_type& obj)
+ insert (odb::database& db, object_type& obj)
{
pointer_type p (&obj);
- return pointer_cache_traits<pointer_type>::insert (db, p);
+ return pointer_traits::insert (db, p);
}
};
template <typename T>
- struct reference_cache_traits_impl<T, void, pk_raw>
- {
- typedef T element_type;
- struct position_type {};
-
- static position_type
- insert (odb::database&, element_type&)
- {
- return position_type ();
- }
- };
+ struct reference_cache_traits:
+ reference_cache_traits_impl<
+ T, pointer_traits<typename object_traits<T>::pointer_type>::kind> {};
}
#include <odb/post.hxx>
diff --git a/odb/database.ixx b/odb/database.ixx
index d4869c1..4a00a74 100644
--- a/odb/database.ixx
+++ b/odb/database.ixx
@@ -2,7 +2,7 @@
// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
-#include <cstring> // std::string
+#include <cstring> // std::strlen()
namespace odb
{
@@ -105,6 +105,28 @@ namespace odb
}
template <typename T>
+ inline typename object_traits<T>::pointer_type database::
+ find (const typename object_traits<T>::id_type& id)
+ {
+ // T is always object_type.
+ //
+
+ // Compiler error pointing here? Perhaps the object doesn't have the
+ // default constructor?
+ //
+ return object_traits<T>::find (*this, id);
+ }
+
+ template <typename T>
+ inline bool database::
+ find (const typename object_traits<T>::id_type& id, T& obj)
+ {
+ // T is always object_type.
+ //
+ return object_traits<T>::find (*this, id, obj);
+ }
+
+ template <typename T>
inline void database::
reload (T* p)
{
@@ -218,6 +240,41 @@ namespace odb
template <typename T>
inline void database::
+ update (T& obj)
+ {
+ // T can be const T while object_type will always be T.
+ //
+ typedef typename odb::object_traits<T>::object_type object_type;
+ typedef odb::object_traits<object_type> object_traits;
+
+ // Compiler error pointing here? Perhaps the object is readonly or
+ // doesn't have an object id? Such objects cannot be updated.
+ //
+ object_traits::update (*this, obj);
+ }
+
+ template <typename T>
+ inline void database::
+ update_ (const typename object_traits<T>::pointer_type& pobj)
+ {
+ // T can be const T while object_type will always be T.
+ //
+ typedef typename odb::object_traits<T>::object_type object_type;
+ typedef odb::object_traits<object_type> object_traits;
+
+ typedef typename odb::object_traits<T>::pointer_type pointer_type;
+ typedef odb::pointer_traits<pointer_type> pointer_traits;
+
+ T& obj (pointer_traits::get_ref (pobj));
+
+ // Compiler error pointing here? Perhaps the object is readonly or
+ // doesn't have an object id? Such objects cannot be updated.
+ //
+ object_traits::update (*this, obj);
+ }
+
+ template <typename T>
+ inline void database::
erase (T* p)
{
typedef typename object_traits<T>::pointer_type object_pointer;
@@ -295,6 +352,26 @@ namespace odb
}
template <typename T>
+ inline void database::
+ erase (const typename object_traits<T>::id_type& id)
+ {
+ // T is always object_type.
+ //
+ object_traits<T>::erase (*this, id);
+ }
+
+ template <typename T>
+ inline void database::
+ erase (T& obj)
+ {
+ // T can be const T while object_type will always be T.
+ //
+ typedef typename object_traits<T>::object_type object_type;
+
+ object_traits<object_type>::erase (*this, obj);
+ }
+
+ template <typename T>
inline unsigned long long database::
erase_query ()
{
@@ -322,6 +399,15 @@ namespace odb
}
template <typename T>
+ inline unsigned long long database::
+ erase_query (const odb::query<T>& q)
+ {
+ // T is always object_type.
+ //
+ return object_traits<T>::erase_query (*this, q);
+ }
+
+ template <typename T>
inline result<T> database::
query (bool cache)
{
diff --git a/odb/database.txx b/odb/database.txx
index dd0d995..abc6ba3 100644
--- a/odb/database.txx
+++ b/odb/database.txx
@@ -5,7 +5,6 @@
#include <odb/exceptions.hxx>
#include <odb/transaction.hxx>
#include <odb/session.hxx>
-#include <odb/callback.hxx>
#include <odb/cache-traits.hxx>
#include <odb/pointer-traits.hxx>
@@ -20,14 +19,10 @@ namespace odb
typedef typename odb::object_traits<T>::object_type object_type;
typedef odb::object_traits<object_type> object_traits;
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- object_traits::callback (*this, obj, callback_event::pre_persist);
object_traits::persist (*this, obj);
- object_traits::callback (*this, obj, callback_event::post_persist);
- reference_cache_traits<T>::insert (*this, obj);
+ object_traits::reference_cache_traits::insert (
+ *this, reference_cache_type<T>::convert (obj));
return object_traits::id (obj);
}
@@ -44,16 +39,13 @@ namespace odb
typedef typename odb::object_traits<T>::pointer_type pointer_type;
typedef odb::pointer_traits<pointer_type> pointer_traits;
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
T& obj (pointer_traits::get_ref (pobj));
-
- object_traits::callback (*this, obj, callback_event::pre_persist);
object_traits::persist (*this, obj);
- object_traits::callback (*this, obj, callback_event::post_persist);
- pointer_cache_traits<pointer_type>::insert (*this, pobj);
+ // Get the canonical object pointer and insert it into object cache.
+ //
+ object_traits::pointer_cache_traits::insert (
+ *this, pointer_cache_type<pointer_type>::convert (pobj));
return object_traits::id (obj);
}
@@ -91,150 +83,14 @@ namespace odb
//
typedef odb::object_traits<T> object_traits;
+ // We don't need to check for transaction here;
+ // object_traits::reload () does this.
+
if (!object_traits::reload (*this, obj))
throw object_not_persistent ();
}
template <typename T>
- typename object_traits<T>::pointer_type database::
- find (const typename object_traits<T>::id_type& id)
- {
- // T is always object_type.
- //
- typedef odb::object_traits<T> object_traits;
- typedef typename object_traits::pointer_type pointer_type;
- typedef odb::pointer_traits<pointer_type> pointer_traits;
-
- // First check the session.
- //
- {
- pointer_type p (
- pointer_cache_traits<pointer_type>::find (*this, id));
-
- if (!pointer_traits::null_ptr (p))
- return p;
- }
-
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- // Compiler error pointing here? Perhaps the object doesn't have the
- // default constructor?
- //
- return pointer_type (object_traits::find (*this, id));
- }
-
- template <typename T>
- bool database::
- find (const typename object_traits<T>::id_type& id, T& obj)
- {
- // T is always object_type.
- //
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- return object_traits<T>::find (*this, id, obj);
- }
-
- template <typename T>
- void database::
- update (T& obj)
- {
- // T can be const T while object_type will always be T.
- //
- typedef typename odb::object_traits<T>::object_type object_type;
- typedef odb::object_traits<object_type> object_traits;
-
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- object_traits::callback (*this, obj,callback_event::pre_update);
-
- // Compiler error pointing here? Perhaps the object is readonly or
- // doesn't have an object id? Such objects cannot be updated.
- //
- object_traits::update (*this, obj);
-
- object_traits::callback (*this, obj, callback_event::post_update);
- }
-
- template <typename T>
- void database::
- update_ (const typename object_traits<T>::pointer_type& pobj)
- {
- // T can be const T while object_type will always be T.
- //
- typedef typename odb::object_traits<T>::object_type object_type;
- typedef odb::object_traits<object_type> object_traits;
-
- typedef typename odb::object_traits<T>::pointer_type pointer_type;
- typedef odb::pointer_traits<pointer_type> pointer_traits;
-
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- T& obj (pointer_traits::get_ref (pobj));
-
- object_traits::callback (*this, obj, callback_event::pre_update);
-
- // Compiler error pointing here? Perhaps the object is readonly or
- // doesn't have an object id? Such objects cannot be updated.
- //
- object_traits::update (*this, obj);
-
- object_traits::callback (*this, obj, callback_event::post_update);
- }
-
- template <typename T>
- void database::
- erase (const typename object_traits<T>::id_type& id)
- {
- // T is always object_type.
- //
- typedef odb::object_traits<T> object_traits;
- typedef typename object_traits::pointer_type pointer_type;
-
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- object_traits::erase (*this, id);
- pointer_cache_traits<pointer_type>::erase (*this, id);
- }
-
- template <typename T>
- void database::
- erase (T& obj)
- {
- // T can be const T while object_type will always be T.
- //
- typedef typename odb::object_traits<T>::object_type object_type;
- typedef odb::object_traits<object_type> object_traits;
- typedef typename object_traits::pointer_type pointer_type;
-
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- typename object_traits::id_type id (object_traits::id (obj));
-
- object_traits::callback (*this, obj, callback_event::pre_erase);
- object_traits::erase (*this, obj);
- pointer_cache_traits<pointer_type>::erase (*this, id);
- object_traits::callback (*this, obj, callback_event::post_erase);
- }
-
- template <typename T>
- unsigned long long database::
- erase_query (const odb::query<T>& q)
- {
- // T is always object_type.
- //
- if (!transaction::has_current ())
- throw not_in_transaction ();
-
- return object_traits<T>::erase_query (*this, q);
- }
-
- template <typename T>
struct database::query_<T, class_object>
{
static result<T>
diff --git a/odb/exceptions.cxx b/odb/exceptions.cxx
index b200843..d56711c 100644
--- a/odb/exceptions.cxx
+++ b/odb/exceptions.cxx
@@ -94,6 +94,18 @@ namespace odb
return "query result is not cached";
}
+ const char* abstract_class::
+ what () const throw ()
+ {
+ return "database operation on instance of abstract class";
+ }
+
+ const char* no_type_info::
+ what () const throw ()
+ {
+ return "no type information";
+ }
+
unknown_schema::
unknown_schema (const std::string& name)
: name_ (name)
diff --git a/odb/exceptions.hxx b/odb/exceptions.hxx
index b55b2a4..9e37967 100644
--- a/odb/exceptions.hxx
+++ b/odb/exceptions.hxx
@@ -113,6 +113,20 @@ namespace odb
{
};
+ // Polymorphism support exceptions.
+ //
+ struct LIBODB_EXPORT abstract_class: exception
+ {
+ virtual const char*
+ what () const throw ();
+ };
+
+ struct LIBODB_EXPORT no_type_info: exception
+ {
+ virtual const char*
+ what () const throw ();
+ };
+
// Schema catalog exceptions.
//
struct LIBODB_EXPORT unknown_schema: exception
@@ -156,6 +170,9 @@ namespace odb
using odb::result_not_cached;
using odb::database_exception;
+ using odb::abstract_class;
+ using odb::no_type_info;
+
using odb::unknown_schema;
}
}
diff --git a/odb/forward.hxx b/odb/forward.hxx
index 97bc7a8..4c5e4b9 100644
--- a/odb/forward.hxx
+++ b/odb/forward.hxx
@@ -73,6 +73,20 @@ namespace odb
template <typename T>
struct view_traits;
+ // Cache traits.
+ //
+ template <typename T> struct no_id_pointer_cache_traits;
+ template <typename T> struct no_op_pointer_cache_traits;
+ template <typename T> struct pointer_cache_traits;
+ template <typename T> struct no_id_reference_cache_traits;
+ template <typename T> struct no_op_reference_cache_traits;
+ template <typename T> struct reference_cache_traits;
+
+ // Polymorphism support.
+ //
+ template <typename R>
+ struct polymorphic_map;
+
namespace details
{
template <>
diff --git a/odb/no-id-object-result.hxx b/odb/no-id-object-result.hxx
new file mode 100644
index 0000000..8893e7a
--- /dev/null
+++ b/odb/no-id-object-result.hxx
@@ -0,0 +1,191 @@
+// file : odb/no-id-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_NO_ID_OBJECT_RESULT_HXX
+#define ODB_NO_ID_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+#include <utility> // std::move
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+#include <odb/result.hxx>
+#include <odb/object-result.hxx>
+#include <odb/pointer-traits.hxx>
+
+#include <odb/details/config.hxx> // ODB_CXX11
+#include <odb/details/shared-ptr.hxx>
+
+namespace odb
+{
+ // Implementation for objects without object id (always non-polymorphic).
+ //
+ template <typename T>
+ class no_id_object_result_impl: public details::shared_base
+ {
+ public:
+ virtual
+ ~no_id_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::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, void, false>;
+ friend class object_result_iterator<const T, void, false>;
+
+ protected:
+ no_id_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 ()
+ {
+ if (pointer_traits::null_ptr (current_) && !end_)
+ load ();
+
+ return 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 void
+ next () = 0;
+
+ virtual void
+ cache () = 0;
+
+ virtual std::size_t
+ size () = 0;
+
+ protected:
+#ifdef ODB_CXX11
+ void
+ current (pointer_type& p)
+ {
+ current_ = std::move (p);
+ guard_.reset (current_);
+ }
+
+ void
+ current (pointer_type&& p)
+ {
+ current (p);
+ }
+#else
+ void
+ current (pointer_type p)
+ {
+ current_ = p;
+ guard_.reset (current_);
+ }
+#endif
+
+ bool begin_;
+ bool end_;
+
+ private:
+ void
+ load ();
+
+ private:
+ database_type& db_;
+ pointer_type current_;
+ typename pointer_traits::guard guard_;
+ };
+
+ template <typename T>
+ class object_result_iterator<T, void, false>
+ {
+ public:
+ // T can be const T while object_type is always non-const.
+ //
+ typedef typename object_traits<T>::object_type object_type;
+
+ typedef no_id_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& obj)
+ {
+ // Objects without ids are not stored in session cache.
+ //
+ if (!res_->end ())
+ res_->load (obj);
+ }
+
+ protected:
+ result_impl_type* res_;
+ };
+}
+
+#include <odb/no-id-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_NO_ID_OBJECT_RESULT_HXX
diff --git a/odb/no-id-object-result.txx b/odb/no-id-object-result.txx
new file mode 100644
index 0000000..99bd80e
--- /dev/null
+++ b/odb/no-id-object-result.txx
@@ -0,0 +1,28 @@
+// file : odb/no-id-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ //
+ // object_result_impl
+ //
+
+ template <typename T>
+ no_id_object_result_impl<T>::
+ ~no_id_object_result_impl ()
+ {
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ load ()
+ {
+ // Objects without ids are not stored in session cache.
+ //
+ pointer_type p (object_traits::create ());
+ object_type& obj (pointer_traits::get_ref (p));
+ current (p);
+ load (obj);
+ }
+}
diff --git a/odb/object-result.hxx b/odb/object-result.hxx
index 759c9f5..f966018 100644
--- a/odb/object-result.hxx
+++ b/odb/object-result.hxx
@@ -7,363 +7,66 @@
#include <odb/pre.hxx>
-#include <cstddef> // std::ptrdiff_t, std::size_t
+#include <cstddef> // std::ptrdiff_t
#include <iterator> // iterator categories
-#include <utility> // std::move
#include <odb/forward.hxx>
+#include <odb/traits.hxx>
#include <odb/result.hxx>
#include <odb/pointer-traits.hxx>
-#include <odb/details/config.hxx> // ODB_CXX11
-#include <odb/details/shared-ptr.hxx>
-
namespace odb
{
+ //
+ // object_result_impl
+ //
template <typename T>
class object_result_impl;
template <typename T>
- class object_result_impl_no_id;
+ class polymorphic_object_result_impl;
- template <typename T, typename ID>
- class object_result_iterator;
+ template <typename T>
+ class no_id_object_result_impl;
+
+ //
+ // object_result_impl_selector
+ //
+ template <typename T,
+ typename ID = typename object_traits<T>::id_type,
+ bool polymorphic = object_traits<T>::polymorphic>
+ struct object_result_impl_selector;
- template <typename T, typename ID = typename object_traits<T>::id_type>
- struct object_result_impl_selector
+ template <typename T, typename ID>
+ struct object_result_impl_selector<T, ID, false>
{
typedef object_result_impl<T> type;
};
- template <typename T>
- struct object_result_impl_selector<T, void>
+ template <typename T, typename ID>
+ struct object_result_impl_selector<T, ID, true>
{
- typedef object_result_impl_no_id<T> type;
+ typedef polymorphic_object_result_impl<T> type;
};
- // Implementation for objects with object id.
- //
template <typename T>
- class object_result_impl: public details::shared_base
+ struct object_result_impl_selector<T, void, false>
{
- public:
- virtual
- ~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:
- // The fetch argument is a hint to the implementation. If it is
- // false then it means load_id() was already called (and presumably
- // fetched the data into the object image) and the object image
- // is still valid (so the implementation doesn't need to fetch
- // the data again).
- //
- virtual void
- load (object_type&, bool fetch = true) = 0;
-
- virtual id_type
- load_id () = 0;
-
- virtual void
- next () = 0;
-
- virtual void
- cache () = 0;
-
- virtual std::size_t
- size () = 0;
-
- protected:
-#ifdef ODB_CXX11
- void
- current (pointer_type& p)
- {
- current_ = std::move (p);
- guard_.reset (current_);
- }
-
- void
- current (pointer_type&& p)
- {
- current (p);
- }
-#else
- void
- current (pointer_type p)
- {
- current_ = p;
- guard_.reset (current_);
- }
-#endif
-
- 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::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, 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_ ()
- {
- }
-
- 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 void
- next () = 0;
-
- virtual void
- cache () = 0;
-
- virtual std::size_t
- size () = 0;
-
- protected:
-#ifdef ODB_CXX11
- void
- current (pointer_type& p)
- {
- current_ = std::move (p);
- guard_.reset (current_);
- }
-
- void
- current (pointer_type&& p)
- {
- current (p);
- }
-#else
- void
- current (pointer_type p)
- {
- current_ = p;
- guard_.reset (current_);
- }
-#endif
-
- bool begin_;
- bool end_;
-
- private:
- database_type& db_;
- pointer_type current_;
- typename pointer_traits::guard guard_;
+ typedef no_id_object_result_impl<T> type;
};
//
// 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&);
-
- id_type
- id ()
- {
- return res_->load_id ();
- }
-
- protected:
- result_impl_type* res_;
- };
-
- template <typename T>
- 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, typename ID, bool polymorphic>
+ class object_result_iterator;
template <typename T>
class result_iterator<T, class_object>: public object_result_iterator<
T,
- typename object_traits<T>::id_type>
+ typename object_traits<T>::id_type,
+ object_traits<T>::polymorphic>
{
public:
typedef T value_type;
@@ -375,8 +78,9 @@ namespace odb
// T can be const T while object_type is always non-const.
//
typedef
- object_result_iterator<T, typename object_traits<T>::id_type>
- base_type;
+ object_result_iterator<T,
+ typename object_traits<T>::id_type,
+ object_traits<T>::polymorphic> base_type;
public:
explicit
@@ -456,8 +160,6 @@ namespace odb
};
}
-#include <odb/object-result.txx>
-
#include <odb/post.hxx>
#endif // ODB_OBJECT_RESULT_HXX
diff --git a/odb/object-result.txx b/odb/object-result.txx
deleted file mode 100644
index 7972da1..0000000
--- a/odb/object-result.txx
+++ /dev/null
@@ -1,112 +0,0 @@
-// file : odb/object-result.txx
-// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
-// license : GNU GPL v2; see accompanying LICENSE file
-
-#include <odb/session.hxx>
-#include <odb/cache-traits.hxx>
-
-namespace odb
-{
- //
- // object_result_impl
- //
-
- template <typename T>
- object_result_impl<T>::
- ~object_result_impl ()
- {
- }
-
- template <typename T>
- typename object_result_impl<T>::pointer_type&
- object_result_impl<T>::
- current ()
- {
- if (pointer_traits::null_ptr (current_) && !end_)
- {
- if (!session::has_current ())
- {
- pointer_type p (object_traits::create ());
- object_type& obj (pointer_traits::get_ref (p));
- current (p);
- load (obj);
- }
- else
- {
- // First check the session.
- //
- const id_type& id (load_id ());
-
- pointer_type p (
- pointer_cache_traits<pointer_type>::find (database (), id));
-
- if (!pointer_traits::null_ptr (p))
- current (p);
- else
- {
- pointer_type p (object_traits::create ());
-
- typename pointer_cache_traits<pointer_type>::insert_guard ig (
- pointer_cache_traits<pointer_type>::insert (database (), id, p));
-
- object_type& obj (pointer_traits::get_ref (p));
- current (p);
- load (obj, false);
- ig.release ();
- }
- }
- }
-
- return current_;
- }
-
- //
- // object_result_impl_no_id
- //
- template <typename T>
- object_result_impl_no_id<T>::
- ~object_result_impl_no_id ()
- {
- }
-
- template <typename T>
- typename object_result_impl_no_id<T>::pointer_type&
- object_result_impl_no_id<T>::
- current ()
- {
- if (pointer_traits::null_ptr (current_) && !end_)
- {
- // Objects without ids are not stored in session cache.
- //
- pointer_type p (object_traits::create ());
- object_type& obj (pointer_traits::get_ref (p));
- current (p);
- load (obj);
- }
-
- return current_;
- }
-
- //
- // object_result_iterator
- //
-
- template <typename T, typename ID>
- void object_result_iterator<T, ID>::
- load (object_type& obj)
- {
- if (res_->end ())
- return;
-
- if (!session::has_current ())
- res_->load (obj);
- else
- {
- typename reference_cache_traits<object_type>::insert_guard ig (
- reference_cache_traits<object_type>::insert (
- res_->database (), res_->load_id (), obj));
- res_->load (obj, false);
- ig.release ();
- }
- }
-}
diff --git a/odb/pointer-traits.hxx b/odb/pointer-traits.hxx
index fbfa721..a24bf02 100644
--- a/odb/pointer-traits.hxx
+++ b/odb/pointer-traits.hxx
@@ -47,7 +47,7 @@ namespace odb
release () {p_ = 0;}
void
- reset (P p) {delete p_; p_ = p;}
+ reset (P p = 0) {delete p_; p_ = p;}
private:
P p_;
@@ -68,6 +68,9 @@ namespace odb
release () {}
void
+ reset () {}
+
+ void
reset (const P&) {}
};
@@ -111,14 +114,28 @@ namespace odb
return p == 0;
}
- // Cast away constness.
+ // Casts.
//
static unrestricted_pointer_type
- cast (pointer_type p)
+ const_pointer_cast (pointer_type p)
{
return const_cast<unrestricted_pointer_type> (p);
}
+ template <typename T1>
+ static T1*
+ static_pointer_cast (pointer_type p)
+ {
+ return static_cast<T1*> (p);
+ }
+
+ template <typename T1>
+ static T1*
+ dynamic_pointer_cast (pointer_type p)
+ {
+ return dynamic_cast<T1*> (p);
+ }
+
public:
// Allocate memory for an element that will be managed by this
// pointer.
@@ -174,9 +191,32 @@ namespace odb
return p.get () == 0;
}
- // cast() is not provided since it transfers the ownership.
+ // const_pointer_cast() is not provided.
//
+ // Note: transfers ownership.
+ //
+ template <typename T1>
+ static std::auto_ptr<T1>
+ static_pointer_cast (pointer_type& p)
+ {
+ return std::auto_ptr<T1> (static_cast<T1*> (p.release ()));
+ }
+
+ // Note: transfers ownership if successful.
+ //
+ template <typename T1>
+ static std::auto_ptr<T1>
+ dynamic_pointer_cast (pointer_type& p)
+ {
+ T1* p1 (dynamic_cast<T1*> (p.get ()));
+
+ if (p1 != 0)
+ p.release ();
+
+ return std::auto_ptr<T1> (p1);
+ }
+
public:
static void*
allocate (std::size_t n)
@@ -225,8 +265,31 @@ namespace odb
return !p;
}
- // cast() is not provided since it transfers the ownership.
+ // const_pointer_cast() is not provided.
+ //
+
+ // Note: transfers ownership.
//
+ template <typename T1>
+ static std::unique_ptr<T1>
+ static_pointer_cast (pointer_type& p)
+ {
+ return std::unique_ptr<T1> (static_cast<T1*> (p.release ()));
+ }
+
+ // Note: transfers ownership if successful.
+ //
+ template <typename T1>
+ static std::unique_ptr<T1>
+ dynamic_pointer_cast (pointer_type& p)
+ {
+ T1* p1 (dynamic_cast<T1*> (p.get ()));
+
+ if (p1 != 0)
+ p.release ();
+
+ return std::unique_ptr<T1> (p1);
+ }
public:
static void*
@@ -279,11 +342,25 @@ namespace odb
}
static unrestricted_pointer_type
- cast (const pointer_type& p)
+ const_pointer_cast (const pointer_type& p)
{
return std::const_pointer_cast<unrestricted_element_type> (p);
}
+ template <typename T1>
+ static std::shared_ptr<T1>
+ static_pointer_cast (const pointer_type& p)
+ {
+ return std::static_pointer_cast<T1> (p);
+ }
+
+ template <typename T1>
+ static std::shared_ptr<T1>
+ dynamic_pointer_cast (const pointer_type& p)
+ {
+ return std::dynamic_pointer_cast<T1> (p);
+ }
+
public:
static void*
allocate (std::size_t n)
diff --git a/odb/polymorphic-info.hxx b/odb/polymorphic-info.hxx
new file mode 100644
index 0000000..349f062
--- /dev/null
+++ b/odb/polymorphic-info.hxx
@@ -0,0 +1,118 @@
+// file : odb/polymorphic-info.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_POLYMORPHIC_INFO_HXX
+#define ODB_POLYMORPHIC_INFO_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/forward.hxx> // database
+#include <odb/traits.hxx>
+
+namespace odb
+{
+ template <typename R>
+ struct polymorphic_abstract_info
+ {
+ polymorphic_abstract_info (const std::type_info& t,
+ const polymorphic_abstract_info* b)
+ : type (t), base (b) {}
+
+ bool
+ derived (const polymorphic_abstract_info& b) const
+ {
+ for (const polymorphic_abstract_info* p (base); p != 0; p = p->base)
+ if (&b == p)
+ return true;
+
+ return false;
+ }
+
+ public:
+ const std::type_info& type;
+ const polymorphic_abstract_info* base;
+ };
+
+ template <typename R>
+ struct polymorphic_concrete_info: polymorphic_abstract_info<R>
+ {
+ typedef R root_type;
+ typedef object_traits<root_type> root_traits;
+ typedef typename root_traits::id_type id_type;
+ typedef typename root_traits::pointer_type pointer_type;
+ typedef typename root_traits::discriminator_type discriminator_type;
+
+ enum call_type
+ {
+ call_callback, // arg points to callback event.
+ call_persist, // arg is not used.
+ call_update, // arg is not used.
+ call_find, // arg points to object id.
+ call_reload, // arg is not used.
+ call_load, // arg points to depth.
+ call_erase // arg points to object id.
+ };
+
+ typedef pointer_type (*create_function) ();
+ typedef bool (*dispatch_function) (
+ call_type, database&, const root_type*, const void* arg);
+ typedef void (*delayed_loader_function) (
+ database&, const id_type&, root_type&);
+
+ public:
+ polymorphic_concrete_info (const std::type_info& t,
+ const polymorphic_abstract_info<R>* b,
+ const discriminator_type& d,
+ create_function cf,
+ dispatch_function df,
+ delayed_loader_function dlf)
+ : polymorphic_abstract_info<R> (t, b),
+ discriminator (d),
+ create (cf), dispatch (df), delayed_loader (dlf)
+ {
+ }
+
+ public:
+ discriminator_type discriminator;
+ create_function create;
+ dispatch_function dispatch;
+ delayed_loader_function delayed_loader;
+ };
+
+ // Register concrete type T in the root's map.
+ //
+ template <typename T>
+ struct polymorphic_entry
+ {
+ typedef T object_type;
+ typedef odb::object_traits<object_type> object_traits;
+
+ typedef typename object_traits::root_type root_type;
+ typedef odb::object_traits<root_type> root_traits;
+
+ polymorphic_entry ();
+ ~polymorphic_entry ();
+ };
+
+ // Helper functions that either return the concrete info or NULL
+ // depending on what kind of info we pass (used in query support).
+ //
+ template <typename R>
+ inline const polymorphic_concrete_info<R>*
+ polymorphic_info (const polymorphic_concrete_info<R>& i)
+ {
+ return &i;
+ }
+
+ template <typename R>
+ inline const polymorphic_concrete_info<R>*
+ polymorphic_info (const polymorphic_abstract_info<R>&)
+ {
+ return 0;
+ }
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_POLYMORPHIC_INFO_HXX
diff --git a/odb/polymorphic-map.hxx b/odb/polymorphic-map.hxx
new file mode 100644
index 0000000..9c18d33
--- /dev/null
+++ b/odb/polymorphic-map.hxx
@@ -0,0 +1,244 @@
+// file : odb/polymorphic-map.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_POLYMORPHIC_MAP_HXX
+#define ODB_POLYMORPHIC_MAP_HXX
+
+#include <odb/pre.hxx>
+
+#include <map>
+#include <utility> // std::move
+#include <cstddef> // std::size_t
+#include <cassert>
+#include <typeinfo>
+
+#include <odb/callback.hxx>
+
+#include <odb/details/config.hxx> // ODB_CXX11
+#include <odb/details/type-info.hxx>
+
+#include <odb/polymorphic-info.hxx>
+
+namespace odb
+{
+ template <typename R>
+ struct polymorphic_map
+ {
+ typedef R root_type;
+ typedef polymorphic_concrete_info<root_type> info_type;
+ typedef typename info_type::discriminator_type discriminator_type;
+
+ polymorphic_map (): ref_count_ (1) {}
+
+ const info_type&
+ find (const std::type_info& t) const;
+
+ const info_type&
+ find (const discriminator_type& d) const;
+
+ public:
+ typedef
+ std::map<const std::type_info*,
+ const info_type*,
+ details::type_info_comparator>
+ type_map;
+
+ struct discriminator_comparator
+ {
+ bool
+ operator() (const discriminator_type* x,
+ const discriminator_type* y) const
+ {
+ return *x < *y;
+ }
+ };
+
+ typedef
+ std::map<const discriminator_type*,
+ const info_type*,
+ discriminator_comparator>
+ discriminator_map;
+
+ public:
+ std::size_t ref_count_;
+ type_map type_map_;
+ discriminator_map discriminator_map_;
+ };
+
+ template <typename R>
+ struct polymorphic_entry_impl
+ {
+ typedef R root_type;
+ typedef object_traits<root_type> root_traits;
+ typedef polymorphic_concrete_info<root_type> info_type;
+
+ static void
+ insert (const info_type&);
+
+ static void
+ erase (const info_type&);
+ };
+
+ template <typename T>
+ typename object_traits<typename object_traits<T>::root_type>::pointer_type
+ create_impl ()
+ {
+ typedef object_traits<T> derived_traits;
+ typedef object_traits<typename derived_traits::root_type> root_traits;
+
+ typedef typename derived_traits::pointer_type derived_pointer_type;
+ typedef typename root_traits::pointer_type root_pointer_type;
+
+ derived_pointer_type p (
+ access::object_factory<T, derived_pointer_type>::create ());
+
+ // Implicit downcast.
+ //
+#ifdef ODB_CXX11
+ root_pointer_type r (std::move (p));
+#else
+ root_pointer_type r (p);
+#endif
+ return r;
+ }
+
+ template <typename T, typename R>
+ struct dispatch_load
+ {
+ static void
+ call (database& db, T& obj, std::size_t d)
+ {
+ object_traits<T>::load_ (db, obj, d);
+ }
+ };
+
+ template <typename R>
+ struct dispatch_load<R, R>
+ {
+ static void
+ call (database&, R&, std::size_t)
+ {
+ assert (false);
+ }
+ };
+
+ template <typename T, bool auto_id>
+ struct dispatch_persist
+ {
+ static void
+ call (database& db, const T& obj)
+ {
+ // Top-level call, no dynamic type checking.
+ //
+ object_traits<T>::persist (db, obj, true, false);
+ }
+ };
+
+ template <typename T>
+ struct dispatch_persist<T, true>
+ {
+ static void
+ call (database& db, const T& obj)
+ {
+ // Top-level call, no dynamic type checking.
+ //
+ object_traits<T>::persist (db, const_cast<T&> (obj), true, false);
+ }
+ };
+
+ template <typename T>
+ bool dispatch_impl (
+ typename polymorphic_concrete_info<
+ typename object_traits<T>::root_type>::call_type c,
+ database& db,
+ const typename object_traits<T>::root_type* pobj,
+ const void* arg)
+ {
+ typedef object_traits<T> derived_traits;
+ typedef typename derived_traits::root_type root_type;
+ typedef object_traits<root_type> root_traits;
+ typedef typename root_traits::id_type id_type;
+ typedef polymorphic_concrete_info<root_type> info_type;
+
+ bool r (false);
+
+ switch (c)
+ {
+ case info_type::call_callback:
+ {
+ derived_traits::callback (
+ db,
+ *const_cast<T*> (static_cast<const T*> (pobj)),
+ *static_cast<const callback_event*> (arg));
+ break;
+ }
+ case info_type::call_persist:
+ {
+ dispatch_persist<T, root_traits::auto_id>::call (
+ db,
+ *static_cast<const T*> (pobj));
+ break;
+ }
+ case info_type::call_update:
+ {
+ derived_traits::update (
+ db,
+ *static_cast<const T*> (pobj),
+ true, // Top-level call.
+ false); // No dynamic type checking.
+ break;
+ }
+ case info_type::call_find:
+ {
+ r = derived_traits::find (
+ db,
+ *static_cast<const id_type*> (arg),
+ *const_cast<T*> (static_cast<const T*> (pobj)),
+ false); // No dynamic type checking.
+ break;
+ }
+ case info_type::call_reload:
+ {
+ r = derived_traits::reload (
+ db,
+ *const_cast<T*> (static_cast<const T*> (pobj)),
+ false); // No dynamic type checking.
+ break;
+ }
+ case info_type::call_load:
+ {
+ dispatch_load<T, root_type>::call (
+ db,
+ *const_cast<T*> (static_cast<const T*> (pobj)),
+ *static_cast<const std::size_t*> (arg));
+ break;
+ }
+ case info_type::call_erase:
+ {
+ if (pobj != 0)
+ derived_traits::erase (
+ db,
+ *static_cast<const T*> (pobj),
+ true, // Top-level call.
+ false); // No dynamic type checking.
+ else
+ derived_traits::erase (
+ db,
+ *static_cast<const id_type*> (arg),
+ true, // Top-level call.
+ false); // No dynamic type checking.
+ break;
+ }
+ }
+
+ return r;
+ }
+}
+
+#include <odb/polymorphic-map.ixx>
+#include <odb/polymorphic-map.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_POLYMORPHIC_MAP_HXX
diff --git a/odb/polymorphic-map.ixx b/odb/polymorphic-map.ixx
new file mode 100644
index 0000000..4dbd174
--- /dev/null
+++ b/odb/polymorphic-map.ixx
@@ -0,0 +1,20 @@
+// file : odb/polymorphic-map.ixx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ template <typename T>
+ inline polymorphic_entry<T>::
+ polymorphic_entry ()
+ {
+ polymorphic_entry_impl<root_type>::insert (object_traits::info);
+ }
+
+ template <typename T>
+ inline polymorphic_entry<T>::
+ ~polymorphic_entry ()
+ {
+ polymorphic_entry_impl<root_type>::erase (object_traits::info);
+ }
+}
diff --git a/odb/polymorphic-map.txx b/odb/polymorphic-map.txx
new file mode 100644
index 0000000..7b1b81a
--- /dev/null
+++ b/odb/polymorphic-map.txx
@@ -0,0 +1,72 @@
+// file : odb/polymorphic-map.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/exceptions.hxx> // no_type_info
+
+namespace odb
+{
+ //
+ // polymorphic_map
+ //
+
+ template <typename R>
+ const typename polymorphic_map<R>::info_type& polymorphic_map<R>::
+ find (const std::type_info& t) const
+ {
+ typename type_map::const_iterator i (type_map_.find (&t));
+
+ if (i != type_map_.end ())
+ return *i->second;
+ else
+ throw no_type_info ();
+ }
+
+ template <typename R>
+ const typename polymorphic_map<R>::info_type& polymorphic_map<R>::
+ find (const discriminator_type& d) const
+ {
+ typename discriminator_map::const_iterator i (
+ discriminator_map_.find (&d));
+
+ if (i != discriminator_map_.end ())
+ return *i->second;
+ else
+ throw no_type_info ();
+ }
+
+ //
+ // polymorphic_entry_impl
+ //
+
+ template <typename R>
+ void polymorphic_entry_impl<R>::
+ insert (const info_type& i)
+ {
+ polymorphic_map<root_type>*& pm (root_traits::map);
+
+ if (pm == 0)
+ pm = new polymorphic_map<root_type>;
+ else
+ pm->ref_count_++;
+
+ pm->type_map_[&i.type] = &i;
+ pm->discriminator_map_[&i.discriminator] = &i;
+ }
+
+ template <typename R>
+ void polymorphic_entry_impl<R>::
+ erase (const info_type& i)
+ {
+ polymorphic_map<root_type>*& pm (root_traits::map);
+
+ pm->discriminator_map_.erase (&i.discriminator);
+ pm->type_map_.erase (&i.type);
+
+ if (--pm->ref_count_ == 0)
+ {
+ delete pm;
+ pm = 0;
+ }
+ }
+}
diff --git a/odb/polymorphic-object-result.hxx b/odb/polymorphic-object-result.hxx
new file mode 100644
index 0000000..805fe96
--- /dev/null
+++ b/odb/polymorphic-object-result.hxx
@@ -0,0 +1,233 @@
+// file : odb/polymorphic-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_POLYMORPHIC_OBJECT_RESULT_HXX
+#define ODB_POLYMORPHIC_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+#include <utility> // std::move
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+#include <odb/result.hxx>
+#include <odb/object-result.hxx>
+#include <odb/pointer-traits.hxx>
+
+#include <odb/details/config.hxx> // ODB_CXX11
+#include <odb/details/shared-ptr.hxx>
+
+namespace odb
+{
+ // Implementation for polymorphic objects with object id.
+ //
+ template <typename T>
+ class polymorphic_object_result_impl: public details::shared_base
+ {
+ public:
+ virtual
+ ~polymorphic_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;
+
+ typedef typename object_traits::root_type root_type;
+ typedef odb::object_traits<root_type> root_traits;
+ typedef typename root_traits::discriminator_type discriminator_type;
+
+ 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, true>;
+ friend class object_result_iterator<const T, id_type, true>;
+
+ protected:
+ polymorphic_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 ()
+ {
+ if (pointer_traits::null_ptr (current_) && !end_)
+ load ();
+
+ return current_;
+ }
+
+ void
+ release ()
+ {
+ current_ = pointer_type ();
+ guard_.release ();
+ }
+
+ void
+ begin ()
+ {
+ if (begin_)
+ {
+ next ();
+ begin_ = false;
+ }
+ }
+
+ bool
+ end () const
+ {
+ return end_;
+ }
+
+ protected:
+ // The fetch argument is a hint to the implementation. If it is
+ // false then it means load_id() was already called (and presumably
+ // fetched the data into the object image) and the object image
+ // is still valid (so the implementation doesn't need to fetch
+ // the data again).
+ //
+ // The load() signature differs from the non-polymorphic cases in
+ // that we pass a pointer to object instead of a reference. The
+ // object is only passed if the user requests loading into an
+ // existing instance. Otherwise, we pass NULL an load() is
+ // responsible for creating the object of a correct dynamic
+ // type and managing the object cache insertion.
+ //
+ virtual void
+ load (object_type*, bool fetch = true) = 0;
+
+ virtual id_type
+ load_id () = 0;
+
+ virtual discriminator_type
+ load_discriminator () = 0;
+
+ virtual void
+ next () = 0;
+
+ virtual void
+ cache () = 0;
+
+ virtual std::size_t
+ size () = 0;
+
+ protected:
+#ifdef ODB_CXX11
+ void
+ current (pointer_type& p, bool guard = true)
+ {
+ current_ = std::move (p);
+
+ if (guard)
+ guard_.reset (current_);
+ else
+ guard_.reset ();
+ }
+
+ void
+ current (pointer_type&& p, bool guard = true)
+ {
+ current (p, guard);
+ }
+#else
+ void
+ current (pointer_type p, bool guard = true)
+ {
+ current_ = p;
+
+ if (guard)
+ guard_.reset (current_);
+ else
+ guard_.reset ();
+ }
+#endif
+
+ bool begin_;
+ bool end_;
+
+ private:
+ void
+ load ();
+
+ private:
+ database_type& db_;
+ pointer_type current_;
+ typename pointer_traits::guard guard_;
+ };
+
+ template <typename T, typename ID>
+ class object_result_iterator<T, ID, true>
+ {
+ 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 typename object_traits<T>::root_type root_type;
+ typedef typename object_traits<root_type>::discriminator_type
+ discriminator_type;
+
+ typedef polymorphic_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&);
+
+ id_type
+ id ()
+ {
+ return res_->load_id ();
+ }
+
+ discriminator_type
+ discriminator ()
+ {
+ return res_->load_discriminator ();
+ }
+
+ protected:
+ result_impl_type* res_;
+ };
+}
+
+#include <odb/polymorphic-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_POLYMORPHIC_OBJECT_RESULT_HXX
diff --git a/odb/polymorphic-object-result.txx b/odb/polymorphic-object-result.txx
new file mode 100644
index 0000000..28331c6
--- /dev/null
+++ b/odb/polymorphic-object-result.txx
@@ -0,0 +1,76 @@
+// file : odb/polymorphic-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/cache-traits.hxx>
+#include <odb/exceptions.hxx>
+
+namespace odb
+{
+ //
+ // polymorphic_object_result_impl
+ //
+
+ template <typename T>
+ polymorphic_object_result_impl<T>::
+ ~polymorphic_object_result_impl ()
+ {
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ load ()
+ {
+ typedef typename root_traits::pointer_type root_pointer_type;
+ typedef typename root_traits::pointer_traits root_pointer_traits;
+
+ // First check the session.
+ //
+ const id_type& id (load_id ());
+
+ root_pointer_type rp (
+ object_traits::pointer_cache_traits::find (database (), id));
+
+ if (!root_pointer_traits::null_ptr (rp))
+ {
+ // Check if the types match.
+ //
+ pointer_type p (
+ root_pointer_traits::template dynamic_pointer_cast<
+ object_type> (rp));
+
+ if (!pointer_traits::null_ptr (p))
+ current (p, false); // Pointer from cache should not be guarded.
+ else
+ // We have an object in session that has a different type
+ // compared to the one in the database.
+ //
+ throw object_not_persistent (); // @@ type_mismatch?
+ }
+ else
+ // load() is responsible for creating the object of a correct
+ // dynamic type and for object cache insertion.
+ //
+ load (0, false);
+ }
+
+ //
+ // object_result_iterator
+ //
+
+ template <typename T, typename ID>
+ void object_result_iterator<T, ID, true>::
+ load (object_type& obj)
+ {
+ if (res_->end ())
+ return;
+
+ typedef odb::object_traits<object_type> object_traits;
+
+ typename object_traits::reference_cache_traits::insert_guard ig (
+ object_traits::reference_cache_traits::insert (
+ res_->database (), res_->load_id (), obj));
+ res_->load (&obj, false);
+ ig.release ();
+ }
+}
diff --git a/odb/query.hxx b/odb/query.hxx
index 0c748d6..e654ade 100644
--- a/odb/query.hxx
+++ b/odb/query.hxx
@@ -11,15 +11,26 @@
namespace odb
{
+ // Table alias for type T and alias tag Tag. The dummy third template
+ // argument is used to make the C++ compiler weed out duplicates.
//
+ // The alias_traits interface consists of two things: the table_name
+ // static variable containing the name and, in case of a derived type
+ // in a polymorphic hierarchy, the base_traits typedef. Note that the
+ // same interface is exposed by object_traits, which is used when
+ // we need straight tables instead of aliases.
//
+ //
+ template <typename T, typename Tag, bool dummy = true>
+ struct alias_traits;
+
template <typename T>
struct query_columns_base;
- template <typename T, const char* table>
+ template <typename T, typename Alias>
struct query_columns;
- template <typename T, const char* table>
+ template <typename T, typename Alias>
struct pointer_query_columns;
// Object pointer syntax wrapper.
diff --git a/odb/result.hxx b/odb/result.hxx
index 14f8c72..29c03df 100644
--- a/odb/result.hxx
+++ b/odb/result.hxx
@@ -9,7 +9,7 @@
#include <cstddef> // std::ptrdiff_t, std::size_t
-#include <odb/forward.hxx> // result
+#include <odb/forward.hxx>
#include <odb/traits.hxx>
namespace odb
@@ -190,10 +190,3 @@ namespace odb
#include <odb/post.hxx>
#endif // ODB_RESULT_HXX
-
-// Include result specializations so that the user code only needs
-// to include this header.
-//
-
-#include <odb/object-result.hxx>
-#include <odb/view-result.hxx>
diff --git a/odb/session.txx b/odb/session.txx
index 553e51a..2a50005 100644
--- a/odb/session.txx
+++ b/odb/session.txx
@@ -28,7 +28,7 @@ namespace odb
std::pair<typename object_map<T>::iterator, bool> r (om.insert (vt));
// In what situation may we possibly attempt to reinsert the object?
- // For example, when the user loads the same object in to different
+ // For example, when the user loads the same object in two different
// instances (i.e., load into a pre-allocated object). In this case
// we should probably update our entries accordingly.
//
diff --git a/odb/simple-object-result.hxx b/odb/simple-object-result.hxx
new file mode 100644
index 0000000..58d8958
--- /dev/null
+++ b/odb/simple-object-result.hxx
@@ -0,0 +1,210 @@
+// file : odb/simple-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_SIMPLE_OBJECT_RESULT_HXX
+#define ODB_SIMPLE_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+#include <utility> // std::move
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+#include <odb/result.hxx>
+#include <odb/object-result.hxx>
+#include <odb/pointer-traits.hxx>
+
+#include <odb/details/config.hxx> // ODB_CXX11
+#include <odb/details/shared-ptr.hxx>
+
+namespace odb
+{
+ // Implementation for non-polymorphic objects with object id.
+ //
+ template <typename T>
+ class object_result_impl: public details::shared_base
+ {
+ public:
+ virtual
+ ~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, false>;
+ friend class object_result_iterator<const T, id_type, false>;
+
+ 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 ()
+ {
+ if (pointer_traits::null_ptr (current_) && !end_)
+ load ();
+
+ return current_;
+ }
+
+ void
+ release ()
+ {
+ current_ = pointer_type ();
+ guard_.release ();
+ }
+
+ void
+ begin ()
+ {
+ if (begin_)
+ {
+ next ();
+ begin_ = false;
+ }
+ }
+
+ bool
+ end () const
+ {
+ return end_;
+ }
+
+ protected:
+ // The fetch argument is a hint to the implementation. If it is
+ // false then it means load_id() was already called (and presumably
+ // fetched the data into the object image) and the object image
+ // is still valid (so the implementation doesn't need to fetch
+ // the data again).
+ //
+ virtual void
+ load (object_type&, bool fetch = true) = 0;
+
+ virtual id_type
+ load_id () = 0;
+
+ virtual void
+ next () = 0;
+
+ virtual void
+ cache () = 0;
+
+ virtual std::size_t
+ size () = 0;
+
+ protected:
+#ifdef ODB_CXX11
+ void
+ current (pointer_type& p, bool guard = true)
+ {
+ current_ = std::move (p);
+
+ if (guard)
+ guard_.reset (current_);
+ else
+ guard_.reset ();
+ }
+
+ void
+ current (pointer_type&& p, bool guard = true)
+ {
+ current (p, guard);
+ }
+#else
+ void
+ current (pointer_type p, bool guard = true)
+ {
+ current_ = p;
+
+ if (guard)
+ guard_.reset (current_);
+ else
+ guard_.reset ();
+ }
+#endif
+
+ bool begin_;
+ bool end_;
+
+ private:
+ void
+ load ();
+
+ private:
+ database_type& db_;
+ pointer_type current_;
+ typename pointer_traits::guard guard_;
+ };
+
+ template <typename T, typename ID>
+ class object_result_iterator<T, ID, false>
+ {
+ 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&);
+
+ id_type
+ id ()
+ {
+ return res_->load_id ();
+ }
+
+ protected:
+ result_impl_type* res_;
+ };
+}
+
+#include <odb/simple-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_SIMPLE_OBJECT_RESULT_HXX
diff --git a/odb/simple-object-result.txx b/odb/simple-object-result.txx
new file mode 100644
index 0000000..832ff7f
--- /dev/null
+++ b/odb/simple-object-result.txx
@@ -0,0 +1,65 @@
+// file : odb/simple-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/cache-traits.hxx>
+
+namespace odb
+{
+ //
+ // object_result_impl
+ //
+
+ template <typename T>
+ object_result_impl<T>::
+ ~object_result_impl ()
+ {
+ }
+
+ template <typename T>
+ void object_result_impl<T>::
+ load ()
+ {
+ // First check the session.
+ //
+ const id_type& id (load_id ());
+
+ pointer_type p (
+ object_traits::pointer_cache_traits::find (database (), id));
+
+ if (!pointer_traits::null_ptr (p))
+ current (p, false); // Pointer from cache should not be guarded.
+ else
+ {
+ p = object_traits::create ();
+
+ typename object_traits::pointer_cache_traits::insert_guard ig (
+ object_traits::pointer_cache_traits::insert (database (), id, p));
+
+ object_type& obj (pointer_traits::get_ref (p));
+ current (p);
+ load (obj, false);
+ ig.release ();
+ }
+ }
+
+ //
+ // object_result_iterator
+ //
+
+ template <typename T, typename ID>
+ void object_result_iterator<T, ID, false>::
+ load (object_type& obj)
+ {
+ if (res_->end ())
+ return;
+
+ typedef odb::object_traits<object_type> object_traits;
+
+ typename object_traits::reference_cache_traits::insert_guard ig (
+ object_traits::reference_cache_traits::insert (
+ res_->database (), res_->load_id (), obj));
+ res_->load (obj, false);
+ ig.release ();
+ }
+}
diff --git a/odb/tr1/pointer-traits.hxx b/odb/tr1/pointer-traits.hxx
index 12e1164..310c448 100644
--- a/odb/tr1/pointer-traits.hxx
+++ b/odb/tr1/pointer-traits.hxx
@@ -61,11 +61,25 @@ namespace odb
}
static unrestricted_pointer_type
- cast (const pointer_type& p)
+ const_pointer_cast (const pointer_type& p)
{
return std::tr1::const_pointer_cast<unrestricted_element_type> (p);
}
+ template <typename T1>
+ static std::tr1::shared_ptr<T1>
+ static_pointer_cast (const pointer_type& p)
+ {
+ return std::tr1::static_pointer_cast<T1> (p);
+ }
+
+ template <typename T1>
+ static std::tr1::shared_ptr<T1>
+ dynamic_pointer_cast (const pointer_type& p)
+ {
+ return std::tr1::dynamic_pointer_cast<T1> (p);
+ }
+
public:
static void*
allocate (std::size_t n)
diff --git a/odb/traits.hxx b/odb/traits.hxx
index 4c71f94..0743dba 100644
--- a/odb/traits.hxx
+++ b/odb/traits.hxx
@@ -138,6 +138,8 @@ namespace odb
typedef typename access::object_traits<T>::object_type object_type;
typedef typename pointer_traits::const_pointer_type const_pointer_type;
typedef const_pointer_type pointer_type;
+
+ static const bool polymorphic = access::object_traits<T>::polymorphic;
};
// Specializations for pointer types to allow the C++ compiler to
diff --git a/odb/view-result.hxx b/odb/view-result.hxx
index dbe77a8..1fd30e0 100644
--- a/odb/view-result.hxx
+++ b/odb/view-result.hxx
@@ -12,6 +12,7 @@
#include <utility> // std::move
#include <odb/forward.hxx>
+#include <odb/traits.hxx>
#include <odb/result.hxx>
#include <odb/pointer-traits.hxx>