summaryrefslogtreecommitdiff
path: root/libodb/odb/database.ixx
diff options
context:
space:
mode:
Diffstat (limited to 'libodb/odb/database.ixx')
-rw-r--r--libodb/odb/database.ixx879
1 files changed, 879 insertions, 0 deletions
diff --git a/libodb/odb/database.ixx b/libodb/odb/database.ixx
new file mode 100644
index 0000000..c3cf2e2
--- /dev/null
+++ b/libodb/odb/database.ixx
@@ -0,0 +1,879 @@
+// file : odb/database.ixx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cstring> // std::strlen()
+#include <utility> // std::move
+#include <iterator>
+
+#include <odb/transaction.hxx>
+#include <odb/pointer-traits.hxx>
+
+namespace odb
+{
+ template <typename T>
+ struct object_pointer_traits
+ {
+ typedef details::meta::no result_type;
+ typedef T object_type;
+ static const T& get_ref (const T& x) {return x;}
+ };
+
+ template <typename T>
+ struct object_pointer_traits<T*>
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const T* p) {return *p;}
+ };
+
+ template <typename T>
+ struct object_pointer_traits<T* const>
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const T* p) {return *p;}
+ };
+
+ template <typename T, template <typename> class P>
+ struct object_pointer_traits<P<T> >
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const P<T>& p) {
+ return pointer_traits<P<T> >::get_ref (p);}
+ };
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ struct object_pointer_traits<P<T, A1> >
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const P<T, A1>& p) {
+ return pointer_traits<P<T, A1> >::get_ref (p);}
+ };
+
+ template <typename T, template <typename> class P>
+ struct object_pointer_traits<const P<T> >
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const P<T>& p) {
+ return pointer_traits<P<T> >::get_ref (p);}
+ };
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ struct object_pointer_traits<const P<T, A1> >
+ {
+ typedef details::meta::yes result_type;
+ typedef T object_type;
+ static const T& get_ref (const P<T, A1>& p) {
+ return pointer_traits<P<T, A1> >::get_ref (p);}
+ };
+
+ inline database::
+ database (database_id id)
+ : id_ (id),
+ tracer_ (0),
+ mutex_ (new details::mutex),
+ schema_version_seq_ (1)
+ {
+ }
+
+ inline database_id database::
+ id () const
+ {
+ return id_;
+ }
+
+ inline database::schema_version_type database::
+ schema_version (const std::string& name) const
+ {
+ return schema_version_migration (name).version;
+ }
+
+ inline bool database::
+ schema_migration (const std::string& name) const
+ {
+ return schema_version_migration (name).migration;
+ }
+
+ inline void database::
+ schema_version_migration (schema_version_type v,
+ bool m,
+ const std::string& name)
+ {
+ schema_version_migration (schema_version_migration_type (v, m), name);
+ }
+
+ inline void database::
+ schema_version_table (const std::string& tname)
+ {
+ schema_version_table_ = tname;
+ }
+
+ inline void database::
+ schema_version_table (const std::string& tname, const std::string& sname)
+ {
+ schema_version_map_[sname].version_table = tname;
+ }
+
+ inline unsigned int database::
+ schema_version_sequence () const
+ {
+ return schema_version_seq_;
+ }
+
+ inline connection_ptr database::
+ connection ()
+ {
+ return connection_ptr (connection_ ());
+ }
+
+#ifndef ODB_CXX11
+ inline void database::
+ query_factory (const char* name, query_factory_ptr f)
+ {
+ query_factory (name, query_factory_wrapper (f));
+ }
+#endif
+
+ inline void database::
+ tracer (tracer_type& t)
+ {
+ tracer_ = &t;
+ }
+
+ inline void database::
+ tracer (tracer_type* t)
+ {
+ tracer_ = t;
+ }
+
+ inline database::tracer_type* database::
+ tracer () const
+ {
+ return tracer_;
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::id_type database::
+ persist (T& obj)
+ {
+ return persist_<T, id_common> (obj);
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::id_type database::
+ persist (const T& obj)
+ {
+ return persist_<const T, id_common> (obj);
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::id_type database::
+ persist (T* p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ return persist_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline typename object_traits<T>::id_type database::
+ persist (const P<T>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ return persist_<T, id_common> (pobj);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline typename object_traits<T>::id_type database::
+ persist (const P<T, A1>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ return persist_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline typename object_traits<T>::id_type database::
+ persist (P<T>& p)
+ {
+ const P<T>& cr (p);
+ return persist<T, P> (cr);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline typename object_traits<T>::id_type database::
+ persist (P<T, A1>& p)
+ {
+ const P<T, A1>& cr (p);
+ return persist<T, A1, P> (cr);
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::id_type database::
+ persist (const typename object_traits<T>::pointer_type& pobj)
+ {
+ return persist_<T, id_common> (pobj);
+ }
+
+ template <typename I>
+ inline void database::
+ persist (I b, I e, bool cont)
+ {
+ persist_<I, id_common> (b, e, cont);
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::pointer_type database::
+ load (const typename object_traits<T>::id_type& id)
+ {
+ return load_<T, id_common> (id);
+ }
+
+ template <typename T>
+ inline void database::
+ load (const typename object_traits<T>::id_type& id, T& obj)
+ {
+ return load_<T, id_common> (id, obj);
+ }
+
+ template <typename T>
+ inline void database::
+ load (T& obj, section& s)
+ {
+ return load_<T, id_common> (obj, s);
+ }
+
+ template <typename T>
+ inline typename object_traits<T>::pointer_type database::
+ find (const typename object_traits<T>::id_type& id)
+ {
+ return find_<T, id_common> (id);
+ }
+
+ template <typename T>
+ inline bool database::
+ find (const typename object_traits<T>::id_type& id, T& obj)
+ {
+ return find_<T, id_common> (id, obj);
+ }
+
+ template <typename T>
+ inline void database::
+ reload (T& obj)
+ {
+ reload_<T, id_common> (obj);
+ }
+
+ template <typename T>
+ inline void database::
+ reload (T* p)
+ {
+ reload<T> (*p);
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ reload (const P<T>& p)
+ {
+ reload (odb::pointer_traits< P<T> >::get_ref (p));
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ reload (const P<T, A1>& p)
+ {
+ reload (odb::pointer_traits< P<T, A1> >::get_ref (p));
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ reload (P<T>& p)
+ {
+ reload (odb::pointer_traits< P<T> >::get_ref (p));
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ reload (P<T, A1>& p)
+ {
+ reload (odb::pointer_traits< P<T, A1> >::get_ref (p));
+ }
+
+ template <typename T>
+ inline void database::
+ reload (const typename object_traits<T>::pointer_type& pobj)
+ {
+ typedef typename object_traits<T>::pointer_type pointer_type;
+
+ reload (odb::pointer_traits<pointer_type>::get_ref (pobj));
+ }
+
+ template <typename T>
+ inline void database::
+ update (T& obj)
+ {
+ update_<T, id_common> (obj);
+ }
+
+ template <typename T>
+ inline void database::
+ update (T* p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ update_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ update (const P<T>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ update_<T, id_common> (pobj);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ update (const P<T, A1>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ update_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ update (P<T>& p)
+ {
+ const P<T>& cr (p);
+ update<T, P> (cr);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ update (P<T, A1>& p)
+ {
+ const P<T, A1>& cr (p);
+ update<T, A1, P> (cr);
+ }
+
+ template <typename T>
+ inline void database::
+ update (const typename object_traits<T>::pointer_type& pobj)
+ {
+ update_<T, id_common> (pobj);
+ }
+
+ template <typename I>
+ inline void database::
+ update (I b, I e, bool cont)
+ {
+ update_<I, id_common> (b, e, cont);
+ }
+
+ template <typename T>
+ inline void database::
+ update (const T& obj, const section& s)
+ {
+ update_<T, id_common> (obj, s);
+ }
+
+ template <typename T>
+ inline void database::
+ erase (const typename object_traits<T>::id_type& id)
+ {
+ return erase_<T, id_common> (id);
+ }
+
+ template <typename T>
+ inline void database::
+ erase (T& obj)
+ {
+ return erase_<T, id_common> (obj);
+ }
+
+ template <typename T>
+ inline void database::
+ erase (T* p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ erase_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ erase (const P<T>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ erase_<T, id_common> (pobj);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ erase (const P<T, A1>& p)
+ {
+ typedef typename object_traits<T>::pointer_type object_pointer;
+
+ // The passed pointer should be the same or implicit-convertible
+ // to the object pointer. This way we make sure the object pointer
+ // does not assume ownership of the passed object.
+ //
+ const object_pointer& pobj (p);
+
+ erase_<T, id_common> (pobj);
+ }
+
+ template <typename T, template <typename> class P>
+ inline void database::
+ erase (P<T>& p)
+ {
+ const P<T>& cr (p);
+ erase<T, P> (cr);
+ }
+
+ template <typename T, typename A1, template <typename, typename> class P>
+ inline void database::
+ erase (P<T, A1>& p)
+ {
+ const P<T, A1>& cr (p);
+ erase<T, A1, P> (cr);
+ }
+
+ template <typename T>
+ inline void database::
+ erase (const typename object_traits<T>::pointer_type& pobj)
+ {
+ erase_<T, id_common> (pobj);
+ }
+
+ template <typename T, typename I>
+ inline void database::
+ erase (I idb, I ide, bool cont)
+ {
+ erase_id_<I, T, id_common> (idb, ide, cont);
+ }
+
+ template <typename I>
+ inline void database::
+ erase (I ob, I oe, bool cont)
+ {
+ erase_object_<I, id_common> (ob, oe, cont);
+ }
+
+ template <typename T>
+ inline unsigned long long database::
+ erase_query ()
+ {
+ // T is always object_type.
+ //
+ return erase_query<T> (odb::query<T> ());
+ }
+
+ template <typename T>
+ inline unsigned long long database::
+ erase_query (const char* q)
+ {
+ // T is always object_type.
+ //
+ return erase_query<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline unsigned long long database::
+ erase_query (const std::string& q)
+ {
+ // T is always object_type.
+ //
+ return erase_query<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline unsigned long long database::
+ erase_query (const odb::query<T>& q)
+ {
+ // T is always object_type.
+ //
+ return object_traits_impl<T, id_common>::erase_query (*this, q);
+ }
+
+ template <typename T>
+ inline result<T> database::
+ query (bool cache)
+ {
+ return query<T> (odb::query<T> (), cache);
+ }
+
+ template <typename T>
+ inline result<T> database::
+ query (const char* q, bool cache)
+ {
+ return query<T> (odb::query<T> (q), cache);
+ }
+
+ template <typename T>
+ inline result<T> database::
+ query (const std::string& q, bool cache)
+ {
+ return query<T> (odb::query<T> (q), cache);
+ }
+
+ template <typename T>
+ inline typename result<T>::pointer_type database::
+ query_one ()
+ {
+ return query_one<T> (odb::query<T> ());
+ }
+
+ template <typename T>
+ inline bool database::
+ query_one (T& o)
+ {
+ return query_one<T> (odb::query<T> (), o);
+ }
+
+ template <typename T>
+ inline T database::
+ query_value ()
+ {
+ return query_value<T> (odb::query<T> ());
+ }
+
+ template <typename T>
+ inline typename result<T>::pointer_type database::
+ query_one (const char* q)
+ {
+ return query_one<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline bool database::
+ query_one (const char* q, T& o)
+ {
+ return query_one<T> (odb::query<T> (q), o);
+ }
+
+ template <typename T>
+ inline T database::
+ query_value (const char* q)
+ {
+ return query_value<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline typename result<T>::pointer_type database::
+ query_one (const std::string& q)
+ {
+ return query_one<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline bool database::
+ query_one (const std::string& q, T& o)
+ {
+ return query_one<T> (odb::query<T> (q), o);
+ }
+
+ template <typename T>
+ inline T database::
+ query_value (const std::string& q)
+ {
+ return query_value<T> (odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline bool database::
+ query_one (const odb::query<T>& q, T& o)
+ {
+ return query_one_<T, id_common> (q, o);
+ }
+
+ template <typename T>
+ inline typename result<T>::pointer_type database::
+ query_one (const odb::query<T>& q)
+ {
+ return query_one_<T, id_common> (q);
+ }
+
+ template <typename T>
+ inline T database::
+ query_value (const odb::query<T>& q)
+ {
+ return query_value_<T, id_common> (q);
+ }
+
+ template <typename T>
+ inline prepared_query<T> database::
+ prepare_query (const char* n, const char* q)
+ {
+ return prepare_query<T> (n, odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline prepared_query<T> database::
+ prepare_query (const char* n, const std::string& q)
+ {
+ return prepare_query<T> (n, odb::query<T> (q));
+ }
+
+ template <typename T>
+ inline prepared_query<T> database::
+ prepare_query (const char* n, const odb::query<T>& q)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ return c.prepare_query (n, q);
+ }
+
+ template <typename T>
+ inline void database::
+ cache_query (const prepared_query<T>& pq)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ c.cache_query (pq);
+ }
+
+#ifdef ODB_CXX11
+ template <typename T, typename P>
+ inline void database::
+ cache_query (const prepared_query<T>& pq, std::unique_ptr<P> params)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ c.cache_query (pq, std::move (params));
+ }
+#else
+ template <typename T, typename P>
+ inline void database::
+ cache_query (const prepared_query<T>& pq, std::auto_ptr<P> params)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ c.cache_query (pq, params);
+ }
+#endif
+
+ template <typename T>
+ inline prepared_query<T> database::
+ lookup_query (const char* name)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ return c.lookup_query<T> (name);
+ }
+
+ template <typename T, typename P>
+ inline prepared_query<T> database::
+ lookup_query (const char* name, P*& params)
+ {
+ connection_type& c (transaction::current ().connection (*this));
+ return c.lookup_query<T, P> (name, params);
+ }
+
+ // Implementations (i.e., the *_() functions).
+ //
+ template <typename I, database_id DB>
+ inline void database::
+ persist_ (I b, I e, bool cont)
+ {
+ // Sun CC with non-standard STL does not have iterator_traits.
+ //
+#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
+ typedef typename std::iterator_traits<I>::value_type value_type;
+#else
+ // Assume iterator is just a pointer.
+ //
+ typedef typename object_pointer_traits<I>::object_type value_type;
+#endif
+
+ typedef object_pointer_traits<value_type> opt;
+
+ persist_<I, typename opt::object_type, id_common> (
+ b, e, cont, typename opt::result_type ());
+ }
+
+ template <typename T, database_id DB>
+ 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_impl<T, DB>::find (*this, id);
+ }
+
+ template <typename T, database_id DB>
+ inline bool database::
+ find_ (const typename object_traits<T>::id_type& id, T& obj)
+ {
+ // T is always object_type.
+ //
+ return object_traits_impl<T, DB>::find (*this, id, obj);
+ }
+
+ template <typename T, database_id DB>
+ inline void database::
+ update_ (T& obj)
+ {
+ // T can be const T while object_type will always be T.
+ //
+ typedef typename object_traits<T>::object_type object_type;
+
+ // Compiler error pointing here? Perhaps the object is readonly or
+ // doesn't have an object id? Such objects cannot be updated.
+ //
+ object_traits_impl<object_type, DB>::update (*this, obj);
+ }
+
+ template <typename T, database_id DB>
+ 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 object_traits<T>::object_type object_type;
+ typedef typename object_traits<T>::pointer_type pointer_type;
+
+ T& obj (pointer_traits<pointer_type>::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_impl<object_type, DB>::update (*this, obj);
+ }
+
+ template <typename T, database_id DB>
+ inline void database::
+ erase_ (const typename object_traits<T>::id_type& id)
+ {
+ // T is always object_type.
+ //
+ object_traits_impl<T, DB>::erase (*this, id);
+ }
+
+ template <typename T, database_id DB>
+ 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_impl<object_type, DB>::erase (*this, obj);
+ }
+
+ template <typename T, database_id DB>
+ inline void database::
+ erase_ (const typename object_traits<T>::pointer_type& pobj)
+ {
+ typedef typename object_traits<T>::pointer_type pointer_type;
+
+ erase_<T, DB> (pointer_traits<pointer_type>::get_ref (pobj));
+ }
+
+ template <typename T, database_id DB, typename Q>
+ inline typename result<T>::pointer_type database::
+ query_one_ (const Q& q)
+ {
+ result<T> r (query_<T, DB>::call (*this, q));
+
+ // We still have to cache the result since loading the object
+ // may result in loading of it's related objects and that would
+ // invalidate the result even for just getting the 'end' status.
+ //
+ r.cache ();
+
+ return r.one ();
+ }
+
+ template <typename T, database_id DB, typename Q>
+ inline bool database::
+ query_one_ (const Q& q, T& o)
+ {
+ result<T> r (query_<T, DB>::call (*this, q));
+ r.cache (); // See above.
+ return r.one (o);
+ }
+
+ template <typename T, database_id DB, typename Q>
+ inline T database::
+ query_value_ (const Q& q)
+ {
+ result<T> r (query_<T, DB>::call (*this, q));
+ r.cache (); // See above.
+
+ // Compiler error pointing here? The object must be default-constructible
+ // in order to use the return-by-value API.
+ //
+ T o;
+ r.value (o);
+ return o;
+ }
+
+ // execute()
+ //
+ inline unsigned long long database::
+ execute (const char* statement)
+ {
+ return execute (statement, std::strlen (statement));
+ }
+
+ inline unsigned long long database::
+ execute (const std::string& statement)
+ {
+ return execute (statement.c_str (), statement.size ());
+ }
+}