diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-11-29 08:52:28 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-11-29 08:52:28 +0200 |
commit | 9d3bf60e2d1f063abd39197b7e60bf6d2bc95aa7 (patch) | |
tree | 4a12c0bd029f8e04a383ed905157f70e764ac165 | |
parent | 91c962e4615101e14be4c720fc386878ddb598a4 (diff) |
Add object/view/container statements, statements cache
-rw-r--r-- | odb/mssql/connection.cxx | 12 | ||||
-rw-r--r-- | odb/mssql/connection.hxx | 6 | ||||
-rw-r--r-- | odb/mssql/container-statements.hxx | 256 | ||||
-rw-r--r-- | odb/mssql/container-statements.txx | 58 | ||||
-rw-r--r-- | odb/mssql/makefile | 2 | ||||
-rw-r--r-- | odb/mssql/object-statements.cxx | 17 | ||||
-rw-r--r-- | odb/mssql/object-statements.hxx | 606 | ||||
-rw-r--r-- | odb/mssql/object-statements.ixx | 70 | ||||
-rw-r--r-- | odb/mssql/object-statements.txx | 168 | ||||
-rw-r--r-- | odb/mssql/statement-cache.hxx | 87 | ||||
-rw-r--r-- | odb/mssql/statements-base.cxx | 17 | ||||
-rw-r--r-- | odb/mssql/statements-base.hxx | 51 | ||||
-rw-r--r-- | odb/mssql/view-statements.hxx | 83 | ||||
-rw-r--r-- | odb/mssql/view-statements.txx | 33 |
14 files changed, 1454 insertions, 12 deletions
diff --git a/odb/mssql/connection.cxx b/odb/mssql/connection.cxx index 1609b80..03b8deb 100644 --- a/odb/mssql/connection.cxx +++ b/odb/mssql/connection.cxx @@ -3,16 +3,14 @@ // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // license : ODB NCUEL; see accompanying LICENSE file -//@@ disabled functionality - #include <string> #include <odb/mssql/mssql.hxx> #include <odb/mssql/database.hxx> #include <odb/mssql/connection.hxx> #include <odb/mssql/transaction.hxx> -//#include <odb/mssql/statement.hxx> -//#include <odb/mssql/statement-cache.hxx> +#include <odb/mssql/statement.hxx> +#include <odb/mssql/statement-cache.hxx> #include <odb/mssql/error.hxx> using namespace std; @@ -26,7 +24,7 @@ namespace odb : odb::connection (db), db_ (db), state_ (state_disconnected), - // statement_cache_ (new statement_cache_type (*this)) + statement_cache_ (new statement_cache_type (*this)), long_buffer_ (0) { SQLRETURN r; @@ -96,7 +94,7 @@ namespace odb db_ (db), handle_ (handle), state_ (state_connected), - // statement_cache_ (new statement_cache_type (*this)) + statement_cache_ (new statement_cache_type (*this)), long_buffer_ (0) { } @@ -106,7 +104,7 @@ namespace odb { // Deallocate prepared statements before we close the connection. // - //statement_cache_.reset (); + statement_cache_.reset (); if (state_ != state_disconnected) SQLDisconnect (handle_); // Ignore any errors. diff --git a/odb/mssql/connection.hxx b/odb/mssql/connection.hxx index c38692b..73c00fd 100644 --- a/odb/mssql/connection.hxx +++ b/odb/mssql/connection.hxx @@ -3,8 +3,6 @@ // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // license : ODB NCUEL; see accompanying LICENSE file -//@@ disabled functionality - #ifndef ODB_MSSQL_CONNECTION_HXX #define ODB_MSSQL_CONNECTION_HXX @@ -103,13 +101,11 @@ namespace odb return handle_; } - /* statement_cache_type& statement_cache () { return *statement_cache_; } - */ details::buffer& long_buffer () @@ -137,7 +133,7 @@ namespace odb // auto_handle<SQL_HANDLE_STMT> direct_stmt_; - //std::auto_ptr<statement_cache_type> statement_cache_; + std::auto_ptr<statement_cache_type> statement_cache_; details::buffer long_buffer_; }; diff --git a/odb/mssql/container-statements.hxx b/odb/mssql/container-statements.hxx new file mode 100644 index 0000000..6d9dd56 --- /dev/null +++ b/odb/mssql/container-statements.hxx @@ -0,0 +1,256 @@ +// file : odb/mssql/container-statements.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_MSSQL_CONTAINER_STATEMENTS_HXX +#define ODB_MSSQL_CONTAINER_STATEMENTS_HXX + +#include <odb/pre.hxx> + +#include <cstddef> // std::size_t + +#include <odb/forward.hxx> +#include <odb/traits.hxx> + +#include <odb/mssql/version.hxx> +#include <odb/mssql/mssql-types.hxx> +#include <odb/mssql/statement.hxx> + +#include <odb/mssql/details/export.hxx> + +namespace odb +{ + namespace mssql + { + class connection; + + // Template argument is the generated abstract container traits type. + // That is, it doesn't need to provide column counts and statements. + // + template <typename T> + class container_statements + { + public: + typedef T traits; + + typedef typename traits::data_image_type data_image_type; + typedef typename traits::cond_image_type cond_image_type; + + typedef typename traits::functions_type functions_type; + + typedef mssql::insert_statement insert_statement_type; + typedef mssql::select_statement select_statement_type; + typedef mssql::delete_statement delete_statement_type; + + typedef mssql::connection connection_type; + + container_statements (connection_type&); + + connection_type& + connection () + { + return conn_; + } + + // Functions. + // + functions_type& + functions () + { + return functions_; + } + + // Id image binding (external). + // + const binding& + id_binding () + { + return *id_binding_; + } + + void + id_binding (const binding& b) + { + id_binding_ = &b; + } + + // Condition image. + // + cond_image_type& + cond_image () + { + return cond_image_; + } + + std::size_t + cond_image_version () const + { + return cond_image_version_; + } + + void + cond_image_version (std::size_t v) + { + cond_image_version_ = v; + } + + std::size_t + cond_id_binding_version () const + { + return cond_id_binding_version_; + } + + void + cond_id_binding_version (std::size_t v) + { + cond_id_binding_version_ = v; + } + + binding& + cond_image_binding () + { + return cond_image_binding_; + } + + // Data image. + // + data_image_type& + data_image () + { + return data_image_; + } + + std::size_t + data_image_version () const + { + return data_image_version_; + } + + void + data_image_version (std::size_t v) + { + data_image_version_ = v; + } + + std::size_t + data_id_binding_version () const + { + return data_id_binding_version_; + } + + void + data_id_binding_version (std::size_t v) + { + data_id_binding_version_ = v; + } + + binding& + data_image_binding () + { + return data_image_binding_; + } + + // + // Statements. + // + + insert_statement_type& + insert_one_statement () + { + // Containers never use auto ids so hardcode the insert_statement + // constructors returning argument as false. + // + if (insert_one_ == 0) + insert_one_.reset ( + new (details::shared) insert_statement_type ( + conn_, insert_one_text_, data_image_binding_, false)); + + return *insert_one_; + } + + select_statement_type& + select_all_statement () + { + if (select_all_ == 0) + select_all_.reset ( + new (details::shared) select_statement_type ( + conn_, + select_all_text_, + cond_image_binding_, + data_image_binding_, + 4096)); // Hardcode a 4kB LOB prefetch size. + + return *select_all_; + } + + delete_statement_type& + delete_all_statement () + { + if (delete_all_ == 0) + delete_all_.reset ( + new (details::shared) delete_statement_type ( + conn_, delete_all_text_, cond_image_binding_)); + + return *delete_all_; + } + + private: + container_statements (const container_statements&); + container_statements& operator= (const container_statements&); + + protected: + connection_type& conn_; + functions_type functions_; + + const binding* id_binding_; + + cond_image_type cond_image_; + std::size_t cond_image_version_; + std::size_t cond_id_binding_version_; + binding cond_image_binding_; + bind* cond_image_bind_; + + data_image_type data_image_; + std::size_t data_image_version_; + std::size_t data_id_binding_version_; + binding data_image_binding_; + bind* data_image_bind_; + + const char* insert_one_text_; + const char* select_all_text_; + const char* delete_all_text_; + + details::shared_ptr<insert_statement_type> insert_one_; + details::shared_ptr<select_statement_type> select_all_; + details::shared_ptr<delete_statement_type> delete_all_; + }; + + // Template argument is the generated concrete container traits type. + // + template <typename T> + class container_statements_impl: public T::statements_type + { + public: + typedef T traits; + typedef typename T::statements_type base; + typedef mssql::connection connection_type; + + container_statements_impl (connection_type&); + + private: + container_statements_impl (const container_statements_impl&); + container_statements_impl& operator= (const container_statements_impl&); + + private: + bind cond_image_bind_array_[traits::cond_column_count]; + bind data_image_bind_array_[traits::data_column_count]; + }; + } +} + +#include <odb/mssql/container-statements.txx> + +#include <odb/post.hxx> + +#endif // ODB_MSSQL_CONTAINER_STATEMENTS_HXX diff --git a/odb/mssql/container-statements.txx b/odb/mssql/container-statements.txx new file mode 100644 index 0000000..cc240bb --- /dev/null +++ b/odb/mssql/container-statements.txx @@ -0,0 +1,58 @@ +// file : odb/mssql/container-statements.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include <cstring> // std::memset + +namespace odb +{ + namespace mssql + { + // container_statements + // + + template <typename T> + container_statements<T>:: + container_statements (connection_type& conn) + : conn_ (conn), + functions_ (this, + &traits::insert_one, + &traits::load_all, + &traits::delete_all), + id_binding_ (0), + cond_image_binding_ (0, 0), // Initialized by impl. + data_image_binding_ (0, 0) // Initialized by impl. + { + cond_image_.version = 0; + cond_image_version_ = 0; + cond_id_binding_version_ = 0; + + data_image_.version = 0; + data_image_version_ = 0; + data_id_binding_version_ = 0; + } + + template <typename T> + container_statements_impl<T>:: + container_statements_impl (connection_type& conn) + : base (conn) + { + this->cond_image_bind_ = cond_image_bind_array_; + this->data_image_bind_ = data_image_bind_array_; + + this->cond_image_binding_.bind = this->cond_image_bind_; + this->cond_image_binding_.count = traits::cond_column_count; + + this->data_image_binding_.bind = this->data_image_bind_; + this->data_image_binding_.count = traits::data_column_count; + + std::memset (cond_image_bind_array_, 0, sizeof (cond_image_bind_array_)); + std::memset (data_image_bind_array_, 0, sizeof (data_image_bind_array_)); + + this->insert_one_text_ = traits::insert_one_statement; + this->select_all_text_ = traits::select_all_statement; + this->delete_all_text_ = traits::delete_all_statement; + } + } +} diff --git a/odb/mssql/makefile b/odb/mssql/makefile index 4758abf..acdeb76 100644 --- a/odb/mssql/makefile +++ b/odb/mssql/makefile @@ -13,7 +13,9 @@ connection-factory.cxx \ database.cxx \ error.cxx \ exceptions.cxx \ +object-statements.cxx \ statement.cxx \ +statements-base.cxx \ tracer.cxx \ transaction.cxx \ transaction-impl.cxx diff --git a/odb/mssql/object-statements.cxx b/odb/mssql/object-statements.cxx new file mode 100644 index 0000000..2d29c1c --- /dev/null +++ b/odb/mssql/object-statements.cxx @@ -0,0 +1,17 @@ +// file : odb/mssql/object-statements.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include <odb/mssql/object-statements.hxx> + +namespace odb +{ + namespace mssql + { + object_statements_base:: + ~object_statements_base () + { + } + } +} diff --git a/odb/mssql/object-statements.hxx b/odb/mssql/object-statements.hxx new file mode 100644 index 0000000..6ab30ec --- /dev/null +++ b/odb/mssql/object-statements.hxx @@ -0,0 +1,606 @@ +// file : odb/mssql/object-statements.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_MSSQL_OBJECT_STATEMENTS_HXX +#define ODB_MSSQL_OBJECT_STATEMENTS_HXX + +#include <odb/pre.hxx> + +#include <vector> +#include <cassert> +#include <cstddef> // std::size_t + +#include <odb/forward.hxx> +#include <odb/traits.hxx> +#include <odb/cache-traits.hxx> + +#include <odb/details/shared-ptr.hxx> + +#include <odb/mssql/version.hxx> +#include <odb/mssql/forward.hxx> +#include <odb/mssql/mssql-types.hxx> +#include <odb/mssql/statement.hxx> +#include <odb/mssql/statements-base.hxx> + +#include <odb/mssql/details/export.hxx> + +namespace odb +{ + namespace mssql + { + 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. + // + + class LIBODB_MSSQL_EXPORT object_statements_base: public statements_base + { + // Locking. + // + public: + void + lock () + { + assert (!locked_); + locked_ = true; + } + + void + unlock () + { + assert (locked_); + locked_ = false; + } + + bool + locked () const + { + 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 + // destruction. + // + auto_unlock (object_statements_base&); + ~auto_unlock (); + + private: + auto_unlock (const auto_unlock&); + auto_unlock& operator= (const auto_unlock&); + + private: + object_statements_base& s_; + }; + + protected: + bool locked_; + }; + + template <typename T, bool optimistic> + struct optimistic_data; + + template <typename T> + struct optimistic_data<T, true> + { + typedef T object_type; + typedef odb::object_traits<object_type> object_traits; + + optimistic_data (bind*); + + // The id + optimistic column binding. + // + std::size_t id_image_version_; + binding id_image_binding_; + + details::shared_ptr<delete_statement> erase_; + }; + + template <typename T> + struct optimistic_data<T, false> + { + optimistic_data (bind*) {} + }; + + template <typename T> + class object_statements: public object_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::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::container_statement_cache_type + container_statement_cache_type; + + typedef mssql::insert_statement insert_statement_type; + typedef mssql::select_statement select_statement_type; + typedef mssql::update_statement update_statement_type; + typedef mssql::delete_statement delete_statement_type; + + // Automatic lock. + // + struct auto_lock + { + // Lock the statements unless they are already locked in which + // case subsequent calls to locked() will return false. + // + auto_lock (object_statements&); + + // Unlock the statements if we are holding the lock and clear + // the delayed loads. This should only happen in case an + // exception is thrown. In normal circumstances, the user + // should call unlock() explicitly. + // + ~auto_lock (); + + // Return true if this auto_lock instance holds the lock. + // + bool + locked () const; + + // Unlock the statements. + // + void + unlock (); + + private: + auto_lock (const auto_lock&); + auto_lock& operator= (const auto_lock&); + + private: + object_statements& s_; + bool locked_; + }; + + public: + object_statements (connection_type&); + + virtual + ~object_statements (); + + // Delayed loading. + // + void + delay_load (const id_type& id, + object_type& obj, + const typename object_cache_traits::position_type& p) + { + delayed_.push_back (delayed_load (id, obj, p)); + } + + void + load_delayed () + { + assert (locked ()); + + if (!delayed_.empty ()) + load_delayed_ (); + } + + void + clear_delayed () + { + if (!delayed_.empty ()) + clear_delayed_ (); + } + + // 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_;} + + // 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_image_version () const { return update_id_image_version_;} + + void + update_id_image_version (std::size_t v) {update_id_image_version_ = v;} + + binding& + update_image_binding () {return update_image_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_;} + + // Object id image and binding. + // + id_image_type& + id_image () {return id_image_;} + + std::size_t + id_image_version () const {return id_image_version_;} + + void + id_image_version (std::size_t v) {id_image_version_ = v;} + + binding& + id_image_binding () {return id_image_binding_;} + + // Optimistic id + managed column image binding. + // + 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_;} + + // 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_, + object_traits::auto_id)); + + return *persist_; + } + + select_statement_type& + find_statement () + { + if (find_ == 0) + find_.reset ( + new (details::shared) select_statement_type ( + conn_, + object_traits::find_statement, + id_image_binding_, + select_image_binding_)); + + return *find_; + } + + 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, + id_image_binding_)); + + return *erase_; + } + + delete_statement_type& + optimistic_erase_statement () + { + if (od_.erase_ == 0) + { + od_.erase_.reset ( + new (details::shared) delete_statement_type ( + conn_, + object_traits::optimistic_erase_statement, + od_.id_image_binding_)); + } + + return *od_.erase_; + } + + // Container statement cache. + // + container_statement_cache_type& + container_statment_cache () + { + return container_statement_cache_; + } + + private: + object_statements (const object_statements&); + object_statements& operator= (const object_statements&); + + private: + void + load_delayed_ (); + + void + clear_delayed_ (); + + private: + // select = total + // insert = total - inverse - managed_optimistic - auto_id + // update = total - inverse - managed_optimistic - id - readonly + // + 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; + + static const std::size_t insert_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 - + (object_traits::auto_id ? 0 : object_traits::id_column_count) - + object_traits::readonly_column_count; + + private: + container_statement_cache_type container_statement_cache_; + + 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 != 0 ? insert_column_count : 1]; + + // Update binding. Note that the id suffix is bound to id_image_ + // below instead of image_ which makes this binding effectively + // bound to two images. As a result, we have to track versions + // for both of them. If this object uses optimistic concurrency, + // then the binding for the managed column (version, timestamp, + // etc) comes after the id and the image for such a column is + // stored as part of the id image. + // + std::size_t update_image_version_; + std::size_t update_id_image_version_; + binding update_image_binding_; + bind update_image_bind_[update_column_count + id_column_count + + managed_optimistic_column_count]; + + // Id image binding (only used as a parameter). Uses the suffix in + // the update bind. + // + id_image_type id_image_; + std::size_t id_image_version_; + binding id_image_binding_; + + // Extra data for objects with optimistic concurrency support. + // + optimistic_data<T, managed_optimistic_column_count != 0> od_; + + details::shared_ptr<insert_statement_type> persist_; + details::shared_ptr<select_statement_type> find_; + details::shared_ptr<update_statement_type> update_; + details::shared_ptr<delete_statement_type> erase_; + + // Delayed loading. + // + struct delayed_load + { + typedef typename object_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) + { + } + + id_type id; + object_type* obj; + position_type pos; + }; + + typedef std::vector<delayed_load> delayed_loads; + delayed_loads delayed_; + + // Delayed vectors swap guard. See the load_delayed_() function for + // details. + // + struct swap_guard + { + swap_guard (object_statements& os, delayed_loads& dl) + : os_ (os), dl_ (dl) + { + dl_.swap (os_.delayed_); + } + + ~swap_guard () + { + os_.clear_delayed (); + dl_.swap (os_.delayed_); + } + + private: + object_statements& os_; + 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 mssql::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/mssql/object-statements.ixx> +#include <odb/mssql/object-statements.txx> + +#include <odb/post.hxx> + +#endif // ODB_MSSQL_OBJECT_STATEMENTS_HXX diff --git a/odb/mssql/object-statements.ixx b/odb/mssql/object-statements.ixx new file mode 100644 index 0000000..722bfd0 --- /dev/null +++ b/odb/mssql/object-statements.ixx @@ -0,0 +1,70 @@ +// file : odb/mssql/object-statements.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +namespace odb +{ + namespace mssql + { + // + // auto_unlock + // + inline object_statements_base::auto_unlock:: + auto_unlock (object_statements_base& s) + : s_ (s) + { + s_.unlock (); + } + + inline object_statements_base::auto_unlock:: + ~auto_unlock () + { + s_.lock (); + } + + // + // auto_lock + // + template <typename T> + inline object_statements<T>::auto_lock:: + auto_lock (object_statements& s) + : s_ (s) + { + if (!s_.locked ()) + { + s_.lock (); + locked_ = true; + } + else + locked_ = false; + } + + template <typename T> + inline object_statements<T>::auto_lock:: + ~auto_lock () + { + if (locked_) + { + s_.unlock (); + s_.clear_delayed (); + } + } + + template <typename T> + inline bool object_statements<T>::auto_lock:: + locked () const + { + return locked_; + } + + template <typename T> + inline void object_statements<T>::auto_lock:: + unlock () + { + assert (locked_); + s_.unlock (); + locked_ = false; + } + } +} diff --git a/odb/mssql/object-statements.txx b/odb/mssql/object-statements.txx new file mode 100644 index 0000000..ebdad67 --- /dev/null +++ b/odb/mssql/object-statements.txx @@ -0,0 +1,168 @@ +// file : odb/mssql/object-statements.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include <cstring> // std::memset + +#include <odb/session.hxx> +#include <odb/callback.hxx> +#include <odb/exceptions.hxx> + +#include <odb/mssql/connection.hxx> + +namespace odb +{ + namespace mssql + { + // + // optimistic_data + // + + template <typename T> + optimistic_data<T, true>:: + optimistic_data (bind* b) + : id_image_binding_ ( + b, + object_traits::id_column_count + + object_traits::managed_optimistic_column_count) + { + id_image_version_ = 0; + } + + // + // object_statements + // + + template <typename T> + object_statements<T>:: + ~object_statements () + { + } + + template <typename T> + object_statements<T>:: + object_statements (connection_type& conn) + : object_statements_base (conn), + container_statement_cache_ (conn), + select_image_binding_ (select_image_bind_, select_column_count), + insert_image_binding_ (insert_image_bind_, insert_column_count), + update_image_binding_ (update_image_bind_, + update_column_count + id_column_count + + managed_optimistic_column_count), + id_image_binding_ (update_image_bind_ + update_column_count, + id_column_count), + od_ (update_image_bind_ + update_column_count) + { + image_.version = 0; + select_image_version_ = 0; + insert_image_version_ = 0; + update_image_version_ = 0; + update_id_image_version_ = 0; + + id_image_.version = 0; + id_image_version_ = 0; + + //@@ TODO + // select_image_binding_.change_callback = image_.change_callback (); + + 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 object_statements<T>:: + load_delayed_ () + { + database& db (connection ().database ()); + + delayed_loads dls; + swap_guard sg (*this, dls); + + while (!dls.empty ()) + { + delayed_load l (dls.back ()); + typename object_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). + // + { + auto_unlock u (*this); + object_traits::callback (db, *l.obj, callback_event::post_load); + } + + g.release (); + } + } + + template <typename T> + void object_statements<T>:: + clear_delayed_ () + { + // Remove the objects from the session cache. + // + if (session::has_current ()) + { + for (typename delayed_loads::iterator i (delayed_.begin ()), + e (delayed_.end ()); i != e; ++i) + { + object_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; + + //@@ TODO + // 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/mssql/statement-cache.hxx b/odb/mssql/statement-cache.hxx new file mode 100644 index 0000000..4b2ae37 --- /dev/null +++ b/odb/mssql/statement-cache.hxx @@ -0,0 +1,87 @@ +// file : odb/mssql/statement-cache.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_MSSQL_STATEMENT_CACHE_HXX +#define ODB_MSSQL_STATEMENT_CACHE_HXX + +#include <odb/pre.hxx> + +#include <map> +#include <typeinfo> + +#include <odb/forward.hxx> + +#include <odb/mssql/version.hxx> +#include <odb/mssql/statements-base.hxx> +#include <odb/mssql/object-statements.hxx> +#include <odb/mssql/view-statements.hxx> + +#include <odb/details/shared-ptr.hxx> +#include <odb/details/type-info.hxx> + +#include <odb/mssql/details/export.hxx> + +namespace odb +{ + namespace mssql + { + class connection; + + class LIBODB_MSSQL_EXPORT statement_cache + { + public: + 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; + } + + 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; + } + + private: + typedef std::map<const std::type_info*, + details::shared_ptr<statements_base>, + details::type_info_comparator> map; + + connection& conn_; + map map_; + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_MSSQL_STATEMENT_CACHE_HXX diff --git a/odb/mssql/statements-base.cxx b/odb/mssql/statements-base.cxx new file mode 100644 index 0000000..0a99a08 --- /dev/null +++ b/odb/mssql/statements-base.cxx @@ -0,0 +1,17 @@ +// file : odb/mssql/statements-base.cxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include <odb/mssql/statements-base.hxx> + +namespace odb +{ + namespace mssql + { + statements_base:: + ~statements_base () + { + } + } +} diff --git a/odb/mssql/statements-base.hxx b/odb/mssql/statements-base.hxx new file mode 100644 index 0000000..b2ae55f --- /dev/null +++ b/odb/mssql/statements-base.hxx @@ -0,0 +1,51 @@ +// file : odb/mssql/statements-base.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_MSSQL_STATEMENTS_BASE_HXX +#define ODB_MSSQL_STATEMENTS_BASE_HXX + +#include <odb/pre.hxx> + +#include <odb/details/shared-ptr.hxx> + +#include <odb/mssql/version.hxx> +#include <odb/mssql/forward.hxx> // connection + +#include <odb/mssql/details/export.hxx> + +namespace odb +{ + namespace mssql + { + class LIBODB_MSSQL_EXPORT statements_base: public details::shared_base + { + public: + typedef mssql::connection connection_type; + + connection_type& + connection () + { + return conn_; + } + + public: + virtual + ~statements_base (); + + protected: + statements_base (connection_type& conn) + : conn_ (conn) + { + } + + protected: + connection_type& conn_; + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_MSSQL_STATEMENTS_BASE_HXX diff --git a/odb/mssql/view-statements.hxx b/odb/mssql/view-statements.hxx new file mode 100644 index 0000000..1e9cea6 --- /dev/null +++ b/odb/mssql/view-statements.hxx @@ -0,0 +1,83 @@ +// file : odb/mssql/view-statements.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#ifndef ODB_MSSQL_VIEW_STATEMENTS_HXX +#define ODB_MSSQL_VIEW_STATEMENTS_HXX + +#include <odb/pre.hxx> + +#include <cstddef> // std::size_t + +#include <odb/forward.hxx> +#include <odb/traits.hxx> + +#include <odb/mssql/mssql-types.hxx> +#include <odb/mssql/version.hxx> +#include <odb/mssql/statement.hxx> +#include <odb/mssql/statements-base.hxx> + +namespace odb +{ + namespace mssql + { + template <typename T> + class view_statements: public statements_base + { + public: + typedef T view_type; + typedef odb::view_traits<view_type> view_traits; + typedef typename view_traits::pointer_type pointer_type; + typedef typename view_traits::image_type image_type; + + public: + view_statements (connection_type&); + + virtual + ~view_statements (); + + // View image. + // + image_type& + image () + { + return image_; + } + + std::size_t + image_version () const + { + return image_version_; + } + + void + image_version (std::size_t v) + { + image_version_ = v; + } + + binding& + image_binding () + { + return image_binding_; + } + + private: + view_statements (const view_statements&); + view_statements& operator= (const view_statements&); + + private: + image_type image_; + std::size_t image_version_; + binding image_binding_; + bind image_bind_[view_traits::column_count]; + }; + } +} + +#include <odb/mssql/view-statements.txx> + +#include <odb/post.hxx> + +#endif // ODB_MSSQL_VIEW_STATEMENTS_HXX diff --git a/odb/mssql/view-statements.txx b/odb/mssql/view-statements.txx new file mode 100644 index 0000000..e4e47d8 --- /dev/null +++ b/odb/mssql/view-statements.txx @@ -0,0 +1,33 @@ +// file : odb/mssql/view-statements.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : ODB NCUEL; see accompanying LICENSE file + +#include <cstring> // std::memset + +namespace odb +{ + namespace mssql + { + template <typename T> + view_statements<T>:: + ~view_statements () + { + } + + template <typename T> + view_statements<T>:: + view_statements (connection_type& conn) + : statements_base (conn), + image_binding_ (image_bind_, view_traits::column_count) + { + image_.version = 0; + image_version_ = 0; + + //@@ TODO + // image_binding_.change_callback = image_.change_callback (); + + std::memset (image_bind_, 0, sizeof (image_bind_)); + } + } +} |