aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-08-14 15:16:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-08-14 15:16:09 +0200
commit1d287936950aa96a7b4a12b0d05633f257ab2c90 (patch)
tree08bd263cffb771dedcb016b5c6aa2ac7d5ea1471
parenta786d2278d538cf8d2e7f91f7c55b3c6e091b015 (diff)
Add support for object sections
Sections are an optimization mechanism that allows the partitioning of data members of a persistent class into groups that can be separately loaded and/or updated.
-rw-r--r--odb/oracle/database.hxx14
-rw-r--r--odb/oracle/database.ixx14
-rw-r--r--odb/oracle/forward.hxx3
-rw-r--r--odb/oracle/polymorphic-object-statements.hxx39
-rw-r--r--odb/oracle/section-statements.hxx179
-rw-r--r--odb/oracle/section-statements.txx49
-rw-r--r--odb/oracle/simple-object-statements.hxx97
-rw-r--r--odb/oracle/simple-object-statements.txx1
8 files changed, 339 insertions, 57 deletions
diff --git a/odb/oracle/database.hxx b/odb/oracle/database.hxx
index c29453b..3fe5de2 100644
--- a/odb/oracle/database.hxx
+++ b/odb/oracle/database.hxx
@@ -127,6 +127,12 @@ namespace odb
void
load (const typename object_traits<T>::id_type& id, T& object);
+ // Load (or reload, if it is already loaded) a section of an object.
+ //
+ template <typename T>
+ void
+ load (T& object, section&);
+
// Reload an object.
//
template <typename T>
@@ -197,6 +203,14 @@ namespace odb
void
update (const typename object_traits<T>::pointer_type& obj_ptr);
+ // Update a section of an object. Throws the section_not_loaded
+ // exception if the section is not loaded. Note also that this
+ // function does not clear the changed flag if it is set.
+ //
+ template <typename T>
+ void
+ update (const T& object, const section&);
+
// Make the object transient. Throw object_not_persistent if not
// found.
//
diff --git a/odb/oracle/database.ixx b/odb/oracle/database.ixx
index 562f24f..8f46e7a 100644
--- a/odb/oracle/database.ixx
+++ b/odb/oracle/database.ixx
@@ -108,6 +108,13 @@ namespace odb
}
template <typename T>
+ inline void database::
+ load (T& obj, section& s)
+ {
+ return load_<T, id_oracle> (obj, s);
+ }
+
+ template <typename T>
inline typename object_traits<T>::pointer_type database::
find (const typename object_traits<T>::id_type& id)
{
@@ -249,6 +256,13 @@ namespace odb
template <typename T>
inline void database::
+ update (const T& obj, const section& s)
+ {
+ update_<T, id_oracle> (obj, s);
+ }
+
+ template <typename T>
+ inline void database::
erase (const typename object_traits<T>::id_type& id)
{
return erase_<T, id_oracle> (id);
diff --git a/odb/oracle/forward.hxx b/odb/oracle/forward.hxx
index 9a46535..6163fdf 100644
--- a/odb/oracle/forward.hxx
+++ b/odb/oracle/forward.hxx
@@ -70,6 +70,9 @@ namespace odb
template <typename T>
class smart_container_statements;
+ template <typename T, typename ST>
+ class section_statements;
+
class query_base;
}
diff --git a/odb/oracle/polymorphic-object-statements.hxx b/odb/oracle/polymorphic-object-statements.hxx
index 818bd8b..3a3cceb 100644
--- a/odb/oracle/polymorphic-object-statements.hxx
+++ b/odb/oracle/polymorphic-object-statements.hxx
@@ -165,8 +165,8 @@ namespace odb
base_statements_type;
typedef
- typename object_traits::container_statement_cache_type
- container_statement_cache_type;
+ typename object_traits::extra_statement_cache_type
+ extra_statement_cache_type;
typedef oracle::insert_statement insert_statement_type;
typedef oracle::select_statement select_statement_type;
@@ -273,6 +273,10 @@ namespace odb
binding&
id_image_binding () {return root_statements_.id_image_binding ();}
+ binding&
+ optimistic_id_image_binding () {
+ return root_statements_.optimistic_id_image_binding ();}
+
// Statements.
//
insert_statement_type&
@@ -333,31 +337,40 @@ namespace odb
return *erase_;
}
- // Container statement cache.
+ // Extra (container, section) statement cache.
//
- container_statement_cache_type&
- container_statment_cache ()
+ extra_statement_cache_type&
+ extra_statement_cache ()
{
- return container_statement_cache_.get (conn_, id_image_binding ());
+ return extra_statement_cache_.get (
+ conn_,
+ image_,
+ id_image_binding (),
+ &id_image_binding ()); // Note, not id+version.
}
public:
- // select = total - id + base::select
+ // select = total - id - separate_load + base::select
// insert = total - inverse
- // update = total - inverse - id - readonly
+ // update = total - inverse - id - readonly - separate_update
//
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 +
+ object_traits::column_count -
+ id_column_count -
+ object_traits::separate_load_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;
+ 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;
+ object_traits::id_column_count -
+ object_traits::readonly_column_count -
+ object_traits::separate_update_column_count;
private:
polymorphic_derived_object_statements (
@@ -370,8 +383,8 @@ namespace odb
root_statements_type& root_statements_;
base_statements_type& base_statements_;
- container_statement_cache_ptr<container_statement_cache_type>
- container_statement_cache_;
+ extra_statement_cache_ptr<extra_statement_cache_type, image_type>
+ extra_statement_cache_;
image_type image_;
diff --git a/odb/oracle/section-statements.hxx b/odb/oracle/section-statements.hxx
new file mode 100644
index 0000000..8579be5
--- /dev/null
+++ b/odb/oracle/section-statements.hxx
@@ -0,0 +1,179 @@
+// file : odb/oracle/section-statements.hxx
+// copyright : Copyright (c) 2005-2013 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_ORACLE_SECTION_STATEMENTS_HXX
+#define ODB_ORACLE_SECTION_STATEMENTS_HXX
+
+#include <odb/pre.hxx>
+
+#include <cstddef> // std::size_t
+
+#include <odb/forward.hxx>
+#include <odb/traits.hxx>
+
+#include <odb/oracle/version.hxx>
+#include <odb/oracle/oracle-types.hxx>
+#include <odb/oracle/binding.hxx>
+#include <odb/oracle/statement.hxx>
+#include <odb/oracle/details/export.hxx>
+
+namespace odb
+{
+ namespace oracle
+ {
+ class connection;
+
+ // Template argument is the section traits type.
+ //
+ template <typename T, typename ST>
+ class section_statements
+ {
+ public:
+ typedef ST traits;
+
+ typedef typename traits::image_type image_type;
+
+ typedef oracle::select_statement select_statement_type;
+ typedef oracle::update_statement update_statement_type;
+
+ typedef oracle::connection connection_type;
+
+ section_statements (connection_type&,
+ image_type&,
+ binding& id, binding& idv);
+
+ connection_type&
+ connection () {return conn_;}
+
+ image_type&
+ image () {return image_;}
+
+ const binding&
+ id_binding () {return id_binding_;}
+
+ // Id and optimistic concurrency version (if any).
+ //
+ const binding&
+ idv_binding () {return idv_binding_;}
+
+ // Select binding.
+ //
+ 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_;}
+
+ // 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_;}
+
+ //
+ // Statements.
+ //
+
+ select_statement_type&
+ select_statement ()
+ {
+ if (select_ == 0)
+ select_.reset (
+ new (details::shared) select_statement_type (
+ conn_,
+ traits::select_statement,
+ id_binding_,
+ select_image_binding_,
+ 4096)); // Hardcode a 4kB LOB prefetch size.
+
+ return *select_;
+ }
+
+ update_statement_type&
+ update_statement ()
+ {
+ if (update_ == 0)
+ update_.reset (
+ new (details::shared) update_statement_type (
+ conn_,
+ traits::update_statement,
+ update_image_binding_));
+
+ return *update_;
+ }
+
+ public:
+ static const std::size_t id_column_count = traits::id_column_count;
+ static const std::size_t managed_optimistic_load_column_count =
+ traits::managed_optimistic_load_column_count;
+ static const std::size_t managed_optimistic_update_column_count =
+ traits::managed_optimistic_update_column_count;
+ static const std::size_t select_column_count = traits::load_column_count;
+ static const std::size_t update_column_count =
+ traits::update_column_count;
+
+ private:
+ section_statements (const section_statements&);
+ section_statements& operator= (const section_statements&);
+
+ protected:
+ connection_type& conn_;
+
+ // These come from object_statements.
+ //
+ image_type& image_;
+ binding& id_binding_;
+ binding& idv_binding_;
+
+ // Select binding.
+ //
+ std::size_t select_image_version_;
+
+ static const std::size_t select_bind_count =
+ select_column_count != 0 || managed_optimistic_load_column_count != 0
+ ? select_column_count + managed_optimistic_load_column_count
+ : 1;
+
+ binding select_image_binding_;
+ bind select_image_bind_[select_bind_count];
+
+ // Update binding.
+ //
+ std::size_t update_image_version_;
+ std::size_t update_id_binding_version_;
+
+ static const std::size_t update_bind_count =
+ update_column_count != 0 || managed_optimistic_update_column_count != 0
+ ? update_column_count + id_column_count +
+ managed_optimistic_update_column_count
+ : 1;
+
+ binding update_image_binding_;
+ bind update_image_bind_[update_bind_count];
+
+ details::shared_ptr<select_statement_type> select_;
+ details::shared_ptr<update_statement_type> update_;
+ };
+ }
+}
+
+#include <odb/oracle/section-statements.txx>
+
+#include <odb/post.hxx>
+
+#endif // ODB_ORACLE_SECTION_STATEMENTS_HXX
diff --git a/odb/oracle/section-statements.txx b/odb/oracle/section-statements.txx
new file mode 100644
index 0000000..a393d80
--- /dev/null
+++ b/odb/oracle/section-statements.txx
@@ -0,0 +1,49 @@
+// file : odb/oracle/section-statements.txx
+// copyright : Copyright (c) 2005-2013 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cstring> // std::memset
+
+namespace odb
+{
+ namespace oracle
+ {
+ template <typename T, typename ST>
+ section_statements<T, ST>::
+ section_statements (connection_type& conn,
+ image_type& im,
+ binding& id, binding& idv)
+ : conn_ (conn),
+ image_ (im),
+ id_binding_ (id),
+ idv_binding_ (idv),
+ select_image_binding_ (select_image_bind_,
+ select_column_count +
+ managed_optimistic_load_column_count),
+ update_image_binding_ (update_image_bind_,
+ update_column_count + id_column_count +
+ managed_optimistic_update_column_count)
+ {
+ select_image_version_ = 0;
+ update_image_version_ = 0;
+ update_id_binding_version_ = 0;
+
+ // If we are using optimistic concurrency, then the select statement
+ // will override the version member in the object image.
+ //
+ if (managed_optimistic_load_column_count != 0)
+ {
+ // Getting to the root image in polymorphic case is tricky.
+ //
+ typedef object_traits_impl<T, id_oracle> object_traits;
+
+ select_image_binding_.change_callback =
+ root_image<object_traits, object_traits::polymorphic>::get (
+ image_).change_callback ();
+ }
+
+ std::memset (select_image_bind_, 0, sizeof (select_image_bind_));
+ std::memset (update_image_bind_, 0, sizeof (update_image_bind_));
+ }
+ }
+}
diff --git a/odb/oracle/simple-object-statements.hxx b/odb/oracle/simple-object-statements.hxx
index a1a695b..17e6085 100644
--- a/odb/oracle/simple-object-statements.hxx
+++ b/odb/oracle/simple-object-statements.hxx
@@ -29,58 +29,59 @@ namespace odb
{
namespace oracle
{
- // The container_statement_cache class is only defined (and used) in
+ // The extra_statement_cache class is only defined (and used) in
// the generated source file. However, object_statements may be
// referenced from another source file in the case of a polymorphic
- // hierarchy (though in this case the container statement cache is
+ // hierarchy (though in this case the extra statement cache is
// not used). As a result, we cannot have a by-value member and
// instead will store a pointer and lazily allocate the cache if
// and when needed. We will also need to store a pointer to the
// deleter function which will be initialized during allocation
// (at that point we know that the cache class is defined).
//
- template <typename T>
- struct container_statement_cache_ptr
+ template <typename T, typename I>
+ struct extra_statement_cache_ptr
{
+ typedef I image_type;
typedef oracle::connection connection_type;
- container_statement_cache_ptr (): p_ (0) {}
- ~container_statement_cache_ptr ()
+ extra_statement_cache_ptr (): p_ (0) {}
+ ~extra_statement_cache_ptr ()
{
if (p_ != 0)
- (this->*deleter_) (0, 0);
+ (this->*deleter_) (0, 0, 0, 0);
}
T&
- get (connection_type& c, binding& id)
+ get (connection_type& c, image_type& im, binding& id, binding* idv)
{
if (p_ == 0)
- allocate (&c, &id);
+ allocate (&c, &im, &id, (idv != 0 ? idv : &id));
return *p_;
}
private:
void
- allocate (connection_type*, binding*);
+ allocate (connection_type*, image_type*, binding*, binding*);
private:
T* p_;
- void (container_statement_cache_ptr::*deleter_) (
- connection_type*, binding*);
+ void (extra_statement_cache_ptr::*deleter_) (
+ connection_type*, image_type*, binding*, binding*);
};
- template <typename T>
- void container_statement_cache_ptr<T>::
- allocate (connection_type* c, binding* id)
+ template <typename T, typename I>
+ void extra_statement_cache_ptr<T, I>::
+ allocate (connection_type* c, image_type* im, binding* id, binding* idv)
{
// To reduce object code size, this function acts as both allocator
// and deleter.
//
if (p_ == 0)
{
- p_ = new T (*c, *id);
- deleter_ = &container_statement_cache_ptr<T>::allocate;
+ p_ = new T (*c, *im, *id, *idv);
+ deleter_ = &extra_statement_cache_ptr<T, I>::allocate;
}
else
delete p_;
@@ -156,9 +157,11 @@ namespace odb
optimistic_data (bind*);
+ binding*
+ id_image_binding () {return &id_image_binding_;}
+
// The id + optimistic column binding.
//
- std::size_t id_image_version_;
binding id_image_binding_;
details::shared_ptr<delete_statement> erase_;
@@ -168,6 +171,9 @@ namespace odb
struct optimistic_data<T, false>
{
optimistic_data (bind*) {}
+
+ binding*
+ id_image_binding () {return 0;}
};
template <typename T>
@@ -186,8 +192,8 @@ namespace odb
pointer_cache_traits;
typedef
- typename object_traits::container_statement_cache_type
- container_statement_cache_type;
+ typename object_traits::extra_statement_cache_type
+ extra_statement_cache_type;
typedef oracle::insert_statement insert_statement_type;
typedef oracle::select_statement select_statement_type;
@@ -326,14 +332,10 @@ namespace odb
binding&
id_image_binding () {return id_image_binding_;}
- // Optimistic id + managed column image binding.
+ // Optimistic id + managed column image binding. It points to
+ // the same suffix as id binding and they are always updated
+ // at the same time.
//
- std::size_t
- optimistic_id_image_version () const {return od_.id_image_version_;}
-
- void
- optimistic_id_image_version (std::size_t v) {od_.id_image_version_ = v;}
-
binding&
optimistic_id_image_binding () {return od_.id_image_binding_;}
@@ -409,36 +411,42 @@ namespace odb
return *od_.erase_;
}
- // Container statement cache.
+ // Extra (container, section) statement cache.
//
- container_statement_cache_type&
- container_statment_cache ()
+ extra_statement_cache_type&
+ extra_statement_cache ()
{
- return container_statement_cache_.get (conn_, id_image_binding_);
+ return extra_statement_cache_.get (
+ conn_, image_, id_image_binding_, od_.id_image_binding ());
}
public:
- // select = total
+ // select = total - separate_load
// insert = total - inverse - managed_optimistic - auto_id
// update = total - inverse - managed_optimistic - id - readonly
+ // - separate_update
//
- static const std::size_t select_column_count =
- object_traits::column_count;
-
static const std::size_t id_column_count =
object_traits::id_column_count;
+ static const std::size_t managed_optimistic_column_count =
+ object_traits::managed_optimistic_column_count;
+
+ static const std::size_t select_column_count =
+ object_traits::column_count -
+ object_traits::separate_load_column_count;
+
static const std::size_t insert_column_count =
- object_traits::column_count - object_traits::inverse_column_count -
+ object_traits::column_count -
+ object_traits::inverse_column_count -
object_traits::managed_optimistic_column_count -
(object_traits::auto_id ? id_column_count : 0);
- static const std::size_t update_column_count = insert_column_count -
+ static const std::size_t update_column_count =
+ insert_column_count -
(object_traits::auto_id ? 0 : id_column_count) -
- object_traits::readonly_column_count;
-
- static const std::size_t managed_optimistic_column_count =
- object_traits::managed_optimistic_column_count;
+ object_traits::readonly_column_count -
+ object_traits::separate_update_column_count;
private:
object_statements (const object_statements&);
@@ -452,8 +460,11 @@ namespace odb
clear_delayed_ ();
private:
- container_statement_cache_ptr<container_statement_cache_type>
- container_statement_cache_;
+ template <typename T1>
+ friend class polymorphic_derived_object_statements;
+
+ extra_statement_cache_ptr<extra_statement_cache_type, image_type>
+ extra_statement_cache_;
image_type image_;
diff --git a/odb/oracle/simple-object-statements.txx b/odb/oracle/simple-object-statements.txx
index da5dee6..6723b1c 100644
--- a/odb/oracle/simple-object-statements.txx
+++ b/odb/oracle/simple-object-statements.txx
@@ -25,7 +25,6 @@ namespace odb
object_traits::id_column_count +
object_traits::managed_optimistic_column_count)
{
- id_image_version_ = 0;
}
//