From 851cbe3927b987ec992bbbb69bd62224bf4a0dc3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 23 Apr 2012 16:48:01 +0200 Subject: Polymorphic inheritance support --- odb/sqlite/polymorphic-object-statements.hxx | 452 +++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 odb/sqlite/polymorphic-object-statements.hxx (limited to 'odb/sqlite/polymorphic-object-statements.hxx') diff --git a/odb/sqlite/polymorphic-object-statements.hxx b/odb/sqlite/polymorphic-object-statements.hxx new file mode 100644 index 0000000..1212176 --- /dev/null +++ b/odb/sqlite/polymorphic-object-statements.hxx @@ -0,0 +1,452 @@ +// file : odb/sqlite/polymorphic-object-statements.hxx +// copyright : Copyright (c) 2005-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SQLITE_POLYMORPHIC_OBJECT_STATEMENTS_HXX +#define ODB_SQLITE_POLYMORPHIC_OBJECT_STATEMENTS_HXX + +#include + +#include // std::size_t + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace odb +{ + namespace sqlite + { + // + // Implementation for polymorphic objects. + // + + template + class polymorphic_root_object_statements: public object_statements + { + public: + typedef typename object_statements::connection_type connection_type; + typedef typename object_statements::object_traits object_traits; + typedef typename object_statements::id_image_type id_image_type; + + typedef + typename object_traits::discriminator_image_type + discriminator_image_type; + + typedef + typename object_statements::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_;} + + 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_)); + + find_discriminator_->cached (true); + } + + 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::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]; + 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_; + bind discriminator_id_image_bind_[id_column_count]; + + details::shared_ptr find_discriminator_; + }; + + template + class polymorphic_derived_object_statements: public statements_base + { + public: + typedef T object_type; + typedef odb::object_traits 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_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 sqlite::insert_statement insert_statement_type; + typedef sqlite::select_statement select_statement_type; + typedef sqlite::update_statement update_statement_type; + typedef sqlite::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]; + } + + 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_)); + + persist_->cached (true); + } + + return *persist_; + } + + select_statement_type& + find_statement (std::size_t d) + { + std::size_t i (object_traits::depth - d); + details::shared_ptr& 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])); + + p->cached (true); + } + + 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_)); + + update_->cached (true); + } + + 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 ())); + + erase_->cached (true); + } + + 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]; + 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_; + 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 persist_; + details::shared_ptr find_[ + object_traits::abstract ? 1 : object_traits::depth]; + details::shared_ptr update_; + details::shared_ptr erase_; + }; + } +} + +#include + +#include + +#endif // ODB_SQLITE_POLYMORPHIC_OBJECT_STATEMENTS_HXX -- cgit v1.1