aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2012-04-23 16:48:02 +0200
commitf039726a9d756dff85607d89bf4ba5fd1ef42edf (patch)
treea422c8d57733d29d2ecab92b39a0b3bef8d6fc1d
parentd2fc34834f0b7660374f78d4409e24a165950c2c (diff)
Polymorphic inheritance support
-rw-r--r--odb/oracle/binding.hxx2
-rw-r--r--odb/oracle/forward.hxx8
-rw-r--r--odb/oracle/makefile36
-rw-r--r--odb/oracle/no-id-object-result.hxx78
-rw-r--r--odb/oracle/no-id-object-result.txx144
-rw-r--r--odb/oracle/no-id-object-statements.hxx133
-rw-r--r--odb/oracle/no-id-object-statements.txx34
-rw-r--r--odb/oracle/object-result.hxx125
-rw-r--r--odb/oracle/oracle-types.hxx3
-rw-r--r--odb/oracle/polymorphic-object-result.hxx91
-rw-r--r--odb/oracle/polymorphic-object-result.txx322
-rw-r--r--odb/oracle/polymorphic-object-statements.hxx426
-rw-r--r--odb/oracle/polymorphic-object-statements.txx133
-rw-r--r--odb/oracle/result.hxx25
-rw-r--r--odb/oracle/simple-object-result.hxx82
-rw-r--r--odb/oracle/simple-object-result.txx (renamed from odb/oracle/object-result.txx)162
-rw-r--r--odb/oracle/simple-object-statements.cxx (renamed from odb/oracle/object-statements.cxx)4
-rw-r--r--odb/oracle/simple-object-statements.hxx (renamed from odb/oracle/object-statements.hxx)197
-rw-r--r--odb/oracle/simple-object-statements.ixx (renamed from odb/oracle/object-statements.ixx)4
-rw-r--r--odb/oracle/simple-object-statements.txx (renamed from odb/oracle/object-statements.txx)91
-rw-r--r--odb/oracle/statement-cache.hxx45
-rw-r--r--odb/oracle/statement-cache.txx43
-rw-r--r--odb/oracle/statement.cxx2
-rw-r--r--odb/oracle/view-result.hxx11
-rw-r--r--odb/oracle/view-result.txx11
25 files changed, 1637 insertions, 575 deletions
diff --git a/odb/oracle/binding.hxx b/odb/oracle/binding.hxx
index b4bafd7..8d4e670 100644
--- a/odb/oracle/binding.hxx
+++ b/odb/oracle/binding.hxx
@@ -24,6 +24,8 @@ namespace odb
typedef oracle::bind bind_type;
typedef oracle::change_callback change_callback_type;
+ binding (): bind (0), count (0), version (0), change_callback (0) {}
+
binding (bind_type* b, std::size_t n)
: bind (b), count (n), version (0), change_callback (0)
{
diff --git a/odb/oracle/forward.hxx b/odb/oracle/forward.hxx
index 72550ac..484fbfc 100644
--- a/odb/oracle/forward.hxx
+++ b/odb/oracle/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/oracle/makefile b/odb/oracle/makefile
index a5bb515..0a49b0f 100644
--- a/odb/oracle/makefile
+++ b/odb/oracle/makefile
@@ -4,24 +4,24 @@
include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make
-cxx := \
-auto-descriptor.cxx \
-auto-handle.cxx \
-connection.cxx \
-connection-factory.cxx \
-database.cxx \
-error.cxx \
-exceptions.cxx \
-object-statements.cxx \
-oracle-types.cxx \
-query.cxx \
-query-const-expr.cxx \
-statement.cxx \
-statements-base.cxx \
-tracer.cxx \
-traits.cxx \
-transaction.cxx \
-transaction-impl.cxx \
+cxx := \
+auto-descriptor.cxx \
+auto-handle.cxx \
+connection.cxx \
+connection-factory.cxx \
+database.cxx \
+error.cxx \
+exceptions.cxx \
+oracle-types.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 \
details/number.cxx
cli_tun := details/options.cli
diff --git a/odb/oracle/no-id-object-result.hxx b/odb/oracle/no-id-object-result.hxx
new file mode 100644
index 0000000..bd00b15
--- /dev/null
+++ b/odb/oracle/no-id-object-result.hxx
@@ -0,0 +1,78 @@
+// file : odb/oracle/no-id-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_NO_ID_OBJECT_RESULT_HXX
+#define ODB_ORACLE_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/oracle/version.hxx>
+#include <odb/oracle/forward.hxx> // query
+#include <odb/oracle/statement.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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:
+ typedef oracle::change_callback change_callback_type;
+
+ static void
+ change_callback (void* context, binding*);
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ bool use_copy_;
+ typename object_traits::image_type* image_copy_;
+ };
+ }
+}
+
+#include <odb/oracle/no-id-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_NO_ID_OBJECT_RESULT_HXX
diff --git a/odb/oracle/no-id-object-result.txx b/odb/oracle/no-id-object-result.txx
new file mode 100644
index 0000000..3d1f63b
--- /dev/null
+++ b/odb/oracle/no-id-object-result.txx
@@ -0,0 +1,144 @@
+// file : odb/oracle/no-id-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#include <odb/callback.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+
+#include <odb/oracle/no-id-object-statements.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ template <typename T>
+ no_id_object_result_impl<T>::
+ ~no_id_object_result_impl ()
+ {
+ change_callback_type& cc (statements_.image ().change_callback_);
+
+ if (cc.context == this)
+ {
+ cc.context = 0;
+ cc.callback = 0;
+ }
+
+ delete image_copy_;
+
+ 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),
+ use_copy_ (false),
+ image_copy_ (0)
+ {
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ load (object_type& obj)
+ {
+ odb::database& db (this->database ());
+
+ object_traits::callback (db, obj, callback_event::pre_load);
+
+ object_traits::init (obj,
+ use_copy_ ? *image_copy_ : statements_.image (),
+ &db);
+
+ // If we are using a copy, make sure the callback information for
+ // LOB data also comes from the copy.
+ //
+ statement_->stream_result (
+ use_copy_ ? &statements_.image () : 0,
+ use_copy_ ? image_copy_ : 0);
+
+ object_traits::callback (db, obj, callback_event::post_load);
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ next ()
+ {
+ this->current (pointer_type ());
+
+ typename object_traits::image_type& im (statements_.image ());
+ change_callback_type& cc (im.change_callback_);
+
+ if (cc.context == this)
+ {
+ cc.callback = 0;
+ cc.context = 0;
+ }
+
+ use_copy_ = false;
+
+ 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++;
+ }
+
+ if (statement_->fetch () == select_statement::no_data)
+ {
+ statement_->free_result ();
+ this->end_ = true;
+ }
+ else
+ {
+ cc.callback = &change_callback;
+ cc.context = this;
+ }
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ cache ()
+ {
+ }
+
+ template <typename T>
+ std::size_t no_id_object_result_impl<T>::
+ size ()
+ {
+ throw result_not_cached ();
+ }
+
+ template <typename T>
+ void no_id_object_result_impl<T>::
+ change_callback (void* c, binding* b)
+ {
+ no_id_object_result_impl<T>* r (
+ static_cast<no_id_object_result_impl<T>*> (c));
+
+ typename object_traits::image_type im (r->statements_.image ());
+
+ if (r->image_copy_ == 0)
+ r->image_copy_ = new typename object_traits::image_type (im);
+ else
+ *r->image_copy_ = im;
+
+ // See comment in simple object_result for details on what's going
+ // on here.
+ //
+ im.version++;
+ if (b != 0)
+ b->version++;
+
+ im.change_callback_.callback = 0;
+ im.change_callback_.context = 0;
+
+ r->use_copy_ = true;
+ }
+ }
+}
diff --git a/odb/oracle/no-id-object-statements.hxx b/odb/oracle/no-id-object-statements.hxx
new file mode 100644
index 0000000..0aa5cf0
--- /dev/null
+++ b/odb/oracle/no-id-object-statements.hxx
@@ -0,0 +1,133 @@
+// file : odb/oracle/no-id-object-statements.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_NO_ID_OBJECT_STATEMENTS_HXX
+#define ODB_ORACLE_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/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
+#include <odb/oracle/oracle-types.hxx>
+#include <odb/oracle/binding.hxx>
+#include <odb/oracle/statement.hxx>
+#include <odb/oracle/statements-base.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ //
+ // 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 oracle::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_;}
+
+ // 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 insert_column_count =
+ object_traits::column_count;
+
+ static const std::size_t select_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_;
+ bind select_image_bind_[select_column_count];
+
+ // Insert binding.
+ //
+ std::size_t insert_image_version_;
+ binding insert_image_binding_;
+ bind insert_image_bind_[insert_column_count];
+
+ details::shared_ptr<insert_statement_type> persist_;
+ };
+ }
+}
+
+#include <odb/oracle/no-id-object-statements.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_NO_ID_OBJECT_STATEMENTS_HXX
diff --git a/odb/oracle/no-id-object-statements.txx b/odb/oracle/no-id-object-statements.txx
new file mode 100644
index 0000000..b5576a0
--- /dev/null
+++ b/odb/oracle/no-id-object-statements.txx
@@ -0,0 +1,34 @@
+// file : odb/oracle/no-id-object-statements.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#include <cstring> // std::memset
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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;
+
+ select_image_binding_.change_callback = image_.change_callback ();
+
+ std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
+ std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
+ }
+ }
+}
diff --git a/odb/oracle/object-result.hxx b/odb/oracle/object-result.hxx
deleted file mode 100644
index 94885e5..0000000
--- a/odb/oracle/object-result.hxx
+++ /dev/null
@@ -1,125 +0,0 @@
-// file : odb/oracle/object-result.hxx
-// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
-// license : ODB NCUEL; see accompanying LICENSE file
-
-#ifndef ODB_ORACLE_OBJECT_RESULT_HXX
-#define ODB_ORACLE_OBJECT_RESULT_HXX
-
-#include <odb/pre.hxx>
-
-#include <cstddef> // std::size_t
-
-#include <odb/details/shared-ptr.hxx>
-
-#include <odb/oracle/version.hxx>
-#include <odb/oracle/forward.hxx> // query, object_statements
-#include <odb/oracle/result.hxx>
-#include <odb/oracle/statement.hxx>
-
-namespace odb
-{
- namespace oracle
- {
- 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:
- typedef oracle::change_callback change_callback_type;
-
- static void
- change_callback (void* context);
-
- private:
- details::shared_ptr<select_statement> statement_;
- object_statements<object_type>& statements_;
- bool use_copy_;
- typename object_traits::image_type* image_copy_;
- };
-
- 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:
- typedef oracle::change_callback change_callback_type;
-
- static void
- change_callback (void* context);
-
- private:
- details::shared_ptr<select_statement> statement_;
- object_statements_no_id<object_type>& statements_;
- bool use_copy_;
- typename object_traits::image_type* image_copy_;
- };
- }
-}
-
-#include <odb/oracle/object-result.txx>
-
-#include <odb/post.hxx>
-
-#endif // ODB_ORACLE_OBJECT_RESULT_HXX
diff --git a/odb/oracle/oracle-types.hxx b/odb/oracle/oracle-types.hxx
index 5b87220..693be5c 100644
--- a/odb/oracle/oracle-types.hxx
+++ b/odb/oracle/oracle-types.hxx
@@ -10,6 +10,7 @@
#include <odb/details/buffer.hxx>
#include <odb/oracle/version.hxx>
+#include <odb/oracle/forward.hxx> // binding
#include <odb/oracle/oracle-fwd.hxx>
#include <odb/oracle/details/export.hxx>
@@ -131,7 +132,7 @@ namespace odb
{
change_callback (): callback (0), context (0) {};
- void (*callback) (void*);
+ void (*callback) (void*, binding*);
void* context;
};
diff --git a/odb/oracle/polymorphic-object-result.hxx b/odb/oracle/polymorphic-object-result.hxx
new file mode 100644
index 0000000..2137c1d
--- /dev/null
+++ b/odb/oracle/polymorphic-object-result.hxx
@@ -0,0 +1,91 @@
+// file : odb/oracle/polymorphic-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_POLYMORPHIC_OBJECT_RESULT_HXX
+#define ODB_ORACLE_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/oracle/version.hxx>
+#include <odb/oracle/forward.hxx> // query
+#include <odb/oracle/statement.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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::image_type image_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:
+ typedef oracle::change_callback change_callback_type;
+
+ static void
+ change_callback (void* context, binding*);
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ bool use_copy_;
+ image_type* image_copy_;
+ };
+ }
+}
+
+#include <odb/oracle/polymorphic-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_POLYMORPHIC_OBJECT_RESULT_HXX
diff --git a/odb/oracle/polymorphic-object-result.txx b/odb/oracle/polymorphic-object-result.txx
new file mode 100644
index 0000000..f371258
--- /dev/null
+++ b/odb/oracle/polymorphic-object-result.txx
@@ -0,0 +1,322 @@
+// file : odb/oracle/polymorphic-object-result.txx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#include <cassert>
+
+#include <odb/callback.hxx>
+#include <odb/cache-traits.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
+
+#include <odb/oracle/polymorphic-object-statements.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ template <typename T>
+ polymorphic_object_result_impl<T>::
+ ~polymorphic_object_result_impl ()
+ {
+ change_callback_type& cc (
+ statements_.root_statements ().image ().change_callback_);
+
+ if (cc.context == this)
+ {
+ cc.context = 0;
+ cc.callback = 0;
+ }
+
+ if (image_copy_ != 0)
+ object_traits::free_image (image_copy_);
+
+ 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),
+ use_copy_ (false),
+ image_copy_ (0)
+ {
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ load (object_type* pobj, bool)
+ {
+ 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 ());
+ image_type& i (use_copy_ ? *image_copy_ : statements_.image ());
+ typename root_traits::image_type& ri (
+ use_copy_ ? object_traits::root_image (i) : 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));
+
+ // 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);
+
+ // If we are using a copy, make sure the callback information for
+ // LOB data also comes from the copy.
+ //
+ statement_->stream_result (
+ use_copy_ ? &statements_.image () : 0,
+ use_copy_ ? image_copy_ : 0);
+
+ // 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 ()
+ {
+ typename root_traits::image_type& i (
+ use_copy_
+ ? object_traits::root_image (*image_copy_)
+ : statements_.root_statements ().image ());
+
+ return root_traits::id (i);
+ }
+
+ template <typename T>
+ typename polymorphic_object_result_impl<T>::discriminator_type
+ polymorphic_object_result_impl<T>::
+ load_discriminator ()
+ {
+ typename root_traits::image_type& i (
+ use_copy_
+ ? object_traits::root_image (*image_copy_)
+ : statements_.root_statements ().image ());
+
+ return root_traits::discriminator (i);
+ }
+
+ template <typename T, typename R>
+ struct polymorphic_image_rebind
+ {
+ // Derived type version.
+ //
+ typedef object_traits<T> traits;
+
+ static void
+ 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 ());
+ }
+ }
+
+ static void
+ inc_version (typename traits::image_type& i)
+ {
+ polymorphic_image_rebind<
+ typename traits::base_type,
+ typename traits::root_type>::inc_version (*i.base);
+
+ i.version++;
+ }
+ };
+
+ template <typename R>
+ struct polymorphic_image_rebind<R, R>
+ {
+ // Root type version.
+ //
+ typedef object_traits<R> traits;
+
+ static void
+ 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++;
+ }
+ }
+
+ static void
+ inc_version (typename traits::image_type& i)
+ {
+ i.version++;
+ }
+ };
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ next ()
+ {
+ this->current (pointer_type ());
+
+ change_callback_type& cc (
+ statements_.root_statements ().image ().change_callback_);
+
+ if (cc.context == this)
+ {
+ cc.callback = 0;
+ cc.context = 0;
+ }
+
+ use_copy_ = false;
+ polymorphic_image_rebind<object_type, root_type>::rebind (statements_);
+
+ if (statement_->fetch () == select_statement::no_data)
+ {
+ statement_->free_result ();
+ this->end_ = true;
+ }
+ else
+ {
+ cc.callback = &change_callback;
+ cc.context = this;
+ }
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ cache ()
+ {
+ }
+
+ template <typename T>
+ std::size_t polymorphic_object_result_impl<T>::
+ size ()
+ {
+ throw result_not_cached ();
+ }
+
+ template <typename T>
+ void polymorphic_object_result_impl<T>::
+ change_callback (void* c, binding* b)
+ {
+ polymorphic_object_result_impl<T>* r (
+ static_cast<polymorphic_object_result_impl<T>*> (c));
+ image_type& im (r->statements_.image ());
+
+ if (r->image_copy_ == 0)
+ r->image_copy_ = object_traits::clone_image (im);
+ else
+ object_traits::copy_image (*r->image_copy_, im);
+
+ typename root_traits::image_type& rim (
+ r->statements_.root_statements ().image ());
+
+ // See comment in simple object_result for details on what's going
+ // on here.
+ //
+ polymorphic_image_rebind<object_type, root_type>::inc_version (im);
+ if (b != 0)
+ b->version++;
+
+ rim.change_callback_.callback = 0;
+ rim.change_callback_.context = 0;
+
+ r->use_copy_ = true;
+ }
+ }
+}
diff --git a/odb/oracle/polymorphic-object-statements.hxx b/odb/oracle/polymorphic-object-statements.hxx
new file mode 100644
index 0000000..0b8ddcb
--- /dev/null
+++ b/odb/oracle/polymorphic-object-statements.hxx
@@ -0,0 +1,426 @@
+// file : odb/oracle/polymorphic-object-statements.hxx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_POLYMORPHIC_OBJECT_STATEMENTS_HXX
+#define ODB_ORACLE_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/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
+#include <odb/oracle/oracle-types.hxx>
+#include <odb/oracle/binding.hxx>
+#include <odb/oracle/statement.hxx>
+#include <odb/oracle/statements-base.hxx>
+#include <odb/oracle/simple-object-statements.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ //
+ // 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_;}
+
+ // 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_,
+ 0)); // No LOB prefetch (discriminator cannot be LOB).
+
+ 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_;
+ bind discriminator_image_bind_[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_;
+ 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 oracle::insert_statement insert_statement_type;
+ typedef oracle::select_statement select_statement_type;
+ typedef oracle::update_statement update_statement_type;
+ typedef oracle::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];
+ }
+
+ // 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],
+ 4096)); // Hardcode a 4kB LOB prefetch size.
+
+ 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_));
+
+ 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 ()));
+
+ 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];
+ bind select_image_bind_[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_;
+ 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_;
+ 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/oracle/polymorphic-object-statements.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_POLYMORPHIC_OBJECT_STATEMENTS_HXX
diff --git a/odb/oracle/polymorphic-object-statements.txx b/odb/oracle/polymorphic-object-statements.txx
new file mode 100644
index 0000000..e997662
--- /dev/null
+++ b/odb/oracle/polymorphic-object-statements.txx
@@ -0,0 +1,133 @@
+// file : odb/oracle/polymorphic-object-statements.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#include <cstring> // std::memset
+
+#include <odb/callback.hxx>
+#include <odb/exceptions.hxx>
+
+#include <odb/oracle/connection.hxx>
+#include <odb/oracle/transaction.hxx>
+#include <odb/oracle/statement-cache.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ //
+ // 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_));
+ }
+
+ //
+ // 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];
+ select_image_bindings_[i].change_callback = 0;
+ }
+
+ // Statements other than the first one (which goes all the way to
+ // the root) can never override the image because they are used to
+ // load up the dynamic part of the object only after the static
+ // part has been loaded (and triggered the callback if necessary).
+ //
+ select_image_bindings_[0].change_callback =
+ root_statements_.image ().change_callback ();
+
+ 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_));
+ }
+
+ 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);
+ sts.find_[0]->stream_result ();
+ 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/oracle/result.hxx b/odb/oracle/result.hxx
deleted file mode 100644
index ff89b30..0000000
--- a/odb/oracle/result.hxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// file : odb/oracle/result.hxx
-// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
-// license : ODB NCUEL; see accompanying LICENSE file
-
-#ifndef ODB_ORACLE_RESULT_HXX
-#define ODB_ORACLE_RESULT_HXX
-
-#include <odb/pre.hxx>
-
-#include <odb/traits.hxx>
-#include <odb/result.hxx>
-
-#include <odb/oracle/version.hxx>
-#include <odb/oracle/forward.hxx>
-
-#include <odb/post.hxx>
-
-#endif // ODB_ORACLE_RESULT_HXX
-
-// Include result specializations so that the user code only needs
-// to include this header.
-//
-
-#include <odb/oracle/object-result.hxx>
-#include <odb/oracle/view-result.hxx>
diff --git a/odb/oracle/simple-object-result.hxx b/odb/oracle/simple-object-result.hxx
new file mode 100644
index 0000000..cbfe8c5
--- /dev/null
+++ b/odb/oracle/simple-object-result.hxx
@@ -0,0 +1,82 @@
+// file : odb/oracle/simple-object-result.hxx
+// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_SIMPLE_OBJECT_RESULT_HXX
+#define ODB_ORACLE_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/oracle/version.hxx>
+#include <odb/oracle/forward.hxx> // query
+#include <odb/oracle/statement.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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:
+ typedef oracle::change_callback change_callback_type;
+
+ static void
+ change_callback (void* context, binding*);
+
+ private:
+ details::shared_ptr<select_statement> statement_;
+ statements_type& statements_;
+ bool use_copy_;
+ typename object_traits::image_type* image_copy_;
+ };
+ }
+}
+
+#include <odb/oracle/simple-object-result.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_SIMPLE_OBJECT_RESULT_HXX
diff --git a/odb/oracle/object-result.txx b/odb/oracle/simple-object-result.txx
index ddc9783..ec0d1f5 100644
--- a/odb/oracle/object-result.txx
+++ b/odb/oracle/simple-object-result.txx
@@ -1,22 +1,18 @@
-// file : odb/oracle/object-result.txx
+// file : odb/oracle/simple-object-result.txx
// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC
// license : ODB NCUEL; see accompanying LICENSE file
#include <cassert>
#include <odb/callback.hxx>
-#include <odb/exceptions.hxx>
+#include <odb/exceptions.hxx> // result_not_cached
-#include <odb/oracle/object-statements.hxx>
+#include <odb/oracle/simple-object-statements.hxx>
namespace odb
{
namespace oracle
{
- //
- // object_result_impl
- //
-
template <typename T>
object_result_impl<T>::
~object_result_impl ()
@@ -39,7 +35,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),
@@ -55,7 +51,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);
@@ -153,7 +149,7 @@ namespace odb
template <typename T>
void object_result_impl<T>::
- change_callback (void* c)
+ change_callback (void* c, binding* b)
{
object_result_impl<T>* r (static_cast<object_result_impl<T>*> (c));
typename object_traits::image_type& im (r->statements_.image ());
@@ -163,144 +159,18 @@ namespace odb
else
*r->image_copy_ = im;
- // Increment binding version since we may have "stolen" some
- // descriptors (LOB, date-time) from the image. Re-bind will
- // reallocate them and update the binding.
- //
- r->statements_.select_image_binding ().version++;
-
- im.change_callback_.callback = 0;
- im.change_callback_.context = 0;
-
- r->use_copy_ = true;
- }
-
- //
- // object_result_impl_no_id
- //
-
- template <typename T>
- object_result_impl_no_id<T>::
- ~object_result_impl_no_id ()
- {
- change_callback_type& cc (statements_.image ().change_callback_);
-
- if (cc.context == this)
- {
- cc.context = 0;
- cc.callback = 0;
- }
-
- delete image_copy_;
-
- 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),
- use_copy_ (false),
- image_copy_ (0)
- {
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- load (object_type& obj)
- {
- odb::database& db (this->database ());
-
- object_traits::callback (db, obj, callback_event::pre_load);
-
- object_traits::init (obj,
- use_copy_ ? *image_copy_ : statements_.image (),
- &db);
-
- // If we are using a copy, make sure the callback information for
- // LOB data also comes from the copy.
+ // Increment image version since we may have "stolen" descriptors
+ // (LOB, date-time) from the image. This will trigger re-bind which
+ // will reallocate them and update the binding. In case this callback
+ // was triggeted as part of a select statement fetch, then it is too
+ // late to update the image version and we also need to update the
+ // image binding.
//
- statement_->stream_result (
- use_copy_ ? &statements_.image () : 0,
- use_copy_ ? image_copy_ : 0);
-
- object_traits::callback (db, obj, callback_event::post_load);
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- next ()
- {
- this->current (pointer_type ());
-
- typename object_traits::image_type& im (statements_.image ());
- change_callback_type& cc (im.change_callback_);
-
- if (cc.context == this)
- {
- cc.callback = 0;
- cc.context = 0;
- }
-
- use_copy_ = false;
-
- 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++;
- }
-
- if (statement_->fetch () == select_statement::no_data)
- {
- statement_->free_result ();
- this->end_ = true;
- }
- else
- {
- cc.callback = &change_callback;
- cc.context = this;
- }
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- cache ()
- {
- }
-
- template <typename T>
- std::size_t object_result_impl_no_id<T>::
- size ()
- {
- throw result_not_cached ();
- }
-
- template <typename T>
- void object_result_impl_no_id<T>::
- change_callback (void* c)
- {
- object_result_impl_no_id<T>* r (
- static_cast<object_result_impl_no_id<T>*> (c));
-
- typename object_traits::image_type im (r->statements_.image ());
-
- if (r->image_copy_ == 0)
- r->image_copy_ = new typename object_traits::image_type (im);
- else
- *r->image_copy_ = im;
-
- // Increment binding version since we may have "stolen" some
- // descriptors (LOB, date-time) from the image. Re-bind will
- // reallocate them and update the binding.
+ // @@ Would be good to only do this if we actually have descriptors.
//
- r->statements_.select_image_binding ().version++;
+ im.version++;
+ if (b != 0)
+ b->version++;
im.change_callback_.callback = 0;
im.change_callback_.context = 0;
diff --git a/odb/oracle/object-statements.cxx b/odb/oracle/simple-object-statements.cxx
index 8000f48..51be556 100644
--- a/odb/oracle/object-statements.cxx
+++ b/odb/oracle/simple-object-statements.cxx
@@ -1,8 +1,8 @@
-// file : odb/oracle/object-statements.cxx
+// file : odb/oracle/simple-object-statements.cxx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : ODB NCUEL; see accompanying LICENSE file
-#include <odb/oracle/object-statements.hxx>
+#include <odb/oracle/simple-object-statements.hxx>
namespace odb
{
diff --git a/odb/oracle/object-statements.hxx b/odb/oracle/simple-object-statements.hxx
index 2fb829d..2a007b2 100644
--- a/odb/oracle/object-statements.hxx
+++ b/odb/oracle/simple-object-statements.hxx
@@ -1,9 +1,9 @@
-// file : odb/oracle/object-statements.hxx
+// file : odb/oracle/simple-object-statements.hxx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : ODB NCUEL; see accompanying LICENSE file
-#ifndef ODB_ORACLE_OBJECT_STATEMENTS_HXX
-#define ODB_ORACLE_OBJECT_STATEMENTS_HXX
+#ifndef ODB_ORACLE_SIMPLE_OBJECT_STATEMENTS_HXX
+#define ODB_ORACLE_SIMPLE_OBJECT_STATEMENTS_HXX
#include <odb/pre.hxx>
@@ -18,7 +18,9 @@
#include <odb/details/shared-ptr.hxx>
#include <odb/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
#include <odb/oracle/oracle-types.hxx>
+#include <odb/oracle/binding.hxx>
#include <odb/oracle/statement.hxx>
#include <odb/oracle/statements-base.hxx>
@@ -28,24 +30,6 @@ namespace odb
{
namespace oracle
{
- 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
@@ -371,18 +361,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
@@ -404,6 +383,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_;
@@ -454,17 +444,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;
@@ -492,111 +486,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 oracle::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_;}
-
- // 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 insert_column_count =
- object_traits::column_count;
-
- static const std::size_t select_column_count =
- object_traits::column_count;
-
- private:
- image_type image_;
-
- // Select binding.
- //
- std::size_t select_image_version_;
- binding select_image_binding_;
- bind select_image_bind_[select_column_count];
-
- // Insert binding.
- //
- std::size_t insert_image_version_;
- binding insert_image_binding_;
- bind insert_image_bind_[insert_column_count];
-
- details::shared_ptr<insert_statement_type> persist_;
- };
}
}
-#include <odb/oracle/object-statements.ixx>
-#include <odb/oracle/object-statements.txx>
+#include <odb/oracle/simple-object-statements.ixx>
+#include <odb/oracle/simple-object-statements.txx>
#include <odb/post.hxx>
-#endif // ODB_ORACLE_OBJECT_STATEMENTS_HXX
+#endif // ODB_ORACLE_SIMPLE_OBJECT_STATEMENTS_HXX
diff --git a/odb/oracle/object-statements.ixx b/odb/oracle/simple-object-statements.ixx
index e4eb6d7..3e399f6 100644
--- a/odb/oracle/object-statements.ixx
+++ b/odb/oracle/simple-object-statements.ixx
@@ -1,4 +1,4 @@
-// file : odb/oracle/object-statements.ixx
+// file : odb/oracle/simple-object-statements.ixx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : ODB NCUEL; see accompanying LICENSE file
@@ -6,7 +6,7 @@ namespace odb
{
namespace oracle
{
- //
+ //
// auto_unlock
//
inline object_statements_base::auto_unlock::
diff --git a/odb/oracle/object-statements.txx b/odb/oracle/simple-object-statements.txx
index 65fcf46..83aff45 100644
--- a/odb/oracle/object-statements.txx
+++ b/odb/oracle/simple-object-statements.txx
@@ -1,8 +1,7 @@
-// file : odb/oracle/object-statements.txx
+// file : odb/oracle/simple-object-statements.txx
// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
// license : ODB NCUEL; see accompanying LICENSE file
-#include <cstddef> // std::size_t
#include <cstring> // std::memset
#include <odb/session.hxx>
@@ -82,37 +81,42 @@ 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);
- find_->stream_result ();
- 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);
+ find_->stream_result ();
+ 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 ();
}
@@ -129,38 +133,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_no_id
- //
-
- 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;
-
- select_image_binding_.change_callback = image_.change_callback ();
-
- std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_));
- std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
- }
}
}
diff --git a/odb/oracle/statement-cache.hxx b/odb/oracle/statement-cache.hxx
index 549251a..d4d65ca 100644
--- a/odb/oracle/statement-cache.hxx
+++ b/odb/oracle/statement-cache.hxx
@@ -11,11 +11,11 @@
#include <typeinfo>
#include <odb/forward.hxx>
+#include <odb/traits.hxx>
#include <odb/oracle/version.hxx>
+#include <odb/oracle/forward.hxx>
#include <odb/oracle/statements-base.hxx>
-#include <odb/oracle/object-statements.hxx>
-#include <odb/oracle/view-statements.hxx>
#include <odb/details/shared-ptr.hxx>
#include <odb/details/type-info.hxx>
@@ -26,49 +26,18 @@ namespace odb
{
namespace oracle
{
- class connection;
-
class LIBODB_ORACLE_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_));
-
- map_.insert (map::value_type (&typeid (T), p));
- return *p;
- }
+ typename object_traits<T>::statements_type&
+ find_object ();
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 +50,8 @@ namespace odb
}
}
+#include <odb/oracle/statement-cache.txx>
+
#include <odb/post.hxx>
#endif // ODB_ORACLE_STATEMENT_CACHE_HXX
diff --git a/odb/oracle/statement-cache.txx b/odb/oracle/statement-cache.txx
new file mode 100644
index 0000000..6f62b8f
--- /dev/null
+++ b/odb/oracle/statement-cache.txx
@@ -0,0 +1,43 @@
+// file : odb/oracle/statement-cache.txx
+// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC
+// license : ODB NCUEL; see accompanying LICENSE file
+
+namespace odb
+{
+ namespace oracle
+ {
+ 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/oracle/statement.cxx b/odb/oracle/statement.cxx
index 8cf2452..309a5ce 100644
--- a/odb/oracle/statement.cxx
+++ b/odb/oracle/statement.cxx
@@ -1389,7 +1389,7 @@ namespace odb
change_callback* cc (result_.change_callback);
if (cc != 0 && cc->callback != 0)
- (cc->callback) (cc->context);
+ (cc->callback) (cc->context, &result_);
if (result_version_ != result_.version)
{
diff --git a/odb/oracle/view-result.hxx b/odb/oracle/view-result.hxx
index 3eb4e2a..f44911a 100644
--- a/odb/oracle/view-result.hxx
+++ b/odb/oracle/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/oracle/version.hxx>
#include <odb/oracle/forward.hxx> // query, view_statements
-#include <odb/oracle/result.hxx>
#include <odb/oracle/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&);
@@ -57,11 +60,11 @@ namespace odb
typedef oracle::change_callback change_callback_type;
static void
- change_callback (void* context);
+ change_callback (void* context, binding*);
private:
details::shared_ptr<select_statement> statement_;
- view_statements<view_type>& statements_;
+ statements_type& statements_;
bool use_copy_;
typename view_traits::image_type* image_copy_;
};
diff --git a/odb/oracle/view-result.txx b/odb/oracle/view-result.txx
index 64d949e..dc5cd6a 100644
--- a/odb/oracle/view-result.txx
+++ b/odb/oracle/view-result.txx
@@ -33,7 +33,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),
@@ -116,7 +116,7 @@ namespace odb
template <typename T>
void view_result_impl<T>::
- change_callback (void* c)
+ change_callback (void* c, binding*)
{
view_result_impl<T>* r (static_cast<view_result_impl<T>*> (c));
@@ -127,9 +127,10 @@ namespace odb
else
*r->image_copy_ = im;
- // Increment binding version since we may have "stolen" some
- // descriptors (LOB, date-time) from the image. Re-bind will
- // reallocate them and update the binding.
+ // See comment in simple object_result for details on what's going
+ // on here. Except for views, there is nothing else other than the
+ // select binding, so just incrementing the binding version will
+ // be sufficient.
//
r->statements_.image_binding ().version++;