aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:01 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:01 +0200
commit42503207920b9264e04c97cb6a5c53214fd2eff8 (patch)
treedd192b60515188e2afd6f11e7cc54aac73f571e4
parent4d0711124bb6cdca491e33a51911d20090a1879a (diff)
Polymorphic inheritance support
-rw-r--r--odb/mysql/binding.hxx4
-rw-r--r--odb/mysql/forward.hxx8
-rw-r--r--odb/mysql/makefile32
-rw-r--r--odb/mysql/no-id-object-result.hxx75
-rw-r--r--odb/mysql/no-id-object-result.txx158
-rw-r--r--odb/mysql/no-id-object-statements.hxx134
-rw-r--r--odb/mysql/no-id-object-statements.txx37
-rw-r--r--odb/mysql/object-result.hxx119
-rw-r--r--odb/mysql/polymorphic-object-result.hxx87
-rw-r--r--odb/mysql/polymorphic-object-result.txx344
-rw-r--r--odb/mysql/polymorphic-object-statements.hxx437
-rw-r--r--odb/mysql/polymorphic-object-statements.txx141
-rw-r--r--odb/mysql/result.hxx25
-rw-r--r--odb/mysql/simple-object-result.hxx79
-rw-r--r--odb/mysql/simple-object-result.txx (renamed from odb/mysql/object-result.txx)162
-rw-r--r--odb/mysql/simple-object-statements.cxx (renamed from odb/mysql/object-statements.cxx)4
-rw-r--r--odb/mysql/simple-object-statements.hxx (renamed from odb/mysql/object-statements.hxx)201
-rw-r--r--odb/mysql/simple-object-statements.ixx (renamed from odb/mysql/object-statements.ixx)2
-rw-r--r--odb/mysql/simple-object-statements.txx (renamed from odb/mysql/object-statements.txx)92
-rw-r--r--odb/mysql/statement-cache.hxx44
-rw-r--r--odb/mysql/statement-cache.txx43
-rw-r--r--odb/mysql/statement.cxx6
-rw-r--r--odb/mysql/view-result.hxx9
-rw-r--r--odb/mysql/view-result.txx2
24 files changed, 1668 insertions, 577 deletions
diff --git a/odb/mysql/binding.hxx b/odb/mysql/binding.hxx
index 3b467f3..10293e2 100644
--- a/odb/mysql/binding.hxx
+++ b/odb/mysql/binding.hxx
@@ -11,8 +11,8 @@
#include <odb/forward.hxx>
-#include <odb/mysql/mysql.hxx>
#include <odb/mysql/version.hxx>
+#include <odb/mysql/mysql-types.hxx>
#include <odb/mysql/details/export.hxx>
@@ -23,6 +23,8 @@ namespace odb
class LIBODB_MYSQL_EXPORT binding
{
public:
+ binding (): bind (0), count (0), version (0) {}
+
binding (MYSQL_BIND* b, std::size_t n)
: bind (b), count (n), version (0)
{
diff --git a/odb/mysql/forward.hxx b/odb/mysql/forward.hxx
index 53a02ff..16bdc4c 100644
--- a/odb/mysql/forward.hxx
+++ b/odb/mysql/forward.hxx
@@ -38,7 +38,13 @@ namespace odb
class object_statements;
template <typename T>
- class object_statements_no_id;
+ class polymorphic_root_object_statements;
+
+ template <typename T>
+ class polymorphic_derived_object_statements;
+
+ template <typename T>
+ class no_id_object_statements;
template <typename T>
class view_statements;
diff --git a/odb/mysql/makefile b/odb/mysql/makefile
index 1aed7ac..1b14f60 100644
--- a/odb/mysql/makefile
+++ b/odb/mysql/makefile
@@ -4,22 +4,22 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
-cxx := \
-connection.cxx \
-connection-factory.cxx \
-database.cxx \
-enum.cxx \
-error.cxx \
-exceptions.cxx \
-object-statements.cxx \
-query.cxx \
-query-const-expr.cxx \
-statement.cxx \
-statements-base.cxx \
-tracer.cxx \
-transaction.cxx \
-transaction-impl.cxx \
-traits.cxx
+cxx := \
+connection.cxx \
+connection-factory.cxx \
+database.cxx \
+enum.cxx \
+error.cxx \
+exceptions.cxx \
+query.cxx \
+query-const-expr.cxx \
+simple-object-statements.cxx \
+statement.cxx \
+statements-base.cxx \
+tracer.cxx \
+traits.cxx \
+transaction.cxx \
+transaction-impl.cxx
cli_tun := details/options.cli
cxx_tun := $(cxx)
diff --git a/odb/mysql/no-id-object-result.hxx b/odb/mysql/no-id-object-result.hxx
new file mode 100644
index 0000000..eb562bf
--- /dev/null
+++ b/odb/mysql/no-id-object-result.hxx
@@ -0,0 +1,75 @@
+// file : odb/mysql/no-id-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_NO_ID_OBJECT_RESULT_HXX
+#define ODB_MYSQL_NO_ID_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/no-id-object-result.hxx>
+
+#include <odb/details/shared-ptr.hxx>
+
+#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/statement.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ class no_id_object_result_impl: public odb::no_id_object_result_impl<T>
+ {
+ public:
+ typedef odb::no_id_object_result_impl<T> base_type;
+
+ typedef typename base_type::object_type object_type;
+ typedef typename base_type::object_traits object_traits;
+
+ typedef typename base_type::pointer_type pointer_type;
+ typedef typename base_type::pointer_traits pointer_traits;
+
+ typedef typename object_traits::statements_type statements_type;
+
+ virtual
+ ~no_id_object_result_impl ();
+
+ no_id_object_result_impl (const query&,
+ details::shared_ptr<select_statement>,
+ statements_type&);
+
+ virtual void
+ load (object_type&);
+
+ virtual void
+ next ();
+
+ virtual void
+ cache ();
+
+ virtual std::size_t
+ size ();
+
+ using base_type::current;
+
+ private:
+ void
+ fetch ();
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ std::size_t count_;
+ };
+ }
+}
+
+#include <odb/mysql/no-id-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_MYSQL_NO_ID_OBJECT_RESULT_HXX
diff --git a/odb/mysql/no-id-object-result.txx b/odb/mysql/no-id-object-result.txx
new file mode 100644
index 0000000..864b49d
--- /dev/null
+++ b/odb/mysql/no-id-object-result.txx
@@ -0,0 +1,158 @@
+// file : odb/mysql/no-id-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <odb/callback.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+
+#include <odb/mysql/no-id-object-statements.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ no_id_object_result_impl<T>::
+ ~no_id_object_result_impl ()
+ {
+ if (!this->end_)
+ statement_->free_result ();
+ }
+
+ template <typename T>
+ no_id_object_result_impl<T>::
+ no_id_object_result_impl (const query&,
+ details::shared_ptr<select_statement> statement,
+ statements_type& statements)
+ : base_type (statements.connection ().database ()),
+ statement_ (statement),
+ statements_ (statements),
+ count_ (0)
+ {
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ load (object_type& obj)
+ {
+ if (count_ > statement_->fetched ())
+ fetch ();
+
+ odb::database& db (this->database ());
+
+ object_traits::callback (db, obj, callback_event::pre_load);
+ object_traits::init (obj, statements_.image (), &db);
+ object_traits::callback (db, obj, callback_event::post_load);
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ next ()
+ {
+ this->current (pointer_type ());
+
+ // If we are cached, simply increment the position and
+ // postpone the actual row fetching until later. This way
+ // if the same object is loaded in between iteration, the
+ // image won't be messed up.
+ //
+ count_++;
+
+ if (statement_->cached ())
+ this->end_ = count_ > statement_->result_size ();
+ else
+ fetch ();
+
+ if (this->end_)
+ statement_->free_result ();
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ fetch ()
+ {
+ // If the result is cached, the image can grow between calls
+ // to fetch() as a result of other statements execution.
+ //
+ if (statement_->cached ())
+ {
+ typename object_traits::image_type& im (statements_.image ());
+
+ if (im.version != statements_.select_image_version ())
+ {
+ binding& b (statements_.select_image_binding ());
+ object_traits::bind (b.bind, im, statement_select);
+ statements_.select_image_version (im.version);
+ b.version++;
+ }
+ }
+
+ while (!this->end_ && count_ > statement_->fetched ())
+ {
+ select_statement::result r (statement_->fetch ());
+
+ switch (r)
+ {
+ case select_statement::truncated:
+ {
+ // Don't re-fetch data we are skipping.
+ //
+ if (count_ != statement_->fetched ())
+ continue;
+
+ typename object_traits::image_type& im (statements_.image ());
+
+ if (object_traits::grow (
+ im, statements_.select_image_truncated ()))
+ im.version++;
+
+ if (im.version != statements_.select_image_version ())
+ {
+ binding& b (statements_.select_image_binding ());
+ object_traits::bind (b.bind, im, statement_select);
+ statements_.select_image_version (im.version);
+ b.version++;
+ statement_->refetch ();
+ }
+ // Fall throught.
+ }
+ case select_statement::success:
+ {
+ break;
+ }
+ case select_statement::no_data:
+ {
+ this->end_ = true;
+ break;
+ }
+ }
+ }
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ cache ()
+ {
+ if (!statement_->cached ())
+ {
+ statement_->cache ();
+
+ if (count_ >= statement_->result_size ())
+ {
+ statement_->free_result ();
+ this->end_ = true;
+ }
+ }
+ }
+
+ template <typename T>
+ std::size_t no_id_object_result_impl<T>::
+ size ()
+ {
+ if (!statement_->cached ())
+ throw result_not_cached ();
+
+ return statement_->result_size ();
+ }
+ }
+}
diff --git a/odb/mysql/no-id-object-statements.hxx b/odb/mysql/no-id-object-statements.hxx
new file mode 100644
index 0000000..89f736b
--- /dev/null
+++ b/odb/mysql/no-id-object-statements.hxx
@@ -0,0 +1,134 @@
+// file : odb/mysql/no-id-object-statements.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_NO_ID_OBJECT_STATEMENTS_HXX
+#define ODB_MYSQL_NO_ID_OBJECT_STATEMENTS_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+
+#include <odb/details/shared-ptr.hxx>
+
+#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx>
+#include <odb/mysql/mysql.hxx>
+#include <odb/mysql/binding.hxx>
+#include <odb/mysql/statement.hxx>
+#include <odb/mysql/statements-base.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ //
+ // Implementation for objects without object id.
+ //
+
+ template <typename T>
+ class no_id_object_statements: public statements_base
+ {
+ public:
+ typedef T object_type;
+ typedef odb::object_traits<object_type> object_traits;
+ typedef typename object_traits::pointer_type pointer_type;
+ typedef typename object_traits::image_type image_type;
+
+ typedef mysql::insert_statement insert_statement_type;
+
+ public:
+ no_id_object_statements (connection_type&);
+
+ virtual
+ ~no_id_object_statements ();
+
+ // Object image.
+ //
+ image_type&
+ image () {return image_;}
+
+ // Insert binding.
+ //
+ std::size_t
+ insert_image_version () const { return insert_image_version_;}
+
+ void
+ insert_image_version (std::size_t v) {insert_image_version_ = v;}
+
+ binding&
+ insert_image_binding () {return insert_image_binding_;}
+
+ // Select binding (needed for query support).
+ //
+ std::size_t
+ select_image_version () const { return select_image_version_;}
+
+ void
+ select_image_version (std::size_t v) {select_image_version_ = v;}
+
+ binding&
+ select_image_binding () {return select_image_binding_;}
+
+ my_bool*
+ select_image_truncated () {return select_image_truncated_;}
+
+ // Statements.
+ //
+ insert_statement_type&
+ persist_statement ()
+ {
+ if (persist_ == 0)
+ persist_.reset (
+ new (details::shared) insert_statement_type (
+ conn_,
+ object_traits::persist_statement,
+ insert_image_binding_,
+ false));
+
+ return *persist_;
+ }
+
+ public:
+ // select = total
+ // insert = total - inverse; inverse == 0 for object without id
+ //
+ static const std::size_t select_column_count =
+ object_traits::column_count;
+
+ static const std::size_t insert_column_count =
+ object_traits::column_count;
+
+ private:
+ no_id_object_statements (const no_id_object_statements&);
+ no_id_object_statements& operator= (const no_id_object_statements&);
+
+ private:
+ image_type image_;
+
+ // Select binding.
+ //
+ std::size_t select_image_version_;
+ binding select_image_binding_;
+ MYSQL_BIND select_image_bind_[select_column_count];
+ my_bool select_image_truncated_[select_column_count];
+
+ // Insert binding.
+ //
+ std::size_t insert_image_version_;
+ binding insert_image_binding_;
+ MYSQL_BIND insert_image_bind_[insert_column_count];
+
+ details::shared_ptr<insert_statement_type> persist_;
+ };
+ }
+}
+
+#include <odb/mysql/no-id-object-statements.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_MYSQL_NO_ID_OBJECT_STATEMENTS_HXX
diff --git a/odb/mysql/no-id-object-statements.txx b/odb/mysql/no-id-object-statements.txx
new file mode 100644
index 0000000..f077b0b
--- /dev/null
+++ b/odb/mysql/no-id-object-statements.txx
@@ -0,0 +1,37 @@
+// file : odb/mysql/no-id-object-statements.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cstring> // std::memset
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ no_id_object_statements<T>::
+ ~no_id_object_statements ()
+ {
+ }
+
+ template <typename T>
+ no_id_object_statements<T>::
+ no_id_object_statements (connection_type& conn)
+ : statements_base (conn),
+ select_image_binding_ (select_image_bind_, select_column_count),
+ insert_image_binding_ (insert_image_bind_, insert_column_count)
+ {
+ image_.version = 0;
+ select_image_version_ = 0;
+ insert_image_version_ = 0;
+
+ std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
+ std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
+ std::memset (
+ select_image_truncated_, 0, sizeof (select_image_truncated_));
+
+ for (std::size_t i (0); i < select_column_count; ++i)
+ select_image_bind_[i].error = select_image_truncated_ + i;
+ }
+ }
+}
diff --git a/odb/mysql/object-result.hxx b/odb/mysql/object-result.hxx
deleted file mode 100644
index 1571588..0000000
--- a/odb/mysql/object-result.hxx
+++ /dev/null
@@ -1,119 +0,0 @@
-// file : odb/mysql/object-result.hxx
-// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
-// license : GNU GPL v2; see accompanying LICENSE file
-
-#ifndef ODB_MYSQL_OBJECT_RESULT_HXX
-#define ODB_MYSQL_OBJECT_RESULT_HXX
-
-#include <odb/pre.hxx>
-
-#include <cstddef> // std::size_t
-
-#include <odb/details/shared-ptr.hxx>
-
-#include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx> // query, object_statements
-#include <odb/mysql/result.hxx>
-#include <odb/mysql/statement.hxx>
-
-namespace odb
-{
- namespace mysql
- {
- template <typename T>
- class object_result_impl: public odb::object_result_impl<T>
- {
- public:
- typedef odb::object_result_impl<T> base_type;
-
- typedef typename base_type::object_type object_type;
- typedef typename base_type::object_traits object_traits;
- typedef typename base_type::id_type id_type;
-
- typedef typename base_type::pointer_type pointer_type;
- typedef typename base_type::pointer_traits pointer_traits;
-
- virtual
- ~object_result_impl ();
-
- object_result_impl (const query&,
- details::shared_ptr<select_statement>,
- object_statements<object_type>&);
-
- virtual void
- load (object_type&, bool fetch);
-
- virtual id_type
- load_id ();
-
- virtual void
- next ();
-
- virtual void
- cache ();
-
- virtual std::size_t
- size ();
-
- using base_type::current;
-
- private:
- void
- fetch (bool next = true);
-
- private:
- details::shared_ptr<select_statement> statement_;
- object_statements<object_type>& statements_;
- std::size_t count_;
- };
-
- template <typename T>
- class object_result_impl_no_id: public odb::object_result_impl_no_id<T>
- {
- public:
- typedef odb::object_result_impl_no_id<T> base_type;
-
- typedef typename base_type::object_type object_type;
- typedef typename base_type::object_traits object_traits;
-
- typedef typename base_type::pointer_type pointer_type;
- typedef typename base_type::pointer_traits pointer_traits;
-
- virtual
- ~object_result_impl_no_id ();
-
- object_result_impl_no_id (const query&,
- details::shared_ptr<select_statement>,
- object_statements_no_id<object_type>&);
-
- virtual void
- load (object_type&);
-
- virtual void
- next ();
-
- virtual void
- cache ();
-
- virtual std::size_t
- size ();
-
- using base_type::current;
-
- private:
- void
- fetch ();
-
- private:
- details::shared_ptr<select_statement> statement_;
- object_statements_no_id<object_type>& statements_;
- std::size_t count_;
- };
- }
-}
-
-#include <odb/mysql/object-result.txx>
-
-#include <odb/post.hxx>
-
-#endif // ODB_MYSQL_OBJECT_RESULT_HXX
diff --git a/odb/mysql/polymorphic-object-result.hxx b/odb/mysql/polymorphic-object-result.hxx
new file mode 100644
index 0000000..59bb74d
--- /dev/null
+++ b/odb/mysql/polymorphic-object-result.hxx
@@ -0,0 +1,87 @@
+// file : odb/mysql/polymorphic-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_POLYMORPHIC_OBJECT_RESULT_HXX
+#define ODB_MYSQL_POLYMORPHIC_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/polymorphic-object-result.hxx>
+
+#include <odb/details/shared-ptr.hxx>
+
+#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/statement.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ class polymorphic_object_result_impl:
+ public odb::polymorphic_object_result_impl<T>
+ {
+ public:
+ typedef odb::polymorphic_object_result_impl<T> base_type;
+
+ typedef typename base_type::object_type object_type;
+ typedef typename base_type::object_traits object_traits;
+ typedef typename base_type::id_type id_type;
+
+ typedef typename base_type::pointer_type pointer_type;
+ typedef typename base_type::pointer_traits pointer_traits;
+
+ typedef typename base_type::root_type root_type;
+ typedef typename base_type::root_traits root_traits;
+ typedef typename base_type::discriminator_type discriminator_type;
+
+ typedef typename object_traits::statements_type statements_type;
+
+ virtual
+ ~polymorphic_object_result_impl ();
+
+ polymorphic_object_result_impl (const query&,
+ details::shared_ptr<select_statement>,
+ statements_type&);
+
+ virtual void
+ load (object_type*, bool fetch);
+
+ virtual id_type
+ load_id ();
+
+ virtual discriminator_type
+ load_discriminator ();
+
+ virtual void
+ next ();
+
+ virtual void
+ cache ();
+
+ virtual std::size_t
+ size ();
+
+ using base_type::current;
+
+ private:
+ void
+ fetch (bool next = true);
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ std::size_t count_;
+ };
+ }
+}
+
+#include <odb/mysql/polymorphic-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_MYSQL_POLYMORPHIC_OBJECT_RESULT_HXX
diff --git a/odb/mysql/polymorphic-object-result.txx b/odb/mysql/polymorphic-object-result.txx
new file mode 100644
index 0000000..2e27677
--- /dev/null
+++ b/odb/mysql/polymorphic-object-result.txx
@@ -0,0 +1,344 @@
+// file : odb/mysql/polymorphic-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cassert>
+
+#include <odb/callback.hxx>
+#include <odb/cache-traits.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+
+#include <odb/mysql/polymorphic-object-statements.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ polymorphic_object_result_impl<T>::
+ ~polymorphic_object_result_impl ()
+ {
+ if (!this->end_)
+ statement_->free_result ();
+ }
+
+ template <typename T>
+ polymorphic_object_result_impl<T>::
+ polymorphic_object_result_impl (const query&,
+ details::shared_ptr<select_statement> st,
+ statements_type& sts)
+ : base_type (sts.connection ().database ()),
+ statement_ (st),
+ statements_ (sts),
+ count_ (0)
+ {
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ load (object_type* pobj, bool f)
+ {
+ if (count_ > statement_->fetched ())
+ fetch ();
+ else if (f && statement_->cached ())
+ {
+ // We have to re-load the image in case it has been overwritten
+ // between the last time we fetched and this call to load().
+ //
+ fetch (false);
+ }
+
+ typename statements_type::root_statements_type& rsts (
+ statements_.root_statements ());
+
+ // This is a top-level call so the statements cannot be locked.
+ //
+ assert (!rsts.locked ());
+ typename statements_type::auto_lock l (rsts);
+
+ odb::database& db (this->database ());
+ typename object_traits::image_type& i (statements_.image ());
+ typename root_traits::image_type& ri (rsts.image ());
+
+ id_type id (root_traits::id (ri));
+
+ // Determine this object's dynamic type.
+ //
+ typedef typename root_traits::info_type info_type;
+ discriminator_type d (root_traits::discriminator (ri));
+ discriminator_type disc (d);
+
+ // Use the polymorphic_info() helper to get concrete_info if
+ // object_type is concrete and NULL if it is abstract.
+ //
+ const info_type* spi (polymorphic_info (object_traits::info));
+ const info_type& pi (
+ spi != 0 && spi->discriminator == d
+ ? *spi
+ : root_traits::map->find (d));
+
+ typedef typename root_traits::pointer_type root_pointer_type;
+ typedef typename root_traits::pointer_traits root_pointer_traits;
+
+ typename object_traits::pointer_cache_traits::insert_guard ig;
+
+ if (pobj == 0)
+ {
+ // Need to create a new instance of the dynamic type.
+ //
+ root_pointer_type rp (pi.create ());
+ pointer_type p (
+ root_pointer_traits::template static_pointer_cast<object_type> (rp));
+
+ // Insert it as a root pointer (for non-unique pointers, rp should
+ // still be valid and for unique pointers this is a no-op).
+ //
+ ig.reset (object_traits::pointer_cache_traits::insert (db, id, rp));
+
+ pobj = &pointer_traits::get_ref (p);
+ current (p);
+ }
+ else
+ {
+ // We are loading into an existing instance. If the static and
+ // dynamic types differ, then make sure the instance is at least
+ // of the dynamic type.
+ //
+ if (&pi != &object_traits::info)
+ {
+ const info_type& dpi (root_traits::map->find (typeid (*pobj)));
+
+ if (&dpi != &pi && dpi.derived (pi))
+ throw object_not_persistent (); // @@ type_mismatch ?
+ }
+ }
+
+ callback_event ce (callback_event::pre_load);
+ pi.dispatch (info_type::call_callback, db, pobj, &ce);
+
+ object_traits::init (*pobj, i, &db);
+
+ // Initialize the id image and binding and load the rest of the object
+ // (containers, dynamic part, etc).
+ //
+ typename object_traits::id_image_type& idi (statements_.id_image ());
+ root_traits::init (idi, id);
+
+ binding& idb (statements_.id_image_binding ());
+ if (idi.version != statements_.id_image_version () || idb.version == 0)
+ {
+ object_traits::bind (idb.bind, idi);
+ statements_.id_image_version (idi.version);
+ idb.version++;
+ }
+
+ object_traits::load_ (statements_, *pobj);
+
+ // Load the dynamic part of the object unless static and dynamic
+ // types are the same.
+ //
+ if (&pi != &object_traits::info)
+ {
+ std::size_t d (object_traits::depth);
+ pi.dispatch (info_type::call_load, db, pobj, &d);
+ };
+
+ rsts.load_delayed ();
+ l.unlock ();
+
+ ce = callback_event::post_load;
+ pi.dispatch (info_type::call_callback, db, pobj, &ce);
+ ig.release ();
+ }
+
+ template <typename T>
+ typename polymorphic_object_result_impl<T>::id_type
+ polymorphic_object_result_impl<T>::
+ load_id ()
+ {
+ if (count_ > statement_->fetched ())
+ fetch ();
+ else if (statement_->cached ())
+ {
+ // We have to re-load the image in case it has been overwritten
+ // between the last time we fetched and this call to load_id().
+ //
+ fetch (false);
+ }
+
+ return root_traits::id (statements_.root_statements ().image ());
+ }
+
+ template <typename T>
+ typename polymorphic_object_result_impl<T>::discriminator_type
+ polymorphic_object_result_impl<T>::
+ load_discriminator ()
+ {
+ if (count_ > statement_->fetched ())
+ fetch ();
+ else if (statement_->cached ())
+ {
+ // We have to re-load the image in case it has been overwritten
+ // between the last time we fetched and this call to
+ // load_discriminator().
+ //
+ fetch (false);
+ }
+
+ return root_traits::discriminator (
+ statements_.root_statements ().image ());
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ next ()
+ {
+ this->current (pointer_type ());
+
+ // If we are cached, simply increment the position and
+ // postpone the actual row fetching until later. This way
+ // if the same object is loaded in between iteration, the
+ // image won't be messed up.
+ //
+ count_++;
+
+ if (statement_->cached ())
+ this->end_ = count_ > statement_->result_size ();
+ else
+ fetch ();
+
+ if (this->end_)
+ statement_->free_result ();
+ }
+
+ template <typename T, typename R>
+ struct polymorphic_image_rebind
+ {
+ // Derived type version.
+ //
+ typedef object_traits<T> traits;
+
+ static bool
+ rebind (typename traits::statements_type& sts)
+ {
+ typename traits::image_type& im (sts.image ());
+
+ if (traits::check_version (sts.select_image_versions (), im))
+ {
+ binding& b (sts.select_image_binding (traits::depth));
+ traits::bind (b.bind, 0, 0, im, statement_select);
+ traits::update_version (
+ sts.select_image_versions (), im, sts.select_image_bindings ());
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ template <typename R>
+ struct polymorphic_image_rebind<R, R>
+ {
+ // Root type version.
+ //
+ typedef object_traits<R> traits;
+
+ static bool
+ rebind (typename traits::statements_type& sts)
+ {
+ typename traits::image_type& im (sts.image ());
+
+ if (im.version != sts.select_image_version ())
+ {
+ binding& b (sts.select_image_binding ());
+ traits::bind (b.bind, im, statement_select);
+ sts.select_image_version (im.version);
+ b.version++;
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ fetch (bool next)
+ {
+ typedef polymorphic_image_rebind<object_type, root_type> image_rebind;
+
+ // If the result is cached, the image can grow between calls
+ // to fetch() as a result of other statements execution.
+ //
+ if (statement_->cached ())
+ image_rebind::rebind (statements_);
+
+ while (!this->end_ && (!next || count_ > statement_->fetched ()))
+ {
+ select_statement::result r (statement_->fetch (next));
+
+ switch (r)
+ {
+ case select_statement::truncated:
+ {
+ // Don't re-fetch data we are skipping.
+ //
+ if (next && count_ != statement_->fetched ())
+ continue;
+
+ typename object_traits::image_type& im (statements_.image ());
+
+ if (object_traits::grow (im,
+ statements_.select_image_truncated ()))
+ im.version++;
+
+ if (image_rebind::rebind (statements_))
+ statement_->refetch ();
+
+ // Fall throught.
+ }
+ case select_statement::success:
+ {
+ break;
+ }
+ case select_statement::no_data:
+ {
+ this->end_ = true;
+ break;
+ }
+ }
+
+ // If we are refetching the current row, then we are done.
+ //
+ if (!next)
+ break;
+ }
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ cache ()
+ {
+ if (!statement_->cached ())
+ {
+ statement_->cache ();
+
+ if (count_ >= statement_->result_size ())
+ {
+ statement_->free_result ();
+ this->end_ = true;
+ }
+ }
+ }
+
+ template <typename T>
+ std::size_t polymorphic_object_result_impl<T>::
+ size ()
+ {
+ if (!statement_->cached ())
+ throw result_not_cached ();
+
+ return statement_->result_size ();
+ }
+ }
+}
diff --git a/odb/mysql/polymorphic-object-statements.hxx b/odb/mysql/polymorphic-object-statements.hxx
new file mode 100644
index 0000000..75b1ae7
--- /dev/null
+++ b/odb/mysql/polymorphic-object-statements.hxx
@@ -0,0 +1,437 @@
+// file : odb/mysql/polymorphic-object-statements.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_POLYMORPHIC_OBJECT_STATEMENTS_HXX
+#define ODB_MYSQL_POLYMORPHIC_OBJECT_STATEMENTS_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+
+#include <odb/details/shared-ptr.hxx>
+
+#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx>
+#include <odb/mysql/mysql.hxx>
+#include <odb/mysql/binding.hxx>
+#include <odb/mysql/statement.hxx>
+#include <odb/mysql/statements-base.hxx>
+#include <odb/mysql/simple-object-statements.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ //
+ // Implementation for polymorphic objects.
+ //
+
+ template <typename T>
+ class polymorphic_root_object_statements: public object_statements<T>
+ {
+ public:
+ typedef typename object_statements<T>::connection_type connection_type;
+ typedef typename object_statements<T>::object_traits object_traits;
+ typedef typename object_statements<T>::id_image_type id_image_type;
+
+ typedef
+ typename object_traits::discriminator_image_type
+ discriminator_image_type;
+
+ typedef
+ typename object_statements<T>::select_statement_type
+ select_statement_type;
+
+ public:
+ // Interface compatibility with derived_object_statements.
+ //
+ typedef polymorphic_root_object_statements root_statements_type;
+
+ root_statements_type&
+ root_statements ()
+ {
+ return *this;
+ }
+
+ public:
+ // Discriminator binding.
+ //
+ discriminator_image_type&
+ discriminator_image () {return discriminator_image_;}
+
+ std::size_t
+ discriminator_image_version () const
+ {return discriminator_image_version_;}
+
+ void
+ discriminator_image_version (std::size_t v)
+ {discriminator_image_version_ = v;}
+
+ binding&
+ discriminator_image_binding () {return discriminator_image_binding_;}
+
+ my_bool*
+ discriminator_image_truncated () {return discriminator_image_truncated_;}
+
+ // Id binding for discriminator retrieval.
+ //
+ id_image_type&
+ discriminator_id_image () {return discriminator_id_image_;}
+
+ std::size_t
+ discriminator_id_image_version () const
+ {return discriminator_id_image_version_;}
+
+ void
+ discriminator_id_image_version (std::size_t v)
+ {discriminator_id_image_version_ = v;}
+
+ binding&
+ discriminator_id_image_binding ()
+ {return discriminator_id_image_binding_;}
+
+ //
+ //
+ select_statement_type&
+ find_discriminator_statement ()
+ {
+ if (find_discriminator_ == 0)
+ find_discriminator_.reset (
+ new (details::shared) select_statement_type (
+ this->conn_,
+ object_traits::find_discriminator_statement,
+ discriminator_id_image_binding_,
+ discriminator_image_binding_,
+ false));
+
+ return *find_discriminator_;
+ }
+
+ public:
+ polymorphic_root_object_statements (connection_type&);
+
+ virtual
+ ~polymorphic_root_object_statements ();
+
+ public:
+ static const std::size_t id_column_count =
+ object_statements<T>::id_column_count;
+
+ static const std::size_t discriminator_column_count =
+ object_traits::discriminator_column_count;
+
+ static const std::size_t managed_optimistic_column_count =
+ object_traits::managed_optimistic_column_count;
+
+ private:
+ // Discriminator image.
+ //
+ discriminator_image_type discriminator_image_;
+ std::size_t discriminator_image_version_;
+ binding discriminator_image_binding_;
+ MYSQL_BIND discriminator_image_bind_[discriminator_column_count +
+ managed_optimistic_column_count];
+ my_bool discriminator_image_truncated_[discriminator_column_count +
+ managed_optimistic_column_count];
+
+ // Id image for discriminator retrieval (only used as a parameter).
+ //
+ id_image_type discriminator_id_image_;
+ std::size_t discriminator_id_image_version_;
+ binding discriminator_id_image_binding_;
+ MYSQL_BIND discriminator_id_image_bind_[id_column_count];
+
+ details::shared_ptr<select_statement_type> find_discriminator_;
+ };
+
+ template <typename T>
+ class polymorphic_derived_object_statements: public statements_base
+ {
+ public:
+ 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 typename object_traits::id_image_type id_image_type;
+ typedef typename object_traits::image_type image_type;
+
+ typedef typename object_traits::root_type root_type;
+ typedef
+ polymorphic_root_object_statements<root_type>
+ root_statements_type;
+
+ typedef typename object_traits::base_type base_type;
+ typedef
+ typename object_traits::base_traits::statements_type
+ base_statements_type;
+
+ typedef
+ typename object_traits::container_statement_cache_type
+ container_statement_cache_type;
+
+ typedef mysql::insert_statement insert_statement_type;
+ typedef mysql::select_statement select_statement_type;
+ typedef mysql::update_statement update_statement_type;
+ typedef mysql::delete_statement delete_statement_type;
+
+ typedef typename root_statements_type::auto_lock auto_lock;
+
+ public:
+ polymorphic_derived_object_statements (connection_type&);
+
+ virtual
+ ~polymorphic_derived_object_statements ();
+
+ public:
+ // Delayed loading.
+ //
+ static void
+ delayed_loader (odb::database&, const id_type&, root_type&);
+
+ public:
+ // Root and immediate base statements.
+ //
+ root_statements_type&
+ root_statements ()
+ {
+ return root_statements_;
+ }
+
+ base_statements_type&
+ base_statements ()
+ {
+ return base_statements_;
+ }
+
+ public:
+ // Object image.
+ //
+ image_type&
+ image ()
+ {
+ return image_;
+ }
+
+ // Insert binding.
+ //
+ std::size_t
+ insert_image_version () const { return insert_image_version_;}
+
+ void
+ insert_image_version (std::size_t v) {insert_image_version_ = v;}
+
+ std::size_t
+ insert_id_binding_version () const { return insert_id_binding_version_;}
+
+ void
+ insert_id_binding_version (std::size_t v) {insert_id_binding_version_ = v;}
+
+ binding&
+ insert_image_binding () {return insert_image_binding_;}
+
+ // Update binding.
+ //
+ std::size_t
+ update_image_version () const { return update_image_version_;}
+
+ void
+ update_image_version (std::size_t v) {update_image_version_ = v;}
+
+ std::size_t
+ update_id_binding_version () const { return update_id_binding_version_;}
+
+ void
+ update_id_binding_version (std::size_t v) {update_id_binding_version_ = v;}
+
+ binding&
+ update_image_binding () {return update_image_binding_;}
+
+ // Select binding.
+ //
+ std::size_t*
+ select_image_versions () { return select_image_versions_;}
+
+ binding*
+ select_image_bindings () {return select_image_bindings_;}
+
+ binding&
+ select_image_binding (std::size_t d)
+ {
+ return select_image_bindings_[object_traits::depth - d];
+ }
+
+ my_bool*
+ select_image_truncated () {return select_image_truncated_;}
+
+ // Object id binding (comes from the root statements).
+ //
+ id_image_type&
+ id_image () {return root_statements_.id_image ();}
+
+ std::size_t
+ id_image_version () const {return root_statements_.id_image_version ();}
+
+ void
+ id_image_version (std::size_t v) {root_statements_.id_image_version (v);}
+
+ binding&
+ id_image_binding () {return root_statements_.id_image_binding ();}
+
+ // Statements.
+ //
+ insert_statement_type&
+ persist_statement ()
+ {
+ if (persist_ == 0)
+ persist_.reset (
+ new (details::shared) insert_statement_type (
+ conn_,
+ object_traits::persist_statement,
+ insert_image_binding_,
+ false));
+
+ return *persist_;
+ }
+
+ select_statement_type&
+ find_statement (std::size_t d)
+ {
+ std::size_t i (object_traits::depth - d);
+ details::shared_ptr<select_statement_type>& p (find_[i]);
+
+ if (p == 0)
+ p.reset (
+ new (details::shared) select_statement_type (
+ conn_,
+ object_traits::find_statements[i],
+ root_statements_.id_image_binding (),
+ select_image_bindings_[i],
+ false));
+
+ return *p;
+ }
+
+ update_statement_type&
+ update_statement ()
+ {
+ if (update_ == 0)
+ update_.reset (
+ new (details::shared) update_statement_type (
+ conn_,
+ object_traits::update_statement,
+ update_image_binding_,
+ false));
+
+ return *update_;
+ }
+
+ delete_statement_type&
+ erase_statement ()
+ {
+ if (erase_ == 0)
+ erase_.reset (
+ new (details::shared) delete_statement_type (
+ conn_,
+ object_traits::erase_statement,
+ root_statements_.id_image_binding (),
+ false));
+
+ return *erase_;
+ }
+
+ // Container statement cache.
+ //
+ container_statement_cache_type&
+ container_statment_cache ()
+ {
+ return container_statement_cache_;
+ }
+
+ public:
+ // select = total - id + base::select
+ // insert = total - inverse
+ // update = total - inverse - id - readonly
+ //
+ static const std::size_t id_column_count =
+ object_traits::id_column_count;
+
+ static const std::size_t select_column_count =
+ object_traits::column_count - id_column_count +
+ base_statements_type::select_column_count;
+
+ static const std::size_t insert_column_count =
+ object_traits::column_count - object_traits::inverse_column_count;
+
+ static const std::size_t update_column_count = insert_column_count -
+ object_traits::id_column_count - object_traits::readonly_column_count;
+
+ private:
+ polymorphic_derived_object_statements (
+ const polymorphic_derived_object_statements&);
+
+ polymorphic_derived_object_statements&
+ operator= (const polymorphic_derived_object_statements&);
+
+ private:
+ root_statements_type& root_statements_;
+ base_statements_type& base_statements_;
+
+ container_statement_cache_type container_statement_cache_;
+
+ image_type image_;
+
+ // Select binding. Here we are have an array of statements/bindings
+ // one for each depth. In other words, if we have classes root, base,
+ // and derived, then we have the following array of statements:
+ //
+ // [0] d + b + r
+ // [1] d + b
+ // [2] d
+ //
+ // Also, because we have a chain of images bound to these statements,
+ // we have an array of versions, one entry for each base plus one for
+ // our own image.
+ //
+ // A poly-abstract class only needs the first statement and in this
+ // case we have only one entry in the the bindings and statements
+ // arrays (but not versions; we still have a chain of images).
+ //
+ std::size_t select_image_versions_[object_traits::depth];
+ binding select_image_bindings_[
+ object_traits::abstract ? 1 : object_traits::depth];
+ MYSQL_BIND select_image_bind_[select_column_count];
+ my_bool select_image_truncated_[select_column_count];
+
+ // Insert binding. The id binding is copied from the hierarchy root.
+ //
+ std::size_t insert_image_version_;
+ std::size_t insert_id_binding_version_;
+ binding insert_image_binding_;
+ MYSQL_BIND insert_image_bind_[insert_column_count];
+
+ // Update binding. The id suffix binding is copied from the hierarchy
+ // root.
+ //
+ std::size_t update_image_version_;
+ std::size_t update_id_binding_version_;
+ binding update_image_binding_;
+ MYSQL_BIND update_image_bind_[update_column_count + id_column_count];
+
+ details::shared_ptr<insert_statement_type> persist_;
+ details::shared_ptr<select_statement_type> find_[
+ object_traits::abstract ? 1 : object_traits::depth];
+ details::shared_ptr<update_statement_type> update_;
+ details::shared_ptr<delete_statement_type> erase_;
+ };
+ }
+}
+
+#include <odb/mysql/polymorphic-object-statements.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_MYSQL_POLYMORPHIC_OBJECT_STATEMENTS_HXX
diff --git a/odb/mysql/polymorphic-object-statements.txx b/odb/mysql/polymorphic-object-statements.txx
new file mode 100644
index 0000000..19e5d52
--- /dev/null
+++ b/odb/mysql/polymorphic-object-statements.txx
@@ -0,0 +1,141 @@
+// file : odb/mysql/polymorphic-object-statements.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cstring> // std::memset
+
+#include <odb/callback.hxx>
+#include <odb/exceptions.hxx>
+
+#include <odb/mysql/connection.hxx>
+#include <odb/mysql/transaction.hxx>
+#include <odb/mysql/statement-cache.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ //
+ // polymorphic_root_object_statements
+ //
+
+ template <typename T>
+ polymorphic_root_object_statements<T>::
+ ~polymorphic_root_object_statements ()
+ {
+ }
+
+ template <typename T>
+ polymorphic_root_object_statements<T>::
+ polymorphic_root_object_statements (connection_type& conn)
+ : object_statements<T> (conn),
+ discriminator_image_binding_ (discriminator_image_bind_,
+ discriminator_column_count +
+ managed_optimistic_column_count),
+ discriminator_id_image_binding_ (discriminator_id_image_bind_,
+ id_column_count)
+ {
+ discriminator_image_.version = 0;
+ discriminator_id_image_.version = 0;
+
+ discriminator_image_version_ = 0;
+ discriminator_id_image_version_ = 0;
+
+ std::memset (discriminator_image_bind_,
+ 0,
+ sizeof (discriminator_image_bind_));
+ std::memset (discriminator_id_image_bind_,
+ 0,
+ sizeof (discriminator_id_image_bind_));
+ std::memset (discriminator_image_truncated_,
+ 0,
+ sizeof (discriminator_image_truncated_));
+
+ for (std::size_t i (0);
+ i < discriminator_column_count + managed_optimistic_column_count;
+ ++i)
+ {
+ discriminator_image_bind_[i].error =
+ discriminator_image_truncated_ + i;
+ }
+ }
+
+ //
+ // polymorphic_derived_object_statements
+ //
+
+ template <typename T>
+ polymorphic_derived_object_statements<T>::
+ ~polymorphic_derived_object_statements ()
+ {
+ }
+
+ template <typename T>
+ polymorphic_derived_object_statements<T>::
+ polymorphic_derived_object_statements (connection_type& conn)
+ : statements_base (conn),
+ root_statements_ (conn.statement_cache ().find_object<root_type> ()),
+ base_statements_ (conn.statement_cache ().find_object<base_type> ()),
+ container_statement_cache_ (conn),
+ insert_image_binding_ (insert_image_bind_, insert_column_count),
+ update_image_binding_ (update_image_bind_,
+ update_column_count + id_column_count)
+ {
+ image_.base = &base_statements_.image ();
+ image_.version = 0;
+
+ for (std::size_t i (0); i < object_traits::depth; ++i)
+ select_image_versions_[i] = 0;
+
+ for (std::size_t i (0);
+ i < (object_traits::abstract ? 1 : object_traits::depth);
+ ++i)
+ {
+ select_image_bindings_[i].bind = select_image_bind_;
+ select_image_bindings_[i].count = object_traits::find_column_counts[i];
+ }
+
+ insert_image_version_ = 0;
+ insert_id_binding_version_ = 0;
+ update_image_version_ = 0;
+ update_id_binding_version_ = 0;
+
+ std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
+ std::memset (update_image_bind_, 0, sizeof (update_image_bind_));
+ std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
+ std::memset (
+ select_image_truncated_, 0, sizeof (select_image_truncated_));
+
+ for (std::size_t i (0); i < select_column_count; ++i)
+ select_image_bind_[i].error = select_image_truncated_ + i;
+ }
+
+ template <typename T>
+ void polymorphic_derived_object_statements<T>::
+ delayed_loader (odb::database& db, const id_type& id, root_type& robj)
+ {
+ connection_type& conn (transaction::current ().connection ());
+ polymorphic_derived_object_statements& sts (
+ conn.statement_cache ().find_object<object_type> ());
+ root_statements_type& rsts (sts.root_statements ());
+
+ object_type& obj (static_cast<object_type&> (robj));
+
+ // The same code as in object_statements::load_delayed_().
+ //
+ if (!object_traits::find_ (sts, &id))
+ throw object_not_persistent ();
+
+ object_traits::callback (db, obj, callback_event::pre_load);
+ object_traits::init (obj, sts.image (), &db);
+ object_traits::load_ (sts, obj); // Load containers, etc.
+
+ rsts.load_delayed ();
+
+ {
+ typename root_statements_type::auto_unlock u (rsts);
+ object_traits::callback (db, obj, callback_event::post_load);
+ }
+ }
+ }
+}
diff --git a/odb/mysql/result.hxx b/odb/mysql/result.hxx
deleted file mode 100644
index 7545e76..0000000
--- a/odb/mysql/result.hxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// file : odb/mysql/result.hxx
-// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
-// license : GNU GPL v2; see accompanying LICENSE file
-
-#ifndef ODB_MYSQL_RESULT_HXX
-#define ODB_MYSQL_RESULT_HXX
-
-#include <odb/pre.hxx>
-
-#include <odb/traits.hxx>
-#include <odb/result.hxx>
-
-#include <odb/mysql/version.hxx>
-#include <odb/mysql/forward.hxx>
-
-#include <odb/post.hxx>
-
-#endif // ODB_MYSQL_RESULT_HXX
-
-// Include result specializations so that the user code only needs
-// to include this header.
-//
-
-#include <odb/mysql/object-result.hxx>
-#include <odb/mysql/view-result.hxx>
diff --git a/odb/mysql/simple-object-result.hxx b/odb/mysql/simple-object-result.hxx
new file mode 100644
index 0000000..b92c5ce
--- /dev/null
+++ b/odb/mysql/simple-object-result.hxx
@@ -0,0 +1,79 @@
+// file : odb/mysql/simple-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_MYSQL_SIMPLE_OBJECT_RESULT_HXX
+#define ODB_MYSQL_SIMPLE_OBJECT_RESULT_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/simple-object-result.hxx>
+
+#include <odb/details/shared-ptr.hxx>
+
+#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx> // query
+#include <odb/mysql/statement.hxx>
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ class object_result_impl: public odb::object_result_impl<T>
+ {
+ public:
+ typedef odb::object_result_impl<T> base_type;
+
+ typedef typename base_type::object_type object_type;
+ typedef typename base_type::object_traits object_traits;
+ typedef typename base_type::id_type id_type;
+
+ typedef typename base_type::pointer_type pointer_type;
+ typedef typename base_type::pointer_traits pointer_traits;
+
+ typedef typename object_traits::statements_type statements_type;
+
+ virtual
+ ~object_result_impl ();
+
+ object_result_impl (const query&,
+ details::shared_ptr<select_statement>,
+ statements_type&);
+
+ virtual void
+ load (object_type&, bool fetch);
+
+ virtual id_type
+ load_id ();
+
+ virtual void
+ next ();
+
+ virtual void
+ cache ();
+
+ virtual std::size_t
+ size ();
+
+ using base_type::current;
+
+ private:
+ void
+ fetch (bool next = true);
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ std::size_t count_;
+ };
+ }
+}
+
+#include <odb/mysql/simple-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_MYSQL_SIMPLE_OBJECT_RESULT_HXX
diff --git a/odb/mysql/object-result.txx b/odb/mysql/simple-object-result.txx
index 8144578..f77f83e 100644
--- a/odb/mysql/object-result.txx
+++ b/odb/mysql/simple-object-result.txx
@@ -1,22 +1,18 @@
-// file : odb/mysql/object-result.txx
+// file : odb/mysql/simple-object-result.txx
// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
#include <cassert>
#include <odb/callback.hxx>
-#include <odb/exceptions.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
-#include <odb/mysql/object-statements.hxx>
+#include <odb/mysql/simple-object-statements.hxx>
namespace odb
{
namespace mysql
{
- //
- // object_result_impl
- //
-
template <typename T>
object_result_impl<T>::
~object_result_impl ()
@@ -29,7 +25,7 @@ namespace odb
object_result_impl<T>::
object_result_impl (const query&,
details::shared_ptr<select_statement> statement,
- object_statements<object_type>& statements)
+ statements_type& statements)
: base_type (statements.connection ().database ()),
statement_ (statement),
statements_ (statements),
@@ -54,7 +50,7 @@ namespace odb
// This is a top-level call so the statements cannot be locked.
//
assert (!statements_.locked ());
- typename object_statements<object_type>::auto_lock l (statements_);
+ typename statements_type::auto_lock l (statements_);
odb::database& db (this->database ());
object_traits::callback (db, obj, callback_event::pre_load);
@@ -214,153 +210,5 @@ namespace odb
return statement_->result_size ();
}
-
- //
- // object_result_impl_no_id
- //
-
- template <typename T>
- object_result_impl_no_id<T>::
- ~object_result_impl_no_id ()
- {
- if (!this->end_)
- statement_->free_result ();
- }
-
- template <typename T>
- object_result_impl_no_id<T>::
- object_result_impl_no_id (const query&,
- details::shared_ptr<select_statement> statement,
- object_statements_no_id<object_type>& statements)
- : base_type (statements.connection ().database ()),
- statement_ (statement),
- statements_ (statements),
- count_ (0)
- {
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- load (object_type& obj)
- {
- if (count_ > statement_->fetched ())
- fetch ();
-
- odb::database& db (this->database ());
-
- object_traits::callback (db, obj, callback_event::pre_load);
- object_traits::init (obj, statements_.image (), &db);
- object_traits::callback (db, obj, callback_event::post_load);
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- next ()
- {
- this->current (pointer_type ());
-
- // If we are cached, simply increment the position and
- // postpone the actual row fetching until later. This way
- // if the same object is loaded in between iteration, the
- // image won't be messed up.
- //
- count_++;
-
- if (statement_->cached ())
- this->end_ = count_ > statement_->result_size ();
- else
- fetch ();
-
- if (this->end_)
- statement_->free_result ();
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- fetch ()
- {
- // If the result is cached, the image can grow between calls
- // to fetch() as a result of other statements execution.
- //
- if (statement_->cached ())
- {
- typename object_traits::image_type& im (statements_.image ());
-
- if (im.version != statements_.select_image_version ())
- {
- binding& b (statements_.select_image_binding ());
- object_traits::bind (b.bind, im, statement_select);
- statements_.select_image_version (im.version);
- b.version++;
- }
- }
-
- while (!this->end_ && count_ > statement_->fetched ())
- {
- select_statement::result r (statement_->fetch ());
-
- switch (r)
- {
- case select_statement::truncated:
- {
- // Don't re-fetch data we are skipping.
- //
- if (count_ != statement_->fetched ())
- continue;
-
- typename object_traits::image_type& im (statements_.image ());
-
- if (object_traits::grow (
- im, statements_.select_image_truncated ()))
- im.version++;
-
- if (im.version != statements_.select_image_version ())
- {
- binding& b (statements_.select_image_binding ());
- object_traits::bind (b.bind, im, statement_select);
- statements_.select_image_version (im.version);
- b.version++;
- statement_->refetch ();
- }
- // Fall throught.
- }
- case select_statement::success:
- {
- break;
- }
- case select_statement::no_data:
- {
- this->end_ = true;
- break;
- }
- }
- }
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- cache ()
- {
- if (!statement_->cached ())
- {
- statement_->cache ();
-
- if (count_ >= statement_->result_size ())
- {
- statement_->free_result ();
- this->end_ = true;
- }
- }
- }
-
- template <typename T>
- std::size_t object_result_impl_no_id<T>::
- size ()
- {
- if (!statement_->cached ())
- throw result_not_cached ();
-
- return statement_->result_size ();
- }
}
}
diff --git a/odb/mysql/object-statements.cxx b/odb/mysql/simple-object-statements.cxx
index 9ad9e99..8452b55 100644
--- a/odb/mysql/object-statements.cxx
+++ b/odb/mysql/simple-object-statements.cxx
@@ -1,8 +1,8 @@
-// file : odb/mysql/object-statements.cxx
+// file : odb/mysql/simple-object-statements.cxx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
-#include <odb/mysql/object-statements.hxx>
+#include <odb/mysql/simple-object-statements.hxx>
namespace odb
{
diff --git a/odb/mysql/object-statements.hxx b/odb/mysql/simple-object-statements.hxx
index 974700f..9a3e80e 100644
--- a/odb/mysql/object-statements.hxx
+++ b/odb/mysql/simple-object-statements.hxx
@@ -1,9 +1,9 @@
-// file : odb/mysql/object-statements.hxx
+// file : odb/mysql/simple-object-statements.hxx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
-#ifndef ODB_MYSQL_OBJECT_STATEMENTS_HXX
-#define ODB_MYSQL_OBJECT_STATEMENTS_HXX
+#ifndef ODB_MYSQL_SIMPLE_OBJECT_STATEMENTS_HXX
+#define ODB_MYSQL_SIMPLE_OBJECT_STATEMENTS_HXX
#include <odb/pre.hxx>
@@ -17,8 +17,10 @@
#include <odb/details/shared-ptr.hxx>
-#include <odb/mysql/mysql.hxx>
#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx>
+#include <odb/mysql/mysql.hxx>
+#include <odb/mysql/binding.hxx>
#include <odb/mysql/statement.hxx>
#include <odb/mysql/statements-base.hxx>
@@ -28,24 +30,6 @@ namespace odb
{
namespace mysql
{
- template <typename T>
- class object_statements;
-
- template <typename T>
- class object_statements_no_id;
-
- template <typename T, typename ID = typename object_traits<T>::id_type>
- struct object_statements_selector
- {
- typedef object_statements<T> type;
- };
-
- template <typename T>
- struct object_statements_selector<T, void>
- {
- typedef object_statements_no_id<T> type;
- };
-
//
// Implementation for objects with object id.
//
@@ -75,16 +59,6 @@ namespace odb
return locked_;
}
- public:
- virtual
- ~object_statements_base ();
-
- protected:
- object_statements_base (connection_type& conn)
- : statements_base (conn), locked_ (false)
- {
- }
-
struct auto_unlock
{
// Unlocks the statement on construction and re-locks it on
@@ -101,6 +75,16 @@ namespace odb
object_statements_base& s_;
};
+ public:
+ virtual
+ ~object_statements_base ();
+
+ protected:
+ object_statements_base (connection_type& conn)
+ : statements_base (conn), locked_ (false)
+ {
+ }
+
protected:
bool locked_;
};
@@ -141,7 +125,9 @@ namespace odb
typedef typename object_traits::image_type image_type;
typedef typename object_traits::id_image_type id_image_type;
- typedef pointer_cache_traits<pointer_type> object_cache_traits;
+ typedef
+ typename object_traits::pointer_cache_traits
+ pointer_cache_traits;
typedef
typename object_traits::container_statement_cache_type
@@ -195,12 +181,16 @@ namespace odb
// Delayed loading.
//
+ typedef void (*loader_function) (
+ odb::database&, const id_type&, object_type&);
+
void
delay_load (const id_type& id,
object_type& obj,
- const typename object_cache_traits::position_type& p)
+ const typename pointer_cache_traits::position_type& p,
+ loader_function l = 0)
{
- delayed_.push_back (delayed_load (id, obj, p));
+ delayed_.push_back (delayed_load (id, obj, p, l));
}
void
@@ -374,18 +364,7 @@ namespace odb
return container_statement_cache_;
}
- private:
- object_statements (const object_statements&);
- object_statements& operator= (const object_statements&);
-
- private:
- void
- load_delayed_ ();
-
- void
- clear_delayed_ ();
-
- private:
+ public:
// select = total
// insert = total - inverse - managed_optimistic
// update = total - inverse - managed_optimistic - id - readonly
@@ -407,6 +386,17 @@ namespace odb
object_traits::managed_optimistic_column_count;
private:
+ object_statements (const object_statements&);
+ object_statements& operator= (const object_statements&);
+
+ private:
+ void
+ load_delayed_ ();
+
+ void
+ clear_delayed_ ();
+
+ private:
container_statement_cache_type container_statement_cache_;
image_type image_;
@@ -458,17 +448,21 @@ namespace odb
//
struct delayed_load
{
- typedef typename object_cache_traits::position_type position_type;
+ typedef typename pointer_cache_traits::position_type position_type;
delayed_load () {}
- delayed_load (const id_type& i, object_type& o, const position_type& p)
- : id (i), obj (&o), pos (p)
+ delayed_load (const id_type& i,
+ object_type& o,
+ const position_type& p,
+ loader_function l)
+ : id (i), obj (&o), pos (p), loader (l)
{
}
id_type id;
object_type* obj;
position_type pos;
+ loader_function loader;
};
typedef std::vector<delayed_load> delayed_loads;
@@ -496,113 +490,12 @@ namespace odb
delayed_loads& dl_;
};
};
-
- //
- // Implementation for objects without object id.
- //
-
- template <typename T>
- class object_statements_no_id: public statements_base
- {
- public:
- typedef T object_type;
- typedef odb::object_traits<object_type> object_traits;
- typedef typename object_traits::pointer_type pointer_type;
- typedef typename object_traits::image_type image_type;
-
- typedef mysql::insert_statement insert_statement_type;
-
- public:
- object_statements_no_id (connection_type&);
-
- virtual
- ~object_statements_no_id ();
-
- // Object image.
- //
- image_type&
- image () {return image_;}
-
- // Insert binding.
- //
- std::size_t
- insert_image_version () const { return insert_image_version_;}
-
- void
- insert_image_version (std::size_t v) {insert_image_version_ = v;}
-
- binding&
- insert_image_binding () {return insert_image_binding_;}
-
- // Select binding (needed for query support).
- //
- std::size_t
- select_image_version () const { return select_image_version_;}
-
- void
- select_image_version (std::size_t v) {select_image_version_ = v;}
-
- binding&
- select_image_binding () {return select_image_binding_;}
-
- my_bool*
- select_image_truncated () {return select_image_truncated_;}
-
- // Statements.
- //
- insert_statement_type&
- persist_statement ()
- {
- if (persist_ == 0)
- persist_.reset (
- new (details::shared) insert_statement_type (
- conn_,
- object_traits::persist_statement,
- insert_image_binding_,
- false));
-
- return *persist_;
- }
-
- private:
- object_statements_no_id (const object_statements_no_id&);
- object_statements_no_id& operator= (const object_statements_no_id&);
-
- private:
- // select = total
- // insert = total - inverse; inverse == 0 for object without id
- //
-
- static const std::size_t select_column_count =
- object_traits::column_count;
-
- static const std::size_t insert_column_count =
- object_traits::column_count;
-
- private:
- image_type image_;
-
- // Select binding.
- //
- std::size_t select_image_version_;
- binding select_image_binding_;
- MYSQL_BIND select_image_bind_[select_column_count];
- my_bool select_image_truncated_[select_column_count];
-
- // Insert binding.
- //
- std::size_t insert_image_version_;
- binding insert_image_binding_;
- MYSQL_BIND insert_image_bind_[insert_column_count];
-
- details::shared_ptr<insert_statement_type> persist_;
- };
}
}
-#include <odb/mysql/object-statements.ixx>
-#include <odb/mysql/object-statements.txx>
+#include <odb/mysql/simple-object-statements.ixx>
+#include <odb/mysql/simple-object-statements.txx>
#include <odb/post.hxx>
-#endif // ODB_MYSQL_OBJECT_STATEMENTS_HXX
+#endif // ODB_MYSQL_SIMPLE_OBJECT_STATEMENTS_HXX
diff --git a/odb/mysql/object-statements.ixx b/odb/mysql/simple-object-statements.ixx
index 3b483dd..8cbc97b 100644
--- a/odb/mysql/object-statements.ixx
+++ b/odb/mysql/simple-object-statements.ixx
@@ -1,4 +1,4 @@
-// file : odb/mysql/object-statements.ixx
+// file : odb/mysql/simple-object-statements.ixx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
diff --git a/odb/mysql/object-statements.txx b/odb/mysql/simple-object-statements.txx
index 2ad4bc9..81f3bce 100644
--- a/odb/mysql/object-statements.txx
+++ b/odb/mysql/simple-object-statements.txx
@@ -1,8 +1,7 @@
-// file : odb/mysql/object-statements.txx
+// file : odb/mysql/simple-object-statements.txx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : GNU GPL v2; see accompanying LICENSE file
-#include <cstddef> // std::size_t
#include <cstring> // std::memset
#include <odb/session.hxx>
@@ -85,36 +84,41 @@ namespace odb
while (!dls.empty ())
{
delayed_load l (dls.back ());
- typename object_cache_traits::insert_guard g (l.pos);
+ typename pointer_cache_traits::insert_guard g (l.pos);
dls.pop_back ();
- if (!object_traits::find_ (*this, l.id))
- throw object_not_persistent ();
-
- object_traits::callback (db, *l.obj, callback_event::pre_load);
-
- // Our calls to init/load below can result in additional delayed
- // loads being added to the delayed_ vector. We need to process
- // those before we call the post callback.
- //
- object_traits::init (*l.obj, image (), &db);
- object_traits::load_ (*this, *l.obj); // Load containers, etc.
-
- if (!delayed_.empty ())
- load_delayed_ ();
-
- // Temporarily unlock the statement for the post_load call so that
- // it can load objects of this type recursively. This is safe to do
- // because we have completely loaded the current object. Also the
- // delayed_ list is clear before the unlock and should be clear on
- // re-lock (since a callback can only call public API functions
- // which will make sure all the delayed loads are processed before
- // returning).
- //
+ if (l.loader == 0)
{
- auto_unlock u (*this);
- object_traits::callback (db, *l.obj, callback_event::post_load);
+ if (!object_traits::find_ (*this, &l.id))
+ throw object_not_persistent ();
+
+ object_traits::callback (db, *l.obj, callback_event::pre_load);
+
+ // Our calls to init/load below can result in additional delayed
+ // loads being added to the delayed_ vector. We need to process
+ // those before we call the post callback.
+ //
+ object_traits::init (*l.obj, image (), &db);
+ object_traits::load_ (*this, *l.obj); // Load containers, etc.
+
+ if (!delayed_.empty ())
+ load_delayed_ ();
+
+ // Temporarily unlock the statement for the post_load call so that
+ // it can load objects of this type recursively. This is safe to do
+ // because we have completely loaded the current object. Also the
+ // delayed_ list is clear before the unlock and should be clear on
+ // re-lock (since a callback can only call public API functions
+ // which will make sure all the delayed loads are processed before
+ // returning).
+ //
+ {
+ auto_unlock u (*this);
+ object_traits::callback (db, *l.obj, callback_event::post_load);
+ }
}
+ else
+ l.loader (db, l.id, *l.obj);
g.release ();
}
@@ -131,41 +135,11 @@ namespace odb
for (typename delayed_loads::iterator i (delayed_.begin ()),
e (delayed_.end ()); i != e; ++i)
{
- object_cache_traits::erase (i->pos);
+ pointer_cache_traits::erase (i->pos);
}
}
delayed_.clear ();
}
-
- //
- // object_statements
- //
-
- template <typename T>
- object_statements_no_id<T>::
- ~object_statements_no_id ()
- {
- }
-
- template <typename T>
- object_statements_no_id<T>::
- object_statements_no_id (connection_type& conn)
- : statements_base (conn),
- select_image_binding_ (select_image_bind_, select_column_count),
- insert_image_binding_ (insert_image_bind_, insert_column_count)
- {
- image_.version = 0;
- select_image_version_ = 0;
- insert_image_version_ = 0;
-
- std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
- std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
- std::memset (
- select_image_truncated_, 0, sizeof (select_image_truncated_));
-
- for (std::size_t i (0); i < select_column_count; ++i)
- select_image_bind_[i].error = select_image_truncated_ + i;
- }
}
}
diff --git a/odb/mysql/statement-cache.hxx b/odb/mysql/statement-cache.hxx
index e62c76c..f801972 100644
--- a/odb/mysql/statement-cache.hxx
+++ b/odb/mysql/statement-cache.hxx
@@ -11,11 +11,11 @@
#include <typeinfo>
#include <odb/forward.hxx>
+#include <odb/traits.hxx>
#include <odb/mysql/version.hxx>
+#include <odb/mysql/forward.hxx>
#include <odb/mysql/statements-base.hxx>
-#include <odb/mysql/object-statements.hxx>
-#include <odb/mysql/view-statements.hxx>
#include <odb/details/shared-ptr.hxx>
#include <odb/details/type-info.hxx>
@@ -26,49 +26,19 @@ namespace odb
{
namespace mysql
{
- class connection;
-
class LIBODB_MYSQL_EXPORT statement_cache
{
public:
- statement_cache (connection& conn)
- : conn_ (conn)
- {
- }
+ statement_cache (connection& conn): conn_ (conn) {}
template <typename T>
- typename object_statements_selector<T>::type&
- find_object ()
- {
- typedef typename object_statements_selector<T>::type object_statements;
-
- map::iterator i (map_.find (&typeid (T)));
-
- if (i != map_.end ())
- return static_cast<object_statements&> (*i->second);
-
- details::shared_ptr<object_statements> p (
- new (details::shared) object_statements (conn_));
+ typename object_traits<T>::statements_type&
+ find_object ();
- map_.insert (map::value_type (&typeid (T), p));
- return *p;
- }
template <typename T>
view_statements<T>&
- find_view ()
- {
- map::iterator i (map_.find (&typeid (T)));
-
- if (i != map_.end ())
- return static_cast<view_statements<T>&> (*i->second);
-
- details::shared_ptr<view_statements<T> > p (
- new (details::shared) view_statements<T> (conn_));
-
- map_.insert (map::value_type (&typeid (T), p));
- return *p;
- }
+ find_view ();
private:
typedef std::map<const std::type_info*,
@@ -81,6 +51,8 @@ namespace odb
}
}
+#include <odb/mysql/statement-cache.txx>
+
#include <odb/post.hxx>
#endif // ODB_MYSQL_STATEMENT_CACHE_HXX
diff --git a/odb/mysql/statement-cache.txx b/odb/mysql/statement-cache.txx
new file mode 100644
index 0000000..3acc5fe
--- /dev/null
+++ b/odb/mysql/statement-cache.txx
@@ -0,0 +1,43 @@
+// file : odb/mysql/statement-cache.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace mysql
+ {
+ template <typename T>
+ typename object_traits<T>::statements_type& statement_cache::
+ find_object ()
+ {
+ typedef typename object_traits<T>::statements_type statements_type;
+
+ map::iterator i (map_.find (&typeid (T)));
+
+ if (i != map_.end ())
+ return static_cast<statements_type&> (*i->second);
+
+ details::shared_ptr<statements_type> p (
+ new (details::shared) statements_type (conn_));
+
+ map_.insert (map::value_type (&typeid (T), p));
+ return *p;
+ }
+
+ template <typename T>
+ view_statements<T>& statement_cache::
+ find_view ()
+ {
+ map::iterator i (map_.find (&typeid (T)));
+
+ if (i != map_.end ())
+ return static_cast<view_statements<T>&> (*i->second);
+
+ details::shared_ptr<view_statements<T> > p (
+ new (details::shared) view_statements<T> (conn_));
+
+ map_.insert (map::value_type (&typeid (T), p));
+ return *p;
+ }
+ }
+}
diff --git a/odb/mysql/statement.cxx b/odb/mysql/statement.cxx
index 6882a27..647ec96 100644
--- a/odb/mysql/statement.cxx
+++ b/odb/mysql/statement.cxx
@@ -259,7 +259,8 @@ namespace odb
{
case 0:
{
- rows_++;
+ if (next)
+ rows_++;
return success;
}
case MYSQL_NO_DATA:
@@ -269,7 +270,8 @@ namespace odb
}
case MYSQL_DATA_TRUNCATED:
{
- rows_++;
+ if (next)
+ rows_++;
return truncated;
}
default:
diff --git a/odb/mysql/view-result.hxx b/odb/mysql/view-result.hxx
index f63e70b..ab59f03 100644
--- a/odb/mysql/view-result.hxx
+++ b/odb/mysql/view-result.hxx
@@ -9,11 +9,12 @@
#include <cstddef> // std::size_t
+#include <odb/view-result.hxx>
+
#include <odb/details/shared-ptr.hxx>
#include <odb/mysql/version.hxx>
#include <odb/mysql/forward.hxx> // query, view_statements
-#include <odb/mysql/result.hxx>
#include <odb/mysql/statement.hxx>
namespace odb
@@ -32,12 +33,14 @@ namespace odb
typedef typename base_type::pointer_type pointer_type;
typedef typename base_type::pointer_traits pointer_traits;
+ typedef view_statements<view_type> statements_type;
+
virtual
~view_result_impl ();
view_result_impl (const query&,
details::shared_ptr<select_statement>,
- view_statements<view_type>&);
+ statements_type&);
virtual void
load (view_type&);
@@ -59,7 +62,7 @@ namespace odb
private:
details::shared_ptr<select_statement> statement_;
- view_statements<view_type>& statements_;
+ statements_type& statements_;
std::size_t count_;
};
}
diff --git a/odb/mysql/view-result.txx b/odb/mysql/view-result.txx
index 6f1896d..f6060ea 100644
--- a/odb/mysql/view-result.txx
+++ b/odb/mysql/view-result.txx
@@ -23,7 +23,7 @@ namespace odb
view_result_impl<T>::
view_result_impl (const query&,
details::shared_ptr<select_statement> statement,
- view_statements<view_type>& statements)
+ statements_type& statements)
: base_type (statements.connection ().database ()),
statement_ (statement),
statements_ (statements),