| connection.hxx | | connection.hxx | |
| // file : odb/pgsql/connection.hxx | | // file : odb/pgsql/connection.hxx | |
| // author : Constantin Michael <constantin@codesynthesis.com> | | // author : Constantin Michael <constantin@codesynthesis.com> | |
| // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC | | // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC | |
| // license : GNU GPL v2; see accompanying LICENSE file | | // license : GNU GPL v2; see accompanying LICENSE file | |
| | | | |
| #ifndef ODB_PGSQL_CONNECTION_HXX | | #ifndef ODB_PGSQL_CONNECTION_HXX | |
| #define ODB_PGSQL_CONNECTION_HXX | | #define ODB_PGSQL_CONNECTION_HXX | |
| | | | |
| #include <odb/pre.hxx> | | #include <odb/pre.hxx> | |
| | | | |
|
| #include <vector> | | | |
| #include <memory> // std::auto_ptr | | #include <memory> // std::auto_ptr | |
| | | | |
| #include <odb/forward.hxx> | | #include <odb/forward.hxx> | |
| #include <odb/connection.hxx> | | #include <odb/connection.hxx> | |
| | | | |
| #include <odb/details/shared-ptr.hxx> | | #include <odb/details/shared-ptr.hxx> | |
| | | | |
| #include <odb/pgsql/version.hxx> | | #include <odb/pgsql/version.hxx> | |
| #include <odb/pgsql/forward.hxx> | | #include <odb/pgsql/forward.hxx> | |
|
| | | #include <odb/pgsql/tracer.hxx> | |
| #include <odb/pgsql/transaction-impl.hxx> | | #include <odb/pgsql/transaction-impl.hxx> | |
| #include <odb/pgsql/auto-handle.hxx> | | #include <odb/pgsql/auto-handle.hxx> | |
| #include <odb/pgsql/pgsql-fwd.hxx> // PGconn | | #include <odb/pgsql/pgsql-fwd.hxx> // PGconn | |
| | | | |
| #include <odb/pgsql/details/export.hxx> | | #include <odb/pgsql/details/export.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace pgsql | | namespace pgsql | |
| { | | { | |
|
| class statement; | | | |
| class statement_cache; | | class statement_cache; | |
| | | | |
| class connection; | | class connection; | |
| typedef details::shared_ptr<connection> connection_ptr; | | typedef details::shared_ptr<connection> connection_ptr; | |
| | | | |
| class LIBODB_PGSQL_EXPORT connection: public odb::connection | | class LIBODB_PGSQL_EXPORT connection: public odb::connection | |
| { | | { | |
| public: | | public: | |
| typedef pgsql::statement_cache statement_cache_type; | | typedef pgsql::statement_cache statement_cache_type; | |
| typedef pgsql::database database_type; | | typedef pgsql::database database_type; | |
| | | | |
| skipping to change at line 65 | | skipping to change at line 64 | |
| public: | | public: | |
| virtual transaction_impl* | | virtual transaction_impl* | |
| begin (); | | begin (); | |
| | | | |
| public: | | public: | |
| using odb::connection::execute; | | using odb::connection::execute; | |
| | | | |
| virtual unsigned long long | | virtual unsigned long long | |
| execute (const char* statement, std::size_t length); | | execute (const char* statement, std::size_t length); | |
| | | | |
|
| | | // SQL statement tracing. | |
| | | // | |
| | | public: | |
| | | typedef pgsql::tracer tracer_type; | |
| | | | |
| | | void | |
| | | tracer (tracer_type& t) | |
| | | { | |
| | | odb::connection::tracer (t); | |
| | | } | |
| | | | |
| | | void | |
| | | tracer (tracer_type* t) | |
| | | { | |
| | | odb::connection::tracer (t); | |
| | | } | |
| | | | |
| | | using odb::connection::tracer; | |
| | | | |
| | | public: | |
| | | bool | |
| | | failed () const | |
| | | { | |
| | | return failed_; | |
| | | } | |
| | | | |
| | | void | |
| | | mark_failed () | |
| | | { | |
| | | failed_ = true; | |
| | | } | |
| | | | |
| public: | | public: | |
| PGconn* | | PGconn* | |
| handle () | | handle () | |
| { | | { | |
| return handle_; | | return handle_; | |
| } | | } | |
| | | | |
| statement_cache_type& | | statement_cache_type& | |
| statement_cache () | | statement_cache () | |
| { | | { | |
| | | | |
| skipping to change at line 93 | | skipping to change at line 124 | |
| void | | void | |
| init (); | | init (); | |
| | | | |
| private: | | private: | |
| // Needed to break the circular connection-database dependency | | // Needed to break the circular connection-database dependency | |
| // (odb::connection has the odb::database member). | | // (odb::connection has the odb::database member). | |
| // | | // | |
| database_type& db_; | | database_type& db_; | |
| | | | |
| auto_handle<PGconn> handle_; | | auto_handle<PGconn> handle_; | |
|
| | | bool failed_; | |
| | | | |
| // Keep statement_cache_ after handle_ so that it is destroyed before | | // Keep statement_cache_ after handle_ so that it is destroyed before | |
| // the connection is closed. | | // the connection is closed. | |
| // | | // | |
| std::auto_ptr<statement_cache_type> statement_cache_; | | std::auto_ptr<statement_cache_type> statement_cache_; | |
| }; | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
End of changes. 5 change blocks. |
| 2 lines changed or deleted | | 34 lines changed or added | |
|
| object-result.txx | | object-result.txx | |
| | | | |
| skipping to change at line 14 | | skipping to change at line 14 | |
| // license : GNU GPL v2; see accompanying LICENSE file | | // license : GNU GPL v2; see accompanying LICENSE file | |
| | | | |
| #include <odb/callback.hxx> | | #include <odb/callback.hxx> | |
| | | | |
| #include <odb/pgsql/object-statements.hxx> | | #include <odb/pgsql/object-statements.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace pgsql | | namespace pgsql | |
| { | | { | |
|
| | | // | |
| | | // object_result_impl | |
| | | // | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| result_impl<T, class_object>:: | | object_result_impl<T>:: | |
| ~result_impl () | | ~object_result_impl () | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| result_impl<T, class_object>:: | | object_result_impl<T>:: | |
| result_impl (const query&, | | object_result_impl (const query&, | |
| details::shared_ptr<select_statement> statement, | | details::shared_ptr<select_statement> statement, | |
| object_statements<object_type>& statements) | | object_statements<object_type>& statements) | |
| : base_type (statements.connection ().database ()), | | : base_type (statements.connection ().database ()), | |
| statement_ (statement), | | statement_ (statement), | |
| statements_ (statements) | | statements_ (statements) | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl<T>:: | |
| load (object_type& obj) | | load (object_type& obj, bool fetch) | |
| { | | { | |
|
| load_image (); | | if (fetch) | |
| | | load_image (); | |
| | | | |
| // This is a top-level call so the statements cannot be locked. | | // This is a top-level call so the statements cannot be locked. | |
| // | | // | |
| assert (!statements_.locked ()); | | assert (!statements_.locked ()); | |
| typename object_statements<object_type>::auto_lock l (statements_); | | typename object_statements<object_type>::auto_lock l (statements_); | |
| | | | |
| odb::database& db (this->database ()); | | odb::database& db (this->database ()); | |
| object_traits::callback (db, obj, callback_event::pre_load); | | object_traits::callback (db, obj, callback_event::pre_load); | |
| | | | |
| typename object_traits::image_type& i (statements_.image ()); | | typename object_traits::image_type& i (statements_.image ()); | |
| | | | |
| skipping to change at line 69 | | skipping to change at line 74 | |
| idb.version++; | | idb.version++; | |
| } | | } | |
| | | | |
| object_traits::load_ (statements_, obj); | | object_traits::load_ (statements_, obj); | |
| statements_.load_delayed (); | | statements_.load_delayed (); | |
| l.unlock (); | | l.unlock (); | |
| object_traits::callback (db, obj, callback_event::post_load); | | object_traits::callback (db, obj, callback_event::post_load); | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| typename result_impl<T, class_object>::id_type | | typename object_result_impl<T>::id_type | |
| result_impl<T, class_object>:: | | object_result_impl<T>:: | |
| load_id () | | load_id () | |
| { | | { | |
| load_image (); | | load_image (); | |
| return object_traits::id (statements_.image ()); | | return object_traits::id (statements_.image ()); | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl<T>:: | |
| next () | | next () | |
| { | | { | |
| this->current (pointer_type ()); | | this->current (pointer_type ()); | |
| | | | |
| if (!statement_->next ()) | | if (!statement_->next ()) | |
| this->end_ = true; | | this->end_ = true; | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl<T>:: | |
| load_image () | | load_image () | |
| { | | { | |
| // The image can grow between calls to load() as a result of other | | // The image can grow between calls to load() as a result of other | |
| // statements execution. | | // statements execution. | |
| // | | // | |
| typename object_traits::image_type& im (statements_.image ()); | | typename object_traits::image_type& im (statements_.image ()); | |
| | | | |
|
| if (im.version != statements_.out_image_version ()) | | if (im.version != statements_.select_image_version ()) | |
| { | | { | |
|
| binding& b (statements_.out_image_binding ()); | | binding& b (statements_.select_image_binding ()); | |
| object_traits::bind (b.bind, im, true); | | object_traits::bind (b.bind, im, statement_select); | |
| statements_.out_image_version (im.version); | | statements_.select_image_version (im.version); | |
| b.version++; | | b.version++; | |
| } | | } | |
| | | | |
| select_statement::result r (statement_->load ()); | | select_statement::result r (statement_->load ()); | |
| | | | |
| if (r == select_statement::truncated) | | if (r == select_statement::truncated) | |
| { | | { | |
|
| if (object_traits::grow (im, statements_.out_image_truncated ())) | | if (object_traits::grow (im, statements_.select_image_truncated ())
) | |
| im.version++; | | im.version++; | |
| | | | |
|
| if (im.version != statements_.out_image_version ()) | | if (im.version != statements_.select_image_version ()) | |
| { | | { | |
|
| binding& b (statements_.out_image_binding ()); | | binding& b (statements_.select_image_binding ()); | |
| object_traits::bind (b.bind, im, true); | | object_traits::bind (b.bind, im, statement_select); | |
| statements_.out_image_version (im.version); | | statements_.select_image_version (im.version); | |
| b.version++; | | b.version++; | |
| statement_->reload (); | | statement_->reload (); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl<T>:: | |
| | | cache () | |
| | | { | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | std::size_t object_result_impl<T>:: | |
| | | size () | |
| | | { | |
| | | return statement_->result_size (); | |
| | | } | |
| | | | |
| | | // | |
| | | // object_result_impl_no_id | |
| | | // | |
| | | | |
| | | template <typename T> | |
| | | object_result_impl_no_id<T>:: | |
| | | ~object_result_impl_no_id () | |
| | | { | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | object_result_impl_no_id<T>:: | |
| | | object_result_impl_no_id (const query&, | |
| | | details::shared_ptr<select_statement> stateme | |
| | | nt, | |
| | | object_statements_no_id<object_type>& stateme | |
| | | nts) | |
| | | : base_type (statements.connection ().database ()), | |
| | | statement_ (statement), | |
| | | statements_ (statements) | |
| | | { | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl_no_id<T>:: | |
| | | load (object_type& obj) | |
| | | { | |
| | | // The image can grow between calls to load() as a result of other | |
| | | // statements execution. | |
| | | // | |
| | | typename object_traits::image_type& im (statements_.image ()); | |
| | | | |
| | | if (im.version != statements_.select_image_version ()) | |
| | | { | |
| | | binding& b (statements_.select_image_binding ()); | |
| | | object_traits::bind (b.bind, im, statement_select); | |
| | | statements_.select_image_version (im.version); | |
| | | b.version++; | |
| | | } | |
| | | | |
| | | select_statement::result r (statement_->load ()); | |
| | | | |
| | | if (r == select_statement::truncated) | |
| | | { | |
| | | if (object_traits::grow (im, statements_.select_image_truncated ()) | |
| | | ) | |
| | | im.version++; | |
| | | | |
| | | if (im.version != statements_.select_image_version ()) | |
| | | { | |
| | | binding& b (statements_.select_image_binding ()); | |
| | | object_traits::bind (b.bind, im, statement_select); | |
| | | statements_.select_image_version (im.version); | |
| | | b.version++; | |
| | | statement_->reload (); | |
| | | } | |
| | | } | |
| | | | |
| | | odb::database& db (this->database ()); | |
| | | | |
| | | object_traits::callback (db, obj, callback_event::pre_load); | |
| | | object_traits::init (obj, im, db); | |
| | | object_traits::callback (db, obj, callback_event::post_load); | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl_no_id<T>:: | |
| | | next () | |
| | | { | |
| | | this->current (pointer_type ()); | |
| | | | |
| | | if (!statement_->next ()) | |
| | | this->end_ = true; | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl_no_id<T>:: | |
| cache () | | cache () | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| std::size_t result_impl<T, class_object>:: | | std::size_t object_result_impl_no_id<T>:: | |
| size () | | size () | |
| { | | { | |
| return statement_->result_size (); | | return statement_->result_size (); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 15 change blocks. |
| 24 lines changed or deleted | | 117 lines changed or added | |
|
| object-statements.hxx | | object-statements.hxx | |
| | | | |
| skipping to change at line 32 | | skipping to change at line 32 | |
| #include <odb/pgsql/binding.hxx> | | #include <odb/pgsql/binding.hxx> | |
| #include <odb/pgsql/statement.hxx> | | #include <odb/pgsql/statement.hxx> | |
| #include <odb/pgsql/statements-base.hxx> | | #include <odb/pgsql/statements-base.hxx> | |
| | | | |
| #include <odb/pgsql/details/export.hxx> | | #include <odb/pgsql/details/export.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace pgsql | | namespace pgsql | |
| { | | { | |
|
| | | 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_PGSQL_EXPORT object_statements_base: public statements_bas
e | | class LIBODB_PGSQL_EXPORT object_statements_base: public statements_bas
e | |
| { | | { | |
| public: | | public: | |
| // Locking. | | // Locking. | |
| // | | // | |
| void | | void | |
| lock () | | lock () | |
| { | | { | |
| assert (!locked_); | | assert (!locked_); | |
| locked_ = true; | | locked_ = true; | |
| | | | |
| skipping to change at line 87 | | skipping to change at line 109 | |
| auto_unlock& operator= (const auto_unlock&); | | auto_unlock& operator= (const auto_unlock&); | |
| | | | |
| private: | | private: | |
| object_statements_base& s_; | | object_statements_base& s_; | |
| }; | | }; | |
| | | | |
| protected: | | protected: | |
| bool locked_; | | 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*, char** nv, int* nl, int* nf); | |
| | | | |
| | | // The id + optimistic column binding. | |
| | | // | |
| | | std::size_t id_image_version_; | |
| | | binding id_image_binding_; | |
| | | native_binding id_image_native_binding_; | |
| | | | |
| | | details::shared_ptr<delete_statement> erase_; | |
| | | }; | |
| | | | |
| | | template <typename T> | |
| | | struct optimistic_data<T, false> | |
| | | { | |
| | | optimistic_data (bind*, char**, int*, int*) {} | |
| | | }; | |
| | | | |
| template <typename T> | | template <typename T> | |
| class object_statements: public object_statements_base | | class object_statements: public object_statements_base | |
| { | | { | |
| public: | | public: | |
| typedef T object_type; | | typedef T object_type; | |
| typedef odb::object_traits<object_type> object_traits; | | typedef odb::object_traits<object_type> object_traits; | |
| typedef typename object_traits::id_type id_type; | | typedef typename object_traits::id_type id_type; | |
| typedef typename object_traits::pointer_type pointer_type; | | typedef typename object_traits::pointer_type pointer_type; | |
| typedef typename object_traits::image_type image_type; | | typedef typename object_traits::image_type image_type; | |
| typedef typename object_traits::id_image_type id_image_type; | | typedef typename object_traits::id_image_type id_image_type; | |
| | | | |
| typedef pointer_cache_traits<pointer_type> object_cache_traits; | | typedef pointer_cache_traits<pointer_type> object_cache_traits; | |
| | | | |
| typedef | | typedef | |
| typename object_traits::container_statement_cache_type | | typename object_traits::container_statement_cache_type | |
| container_statement_cache_type; | | container_statement_cache_type; | |
| | | | |
|
| typedef pgsql::insert_statement persist_statement_type; | | typedef pgsql::insert_statement insert_statement_type; | |
| typedef pgsql::select_statement find_statement_type; | | typedef pgsql::select_statement select_statement_type; | |
| typedef pgsql::update_statement update_statement_type; | | typedef pgsql::update_statement update_statement_type; | |
|
| typedef pgsql::delete_statement erase_statement_type; | | typedef pgsql::delete_statement delete_statement_type; | |
| | | | |
| // Automatic lock. | | // Automatic lock. | |
| // | | // | |
| struct auto_lock | | struct auto_lock | |
| { | | { | |
| // Lock the statements unless they are already locked in which | | // Lock the statements unless they are already locked in which | |
| // case subsequent calls to locked() will return false. | | // case subsequent calls to locked() will return false. | |
| // | | // | |
| auto_lock (object_statements&); | | auto_lock (object_statements&); | |
| | | | |
| | | | |
| skipping to change at line 179 | | skipping to change at line 227 | |
| void | | void | |
| clear_delayed () | | clear_delayed () | |
| { | | { | |
| if (!delayed_.empty ()) | | if (!delayed_.empty ()) | |
| clear_delayed_ (); | | clear_delayed_ (); | |
| } | | } | |
| | | | |
| // Object image. | | // Object image. | |
| // | | // | |
| image_type& | | image_type& | |
|
| image () | | image () {return image_;} | |
| { | | | |
| return image_; | | | |
| } | | | |
| | | | |
|
| | | // Insert binding. | |
| | | // | |
| std::size_t | | std::size_t | |
|
| in_image_version () const | | insert_image_version () const { return insert_image_version_;} | |
| { | | | |
| return in_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 | | std::size_t | |
|
| out_image_version () const | | update_image_version () const { return update_image_version_;} | |
| { | | | |
| return out_image_version_; | | | |
| } | | | |
| | | | |
| void | | void | |
|
| in_image_version (std::size_t v) | | update_image_version (std::size_t v) {update_image_version_ = v;} | |
| { | | | |
| in_image_version_ = v; | | std::size_t | |
| } | | update_id_image_version () const { return update_id_image_version_;} | |
| | | | |
| void | | void | |
|
| out_image_version (std::size_t v) | | update_id_image_version (std::size_t v) {update_id_image_version_ = v | |
| { | | ;} | |
| out_image_version_ = v; | | | |
| } | | | |
| | | | |
| binding& | | binding& | |
|
| in_image_binding () | | update_image_binding () {return update_image_binding_;} | |
| { | | | |
| return in_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& | | binding& | |
|
| out_image_binding () | | select_image_binding () {return select_image_binding_;} | |
| { | | | |
| return out_image_binding_; | | | |
| } | | | |
| | | | |
| bool* | | bool* | |
|
| out_image_truncated () | | select_image_truncated () {return select_image_truncated_;} | |
| { | | | |
| return out_image_truncated_; | | | |
| } | | | |
| | | | |
|
| // Object id image. | | // Object id image and binding. | |
| // | | // | |
| id_image_type& | | id_image_type& | |
|
| id_image () | | id_image () {return id_image_;} | |
| { | | | |
| return id_image_; | | | |
| } | | | |
| | | | |
| std::size_t | | std::size_t | |
|
| id_image_version () const | | id_image_version () const {return id_image_version_;} | |
| { | | | |
| return id_image_version_; | | | |
| } | | | |
| | | | |
| void | | void | |
|
| id_image_version (std::size_t v) | | id_image_version (std::size_t v) {id_image_version_ = v;} | |
| { | | | |
| id_image_version_ = v; | | | |
| } | | | |
| | | | |
| binding& | | binding& | |
|
| id_image_binding () | | id_image_binding () {return 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. | | // Statements. | |
| // | | // | |
|
| persist_statement_type& | | insert_statement_type& | |
| persist_statement () | | persist_statement () | |
| { | | { | |
| if (persist_ == 0) | | if (persist_ == 0) | |
| { | | { | |
| persist_.reset ( | | persist_.reset ( | |
|
| new (details::shared) persist_statement_type ( | | new (details::shared) insert_statement_type ( | |
| conn_, | | conn_, | |
| object_traits::persist_statement_name, | | object_traits::persist_statement_name, | |
| object_traits::persist_statement, | | object_traits::persist_statement, | |
| object_traits::persist_statement_types, | | object_traits::persist_statement_types, | |
|
| object_traits::in_column_count, | | insert_column_count, | |
| in_image_binding_, | | insert_image_binding_, | |
| in_image_native_binding_)); | | insert_image_native_binding_, | |
| | | object_traits::auto_id, | |
| | | false)); | |
| } | | } | |
| | | | |
| return *persist_; | | return *persist_; | |
| } | | } | |
| | | | |
|
| find_statement_type& | | select_statement_type& | |
| find_statement () | | find_statement () | |
| { | | { | |
| if (find_ == 0) | | if (find_ == 0) | |
| { | | { | |
| find_.reset ( | | find_.reset ( | |
|
| new (details::shared) find_statement_type ( | | new (details::shared) select_statement_type ( | |
| conn_, | | conn_, | |
| object_traits::find_statement_name, | | object_traits::find_statement_name, | |
| object_traits::find_statement, | | object_traits::find_statement, | |
| object_traits::find_statement_types, | | object_traits::find_statement_types, | |
|
| 1, | | id_column_count, | |
| id_image_binding_, | | id_image_binding_, | |
| id_image_native_binding_, | | id_image_native_binding_, | |
|
| out_image_binding_)); | | select_image_binding_, | |
| | | false)); | |
| } | | } | |
| | | | |
| return *find_; | | return *find_; | |
| } | | } | |
| | | | |
| update_statement_type& | | update_statement_type& | |
| update_statement () | | update_statement () | |
| { | | { | |
| if (update_ == 0) | | if (update_ == 0) | |
| { | | { | |
| update_.reset ( | | update_.reset ( | |
| new (details::shared) update_statement_type ( | | new (details::shared) update_statement_type ( | |
| conn_, | | conn_, | |
| object_traits::update_statement_name, | | object_traits::update_statement_name, | |
| object_traits::update_statement, | | object_traits::update_statement, | |
| object_traits::update_statement_types, | | object_traits::update_statement_types, | |
|
| object_traits::in_column_count + 1, | | update_column_count + id_column_count, | |
| id_image_binding_, | | update_image_binding_, | |
| id_image_native_binding_, | | update_image_native_binding_, | |
| in_image_binding_, | | false)); | |
| in_image_native_binding_)); | | | |
| } | | } | |
| | | | |
| return *update_; | | return *update_; | |
| } | | } | |
| | | | |
|
| erase_statement_type& | | delete_statement_type& | |
| erase_statement () | | erase_statement () | |
| { | | { | |
| if (erase_ == 0) | | if (erase_ == 0) | |
| { | | { | |
| erase_.reset ( | | erase_.reset ( | |
|
| new (details::shared) erase_statement_type ( | | new (details::shared) delete_statement_type ( | |
| conn_, | | conn_, | |
| object_traits::erase_statement_name, | | object_traits::erase_statement_name, | |
| object_traits::erase_statement, | | object_traits::erase_statement, | |
| object_traits::erase_statement_types, | | object_traits::erase_statement_types, | |
|
| 1, | | id_column_count, | |
| id_image_binding_, | | id_image_binding_, | |
|
| id_image_native_binding_)); | | id_image_native_binding_, | |
| | | false)); | |
| } | | } | |
| | | | |
| return *erase_; | | 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_name, | |
| | | object_traits::optimistic_erase_statement, | |
| | | object_traits::optimistic_erase_statement_types, | |
| | | id_column_count + managed_optimistic_column_count, | |
| | | od_.id_image_binding_, | |
| | | od_.id_image_native_binding_, | |
| | | false)); | |
| | | } | |
| | | | |
| | | return *od_.erase_; | |
| | | } | |
| | | | |
| // Container statement cache. | | // Container statement cache. | |
| // | | // | |
| container_statement_cache_type& | | container_statement_cache_type& | |
| container_statment_cache () | | container_statment_cache () | |
| { | | { | |
| return container_statement_cache_; | | return container_statement_cache_; | |
| } | | } | |
| | | | |
| private: | | private: | |
| object_statements (const object_statements&); | | object_statements (const object_statements&); | |
| object_statements& operator= (const object_statements&); | | object_statements& operator= (const object_statements&); | |
| | | | |
| private: | | private: | |
| void | | void | |
| load_delayed_ (); | | load_delayed_ (); | |
| | | | |
| void | | void | |
| clear_delayed_ (); | | clear_delayed_ (); | |
| | | | |
| private: | | private: | |
|
| | | // select = total | |
| | | // insert = total - inverse - managed_optimistic | |
| | | // update = total - inverse - managed_optimistic - id - readonly | |
| | | // | |
| | | 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; | |
| | | | |
| | | static const std::size_t update_column_count = insert_column_count - | |
| | | object_traits::id_column_count - object_traits::readonly_column_cou | |
| | | nt; | |
| | | | |
| | | 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; | |
| | | | |
| | | private: | |
| container_statement_cache_type container_statement_cache_; | | container_statement_cache_type container_statement_cache_; | |
| | | | |
| image_type image_; | | image_type image_; | |
| | | | |
|
| // In (send) binding. The last element is the id parameter. | | // Select binding. | |
| // | | // | |
|
| std::size_t in_image_version_; | | std::size_t select_image_version_; | |
| binding in_image_binding_; | | binding select_image_binding_; | |
| bind in_image_bind_[object_traits::in_column_count + 1]; | | bind select_image_bind_[select_column_count]; | |
| native_binding in_image_native_binding_; | | bool select_image_truncated_[select_column_count]; | |
| char* in_image_values_[object_traits::in_column_count + 1]; | | | |
| int in_image_lengths_[object_traits::in_column_count + 1]; | | // Insert binding. | |
| int in_image_formats_[object_traits::in_column_count + 1]; | | // | |
| | | std::size_t insert_image_version_; | |
| // Out (receive) binding. | | binding insert_image_binding_; | |
| // | | bind insert_image_bind_[insert_column_count]; | |
| std::size_t out_image_version_; | | native_binding insert_image_native_binding_; | |
| binding out_image_binding_; | | char* insert_image_values_[insert_column_count]; | |
| bind out_image_bind_[object_traits::out_column_count]; | | int insert_image_lengths_[insert_column_count]; | |
| bool out_image_truncated_[object_traits::out_column_count]; | | int insert_image_formats_[insert_column_count]; | |
| | | | |
| | | // 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]; | |
| | | native_binding update_image_native_binding_; | |
| | | char* update_image_values_[update_column_count + id_column_count + | |
| | | managed_optimistic_column_count]; | |
| | | int update_image_lengths_[update_column_count + id_column_count + | |
| | | managed_optimistic_column_count]; | |
| | | int update_image_formats_[update_column_count + id_column_count + | |
| | | managed_optimistic_column_count]; | |
| | | | |
|
| // Id image binding (only in). | | // Id image binding (only used as a parameter). Uses the suffix in | |
| | | // the update bind. | |
| // | | // | |
| id_image_type id_image_; | | id_image_type id_image_; | |
| std::size_t id_image_version_; | | std::size_t id_image_version_; | |
| binding id_image_binding_; | | binding id_image_binding_; | |
| native_binding id_image_native_binding_; | | native_binding id_image_native_binding_; | |
| | | | |
|
| details::shared_ptr<persist_statement_type> persist_; | | // Extra data for objects with optimistic concurrency support. | |
| details::shared_ptr<find_statement_type> find_; | | // | |
| | | 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<update_statement_type> update_; | |
|
| details::shared_ptr<erase_statement_type> erase_; | | details::shared_ptr<delete_statement_type> erase_; | |
| | | | |
| // Delayed loading. | | // Delayed loading. | |
| // | | // | |
| struct delayed_load | | struct delayed_load | |
| { | | { | |
| typedef typename object_cache_traits::position_type position_type; | | typedef typename object_cache_traits::position_type position_type; | |
| | | | |
| delayed_load () {} | | delayed_load () {} | |
| delayed_load (const id_type& i, object_type& o, const position_type
& p) | | delayed_load (const id_type& i, object_type& o, const position_type
& p) | |
| : id (i), obj (&o), pos (p) | | : id (i), obj (&o), pos (p) | |
| | | | |
| skipping to change at line 428 | | skipping to change at line 542 | |
| { | | { | |
| os_.clear_delayed (); | | os_.clear_delayed (); | |
| dl_.swap (os_.delayed_); | | dl_.swap (os_.delayed_); | |
| } | | } | |
| | | | |
| private: | | private: | |
| object_statements& os_; | | object_statements& os_; | |
| delayed_loads& dl_; | | 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 pgsql::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_;} | |
| | | | |
| | | bool* | |
| | | select_image_truncated () {return select_image_truncated_;} | |
| | | | |
| | | // Statements. | |
| | | // | |
| | | insert_statement_type& | |
| | | persist_statement () | |
| | | { | |
| | | if (persist_ == 0) | |
| | | { | |
| | | persist_.reset ( | |
| | | new (details::shared) insert_statement_type ( | |
| | | conn_, | |
| | | object_traits::persist_statement_name, | |
| | | object_traits::persist_statement, | |
| | | object_traits::persist_statement_types, | |
| | | insert_column_count, | |
| | | insert_image_binding_, | |
| | | insert_image_native_binding_, | |
| | | false, | |
| | | 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]; | |
| | | bool select_image_truncated_[select_column_count]; | |
| | | | |
| | | // Insert binding. | |
| | | // | |
| | | std::size_t insert_image_version_; | |
| | | binding insert_image_binding_; | |
| | | bind insert_image_bind_[insert_column_count]; | |
| | | native_binding insert_image_native_binding_; | |
| | | char* insert_image_values_[insert_column_count]; | |
| | | int insert_image_lengths_[insert_column_count]; | |
| | | int insert_image_formats_[insert_column_count]; | |
| | | | |
| | | details::shared_ptr<insert_statement_type> persist_; | |
| | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/pgsql/object-statements.ixx> | | #include <odb/pgsql/object-statements.ixx> | |
| #include <odb/pgsql/object-statements.txx> | | #include <odb/pgsql/object-statements.txx> | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
| #endif // ODB_PGSQL_OBJECT_STATEMENTS_HXX | | #endif // ODB_PGSQL_OBJECT_STATEMENTS_HXX | |
| | | | |
End of changes. 39 change blocks. |
| 89 lines changed or deleted | | 317 lines changed or added | |
|
| object-statements.txx | | object-statements.txx | |
| | | | |
| skipping to change at line 19 | | skipping to change at line 19 | |
| #include <odb/session.hxx> | | #include <odb/session.hxx> | |
| #include <odb/callback.hxx> | | #include <odb/callback.hxx> | |
| #include <odb/exceptions.hxx> | | #include <odb/exceptions.hxx> | |
| | | | |
| #include <odb/pgsql/connection.hxx> | | #include <odb/pgsql/connection.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace pgsql | | namespace pgsql | |
| { | | { | |
|
| | | // | |
| | | // optimistic_data | |
| | | // | |
| | | | |
| | | template <typename T> | |
| | | optimistic_data<T, true>:: | |
| | | optimistic_data (bind* b, char** nv, int* nl, int* nf) | |
| | | : id_image_binding_ ( | |
| | | b, | |
| | | object_traits::id_column_count + | |
| | | object_traits::managed_optimistic_column_count), | |
| | | id_image_native_binding_ ( | |
| | | nv, nl, nf, | |
| | | object_traits::id_column_count + | |
| | | object_traits::managed_optimistic_column_count) | |
| | | { | |
| | | id_image_version_ = 0; | |
| | | } | |
| | | | |
| | | // | |
| | | // object_statements | |
| | | // | |
| | | | |
| template <typename T> | | template <typename T> | |
| object_statements<T>:: | | object_statements<T>:: | |
| ~object_statements () | | ~object_statements () | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
| object_statements<T>:: | | object_statements<T>:: | |
| object_statements (connection_type& conn) | | object_statements (connection_type& conn) | |
| : object_statements_base (conn), | | : object_statements_base (conn), | |
| container_statement_cache_ (conn), | | container_statement_cache_ (conn), | |
|
| in_image_binding_ (in_image_bind_, object_traits::in_column_count | | // select | |
| ), | | select_image_binding_ (select_image_bind_, select_column_count), | |
| in_image_native_binding_ (in_image_values_, | | // insert | |
| in_image_lengths_, | | insert_image_binding_ (insert_image_bind_, insert_column_count), | |
| in_image_formats_, | | insert_image_native_binding_ (insert_image_values_, | |
| object_traits::in_column_count), | | insert_image_lengths_, | |
| out_image_binding_ (out_image_bind_, | | insert_image_formats_, | |
| object_traits::out_column_count), | | insert_column_count), | |
| id_image_binding_ (in_image_bind_ + object_traits::in_column_coun | | // update | |
| t, | | update_image_binding_ (update_image_bind_, | |
| 1), | | update_column_count + id_column_count + | |
| | | managed_optimistic_column_count), | |
| | | update_image_native_binding_ (update_image_values_, | |
| | | update_image_lengths_, | |
| | | update_image_formats_, | |
| | | update_column_count + id_column_cou | |
| | | nt + | |
| | | managed_optimistic_column_count), | |
| | | // id | |
| | | id_image_binding_ (update_image_bind_ + update_column_count, | |
| | | id_column_count), | |
| id_image_native_binding_ ( | | id_image_native_binding_ ( | |
|
| in_image_values_ + object_traits::in_column_count, | | update_image_values_ + update_column_count, | |
| in_image_lengths_ + object_traits::in_column_count, | | update_image_lengths_ + update_column_count, | |
| in_image_formats_ + object_traits::in_column_count, 1) | | update_image_formats_ + update_column_count, | |
| | | id_column_count), | |
| | | // optimistic data | |
| | | od_ (update_image_bind_ + update_column_count, | |
| | | update_image_values_ + update_column_count, | |
| | | update_image_lengths_ + update_column_count, | |
| | | update_image_formats_ + update_column_count) | |
| { | | { | |
| image_.version = 0; | | image_.version = 0; | |
|
| in_image_version_ = 0; | | select_image_version_ = 0; | |
| out_image_version_ = 0; | | insert_image_version_ = 0; | |
| | | update_image_version_ = 0; | |
| | | update_id_image_version_ = 0; | |
| | | | |
| id_image_.version = 0; | | id_image_.version = 0; | |
| id_image_version_ = 0; | | id_image_version_ = 0; | |
| | | | |
|
| std::memset (in_image_bind_, 0, sizeof (in_image_bind_)); | | std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_)); | |
| std::memset (out_image_bind_, 0, sizeof (out_image_bind_)); | | std::memset (update_image_bind_, 0, sizeof (update_image_bind_)); | |
| std::memset (out_image_truncated_, 0, sizeof (out_image_truncated_)); | | std::memset (select_image_bind_, 0, sizeof (select_image_bind_)); | |
| | | std::memset ( | |
| | | select_image_truncated_, 0, sizeof (select_image_truncated_)); | |
| | | | |
|
| for (std::size_t i (0); i < object_traits::out_column_count; ++i) | | for (std::size_t i (0); i < select_column_count; ++i) | |
| out_image_bind_[i].truncated = out_image_truncated_ + i; | | select_image_bind_[i].truncated = select_image_truncated_ + i; | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
| void object_statements<T>:: | | void object_statements<T>:: | |
| load_delayed_ () | | load_delayed_ () | |
| { | | { | |
| database& db (connection ().database ()); | | database& db (connection ().database ()); | |
| | | | |
| delayed_loads dls; | | delayed_loads dls; | |
| swap_guard sg (*this, dls); | | swap_guard sg (*this, dls); | |
| | | | |
| skipping to change at line 123 | | skipping to change at line 167 | |
| { | | { | |
| for (typename delayed_loads::iterator i (delayed_.begin ()), | | for (typename delayed_loads::iterator i (delayed_.begin ()), | |
| e (delayed_.end ()); i != e; ++i) | | e (delayed_.end ()); i != e; ++i) | |
| { | | { | |
| object_cache_traits::erase (i->pos); | | object_cache_traits::erase (i->pos); | |
| } | | } | |
| } | | } | |
| | | | |
| delayed_.clear (); | | 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 | |
| | | select_image_binding_ (select_image_bind_, select_column_count), | |
| | | // insert | |
| | | insert_image_binding_ (insert_image_bind_, insert_column_count), | |
| | | insert_image_native_binding_ (insert_image_values_, | |
| | | insert_image_lengths_, | |
| | | insert_image_formats_, | |
| | | insert_column_count) | |
| | | { | |
| | | image_.version = 0; | |
| | | select_image_version_ = 0; | |
| | | insert_image_version_ = 0; | |
| | | | |
| | | std::memset (insert_image_bind_, 0, sizeof (insert_image_bind_)); | |
| | | std::memset (select_image_bind_, 0, sizeof (select_image_bind_)); | |
| | | std::memset ( | |
| | | select_image_truncated_, 0, sizeof (select_image_truncated_)); | |
| | | | |
| | | for (std::size_t i (0); i < select_column_count; ++i) | |
| | | select_image_bind_[i].truncated = select_image_truncated_ + i; | |
| | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 7 change blocks. |
| 21 lines changed or deleted | | 100 lines changed or added | |
|
| statement.hxx | | statement.hxx | |
| | | | |
| skipping to change at line 14 | | skipping to change at line 14 | |
| // license : GNU GPL v2; see accompanying LICENSE file | | // license : GNU GPL v2; see accompanying LICENSE file | |
| | | | |
| #ifndef ODB_PGSQL_STATEMENT_HXX | | #ifndef ODB_PGSQL_STATEMENT_HXX | |
| #define ODB_PGSQL_STATEMENT_HXX | | #define ODB_PGSQL_STATEMENT_HXX | |
| | | | |
| #include <odb/pre.hxx> | | #include <odb/pre.hxx> | |
| | | | |
| #include <string> | | #include <string> | |
| #include <cstddef> // std::size_t | | #include <cstddef> // std::size_t | |
| | | | |
|
| #include <odb/details/shared-ptr.hxx> | | #include <odb/forward.hxx> | |
| | | #include <odb/statement.hxx> | |
| | | | |
| #include <odb/pgsql/version.hxx> | | #include <odb/pgsql/version.hxx> | |
| #include <odb/pgsql/binding.hxx> | | #include <odb/pgsql/binding.hxx> | |
| #include <odb/pgsql/pgsql-fwd.hxx> // PGresult | | #include <odb/pgsql/pgsql-fwd.hxx> // PGresult | |
| #include <odb/pgsql/auto-handle.hxx> | | #include <odb/pgsql/auto-handle.hxx> | |
| | | | |
| #include <odb/pgsql/details/export.hxx> | | #include <odb/pgsql/details/export.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace pgsql | | namespace pgsql | |
| { | | { | |
| class connection; | | class connection; | |
| | | | |
|
| class LIBODB_PGSQL_EXPORT statement: public details::shared_base | | class LIBODB_PGSQL_EXPORT statement: public odb::statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~statement () = 0; | | ~statement () = 0; | |
| | | | |
|
| | | const char* | |
| | | name () const | |
| | | { | |
| | | return name_; | |
| | | } | |
| | | | |
| | | virtual const char* | |
| | | text () const; | |
| | | | |
| void | | void | |
| deallocate (); | | deallocate (); | |
| | | | |
| // Adapt an ODB binding to a native PostgreSQL parameter binding. | | // Adapt an ODB binding to a native PostgreSQL parameter binding. | |
| // | | // | |
| static void | | static void | |
| bind_param (native_binding&, const binding&); | | bind_param (native_binding&, const binding&); | |
| | | | |
| // Populate an ODB binding given a PostgreSQL result. If the truncate
d | | // Populate an ODB binding given a PostgreSQL result. If the truncate
d | |
| // argument is true, then only truncated columns are extracted. Retur
n | | // argument is true, then only truncated columns are extracted. Retur
n | |
| | | | |
| skipping to change at line 58 | | skipping to change at line 68 | |
| static bool | | static bool | |
| bind_result (bind*, | | bind_result (bind*, | |
| std::size_t count, | | std::size_t count, | |
| PGresult*, | | PGresult*, | |
| std::size_t row, | | std::size_t row, | |
| bool truncated = false); | | bool truncated = false); | |
| | | | |
| protected: | | protected: | |
| statement (connection&, | | statement (connection&, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| | | const Oid* types, | |
| | | std::size_t types_count); | |
| | | | |
| | | statement (connection&, | |
| | | const char* name, | |
| | | const char* text, | |
| | | bool copy_name_text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count); | | std::size_t types_count); | |
| | | | |
|
| | | private: | |
| | | void | |
| | | init (const Oid* types, std::size_t types_count); | |
| | | | |
| protected: | | protected: | |
| connection& conn_; | | connection& conn_; | |
|
| std::string name_; | | | |
| | | std::string name_copy_; | |
| | | const char* name_; | |
| | | | |
| | | std::string text_copy_; | |
| | | const char* text_; | |
| | | | |
| private: | | private: | |
| bool deallocated_; | | bool deallocated_; | |
| }; | | }; | |
| | | | |
| class LIBODB_PGSQL_EXPORT select_statement: public statement | | class LIBODB_PGSQL_EXPORT select_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~select_statement (); | | ~select_statement (); | |
| | | | |
| select_statement (connection& conn, | | select_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| binding& cond, | | binding& param, | |
| native_binding& native_cond, | | native_binding& native_param, | |
| binding& data); | | binding& result); | |
| | | | |
| select_statement (connection& conn, | | select_statement (connection& conn, | |
|
| const std::string& name, | | const char* name, | |
| const std::string& stmt, | | const char* stmt, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| native_binding& native_cond, | | binding& param, | |
| binding& data); | | native_binding& native_param, | |
| | | binding& result, | |
| | | bool copy_name_text = true); | |
| | | | |
| select_statement (connection& conn, | | select_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| binding& data); | | binding& result); | |
| | | | |
| | | select_statement (connection& conn, | |
| | | const char* name, | |
| | | const char* text, | |
| | | binding& result, | |
| | | bool copy_name_text = true); | |
| | | | |
| | | select_statement (connection& conn, | |
| | | const std::string& name, | |
| | | const std::string& text, | |
| | | const Oid* types, | |
| | | std::size_t types_count, | |
| | | native_binding& native_param, | |
| | | binding& result); | |
| | | | |
| // Common select interface expected by the generated code. | | // Common select interface expected by the generated code. | |
| // | | // | |
| public: | | public: | |
| enum result | | enum result | |
| { | | { | |
| success, | | success, | |
| no_data, | | no_data, | |
| truncated | | truncated | |
| }; | | }; | |
| | | | |
| skipping to change at line 161 | | skipping to change at line 203 | |
| load (); | | load (); | |
| | | | |
| void | | void | |
| reload (); | | reload (); | |
| | | | |
| private: | | private: | |
| select_statement (const select_statement&); | | select_statement (const select_statement&); | |
| select_statement& operator= (const select_statement&); | | select_statement& operator= (const select_statement&); | |
| | | | |
| private: | | private: | |
|
| binding* cond_; | | binding* param_; | |
| native_binding* native_cond_; | | native_binding* native_param_; | |
| | | | |
|
| binding& data_; | | binding& result_; | |
| | | | |
|
| auto_handle<PGresult> result_; | | auto_handle<PGresult> handle_; | |
| std::size_t row_count_; | | std::size_t row_count_; | |
| std::size_t current_row_; | | std::size_t current_row_; | |
| }; | | }; | |
| | | | |
| class LIBODB_PGSQL_EXPORT insert_statement: public statement | | class LIBODB_PGSQL_EXPORT insert_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~insert_statement (); | | ~insert_statement (); | |
| | | | |
| insert_statement (connection& conn, | | insert_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| | | const Oid* types, | |
| | | std::size_t types_count, | |
| | | binding& param, | |
| | | native_binding& native_param, | |
| | | bool returning); | |
| | | | |
| | | insert_statement (connection& conn, | |
| | | const char* name, | |
| | | const char* text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| binding& data, | | binding& param, | |
| native_binding& native_data); | | native_binding& native_param, | |
| | | bool returning, | |
| | | bool copy_name_text = true); | |
| | | | |
| // Return true if successful and false if the row is a duplicate. | | // Return true if successful and false if the row is a duplicate. | |
| // All other errors are reported by throwing exceptions. | | // All other errors are reported by throwing exceptions. | |
| // | | // | |
| bool | | bool | |
| execute (); | | execute (); | |
| | | | |
| unsigned long long | | unsigned long long | |
|
| id (); | | id () | |
| | | { | |
| | | return id_; | |
| | | } | |
| | | | |
| private: | | private: | |
| insert_statement (const insert_statement&); | | insert_statement (const insert_statement&); | |
| insert_statement& operator= (const insert_statement&); | | insert_statement& operator= (const insert_statement&); | |
| | | | |
| private: | | private: | |
|
| binding& data_; | | binding& param_; | |
| native_binding& native_data_; | | native_binding& native_param_; | |
| | | | |
|
| bool id_cached_; | | bool returning_; | |
| unsigned long long id_; | | unsigned long long id_; | |
| }; | | }; | |
| | | | |
| class LIBODB_PGSQL_EXPORT update_statement: public statement | | class LIBODB_PGSQL_EXPORT update_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~update_statement (); | | ~update_statement (); | |
| | | | |
|
| // Asssumes that cond.values, cond.lengths, and cond.formats are | | | |
| // suffixes of data.values, data.lengths, and data.formats | | | |
| // respectively. | | | |
| // | | | |
| update_statement (connection& conn, | | update_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| binding& cond, | | binding& param, | |
| native_binding& native_cond, | | native_binding& native_param); | |
| binding& data, | | | |
| native_binding& native_data); | | | |
| | | | |
|
| void | | update_statement (connection& conn, | |
| | | const char* name, | |
| | | const char* text, | |
| | | const Oid* types, | |
| | | std::size_t types_count, | |
| | | binding& param, | |
| | | native_binding& native_param, | |
| | | bool copy_name_text = true); | |
| | | | |
| | | unsigned long long | |
| execute (); | | execute (); | |
| | | | |
| private: | | private: | |
| update_statement (const update_statement&); | | update_statement (const update_statement&); | |
| update_statement& operator= (const update_statement&); | | update_statement& operator= (const update_statement&); | |
| | | | |
| private: | | private: | |
|
| binding& cond_; | | binding& param_; | |
| native_binding& native_cond_; | | native_binding& native_param_; | |
| | | | |
| binding& data_; | | | |
| native_binding& native_data_; | | | |
| }; | | }; | |
| | | | |
| class LIBODB_PGSQL_EXPORT delete_statement: public statement | | class LIBODB_PGSQL_EXPORT delete_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~delete_statement (); | | ~delete_statement (); | |
| | | | |
| delete_statement (connection& conn, | | delete_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| | | const Oid* types, | |
| | | std::size_t types_count, | |
| | | binding& param, | |
| | | native_binding& native_param); | |
| | | | |
| | | delete_statement (connection& conn, | |
| | | const char* name, | |
| | | const char* text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| binding& cond, | | binding& param, | |
| native_binding& native_cond); | | native_binding& native_param, | |
| | | bool copy_name_text = true); | |
| | | | |
| delete_statement (connection& conn, | | delete_statement (connection& conn, | |
| const std::string& name, | | const std::string& name, | |
|
| const std::string& stmt, | | const std::string& text, | |
| const Oid* types, | | const Oid* types, | |
| std::size_t types_count, | | std::size_t types_count, | |
|
| native_binding& native_cond); | | native_binding& native_param); | |
| | | | |
| unsigned long long | | unsigned long long | |
| execute (); | | execute (); | |
| | | | |
| private: | | private: | |
| delete_statement (const delete_statement&); | | delete_statement (const delete_statement&); | |
| delete_statement& operator= (const delete_statement&); | | delete_statement& operator= (const delete_statement&); | |
| | | | |
| private: | | private: | |
|
| binding* cond_; | | binding* param_; | |
| native_binding& native_cond_; | | native_binding& native_param_; | |
| }; | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
| #endif // ODB_PGSQL_STATEMENT_HXX | | #endif // ODB_PGSQL_STATEMENT_HXX | |
| | | | |
End of changes. 29 change blocks. |
| 47 lines changed or deleted | | 112 lines changed or added | |
|
| traits.hxx | | traits.hxx | |
| | | | |
| skipping to change at line 14 | | skipping to change at line 14 | |
| // license : GNU GPL v2; see accompanying LICENSE file | | // license : GNU GPL v2; see accompanying LICENSE file | |
| | | | |
| #ifndef ODB_PGSQL_TRAITS_HXX | | #ifndef ODB_PGSQL_TRAITS_HXX | |
| #define ODB_PGSQL_TRAITS_HXX | | #define ODB_PGSQL_TRAITS_HXX | |
| | | | |
| #include <odb/pre.hxx> | | #include <odb/pre.hxx> | |
| | | | |
| #include <string> | | #include <string> | |
| #include <vector> | | #include <vector> | |
| #include <cstddef> // std::size_t | | #include <cstddef> // std::size_t | |
|
| | | #include <cstring> // std::memcpy, std::memset, std::strlen | |
| | | | |
| #include <odb/traits.hxx> | | #include <odb/traits.hxx> | |
| #include <odb/wrapper-traits.hxx> | | #include <odb/wrapper-traits.hxx> | |
| | | | |
| #include <odb/details/buffer.hxx> | | #include <odb/details/buffer.hxx> | |
| #include <odb/details/wrapper-p.hxx> | | #include <odb/details/wrapper-p.hxx> | |
| | | | |
| #include <odb/pgsql/version.hxx> | | #include <odb/pgsql/version.hxx> | |
| #include <odb/pgsql/pgsql-types.hxx> | | #include <odb/pgsql/pgsql-types.hxx> | |
| | | | |
| | | | |
| skipping to change at line 149 | | skipping to change at line 150 | |
| }; | | }; | |
| | | | |
| // The wrapped_value_traits specializations should be able to handle | | // The wrapped_value_traits specializations should be able to handle | |
| // any value type which means we have to have every possible signature | | // any value type which means we have to have every possible signature | |
| // of the set_value() and set_image() functions. | | // of the set_value() and set_image() functions. | |
| // | | // | |
| template <typename W, database_type_id ID> | | template <typename W, database_type_id ID> | |
| struct wrapped_value_traits<W, ID, false> | | struct wrapped_value_traits<W, ID, false> | |
| { | | { | |
| typedef wrapper_traits<W> wtraits; | | typedef wrapper_traits<W> wtraits; | |
|
| typedef typename wtraits::wrapped_type wrapped_type; | | typedef typename wtraits::unrestricted_wrapped_type wrapped_type; | |
| | | | |
| typedef W value_type; | | typedef W value_type; | |
| typedef wrapped_type query_type; | | typedef wrapped_type query_type; | |
| typedef typename image_traits<ID>::image_type image_type; | | typedef typename image_traits<ID>::image_type image_type; | |
| | | | |
| typedef value_traits<wrapped_type, ID> vtraits; | | typedef value_traits<wrapped_type, ID> vtraits; | |
| | | | |
| static void | | static void | |
| set_value (W& v, const image_type& i, bool is_null) | | set_value (W& v, const image_type& i, bool is_null) | |
| { | | { | |
| | | | |
| skipping to change at line 210 | | skipping to change at line 211 | |
| | | | |
| // VARBIT. | | // VARBIT. | |
| // | | // | |
| static void | | static void | |
| set_value (W& v, const details::ubuffer& b, std::size_t n, bool is_nu
ll) | | set_value (W& v, const details::ubuffer& b, std::size_t n, bool is_nu
ll) | |
| { | | { | |
| vtraits::set_value (wtraits::set_ref (v), b, n, is_null); | | vtraits::set_value (wtraits::set_ref (v), b, n, is_null); | |
| } | | } | |
| | | | |
| static void | | static void | |
|
| set_image (details::ubuffer& b, std::size_t& n, bool& is_null, const | | set_image (details::ubuffer& b, | |
| W& v) | | std::size_t& n, | |
| | | bool& is_null, | |
| | | const W& v) | |
| { | | { | |
| vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); | | vtraits::set_image (b, n, is_null, wtraits::get_ref (v)); | |
| } | | } | |
| | | | |
| // UUID. | | // UUID. | |
| // | | // | |
| static void | | static void | |
| set_value (W& v, const unsigned char* i, bool is_null) | | set_value (W& v, const unsigned char* i, bool is_null) | |
| { | | { | |
| vtraits::set_value (wtraits::set_ref (v), i, is_null); | | vtraits::set_value (wtraits::set_ref (v), i, is_null); | |
| | | | |
| skipping to change at line 234 | | skipping to change at line 238 | |
| set_image (unsigned char* i, bool& is_null, const W& v) | | set_image (unsigned char* i, bool& is_null, const W& v) | |
| { | | { | |
| vtraits::set_image (i, is_null, wtraits::get_ref (v)); | | vtraits::set_image (i, is_null, wtraits::get_ref (v)); | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <typename W, database_type_id ID> | | template <typename W, database_type_id ID> | |
| struct wrapped_value_traits<W, ID, true> | | struct wrapped_value_traits<W, ID, true> | |
| { | | { | |
| typedef wrapper_traits<W> wtraits; | | typedef wrapper_traits<W> wtraits; | |
|
| typedef typename wtraits::wrapped_type wrapped_type; | | typedef typename wtraits::unrestricted_wrapped_type wrapped_type; | |
| | | | |
| typedef W value_type; | | typedef W value_type; | |
| typedef wrapped_type query_type; | | typedef wrapped_type query_type; | |
| typedef typename image_traits<ID>::image_type image_type; | | typedef typename image_traits<ID>::image_type image_type; | |
| | | | |
| typedef value_traits<wrapped_type, ID> vtraits; | | typedef value_traits<wrapped_type, ID> vtraits; | |
| | | | |
| static void | | static void | |
| set_value (W& v, const image_type& i, bool is_null) | | set_value (W& v, const image_type& i, bool is_null) | |
| { | | { | |
| | | | |
| skipping to change at line 466 | | skipping to change at line 470 | |
| | | | |
| template <std::size_t n> | | template <std::size_t n> | |
| struct default_value_traits<const char[n], id_string>: | | struct default_value_traits<const char[n], id_string>: | |
| c_string_value_traits | | c_string_value_traits | |
| { | | { | |
| }; | | }; | |
| | | | |
| // std::vector<char> (buffer) specialization. | | // std::vector<char> (buffer) specialization. | |
| // | | // | |
| template <> | | template <> | |
|
| struct LIBODB_PGSQL_EXPORT default_value_traits<std::vector<char>, id_b | | struct LIBODB_PGSQL_EXPORT default_value_traits< | |
| ytea> | | std::vector<char>, id_bytea> | |
| { | | { | |
| public: | | public: | |
| typedef std::vector<char> value_type; | | typedef std::vector<char> value_type; | |
| typedef std::vector<char> query_type; | | typedef std::vector<char> query_type; | |
| typedef details::buffer image_type; | | typedef details::buffer image_type; | |
| | | | |
| static void | | static void | |
| set_value (value_type& v, | | set_value (value_type& v, | |
| const details::buffer& b, | | const details::buffer& b, | |
| std::size_t n, | | std::size_t n, | |
| | | | |
| skipping to change at line 492 | | skipping to change at line 497 | |
| v.clear (); | | v.clear (); | |
| } | | } | |
| | | | |
| static void | | static void | |
| set_image (details::buffer&, | | set_image (details::buffer&, | |
| std::size_t& n, | | std::size_t& n, | |
| bool& is_null, | | bool& is_null, | |
| const value_type&); | | const value_type&); | |
| }; | | }; | |
| | | | |
|
| | | // std::vector<unsigned char> (buffer) specialization. | |
| | | // | |
| | | template <> | |
| | | struct LIBODB_PGSQL_EXPORT default_value_traits< | |
| | | std::vector<unsigned char>, id_bytea> | |
| | | { | |
| | | public: | |
| | | typedef std::vector<unsigned char> value_type; | |
| | | typedef std::vector<unsigned char> query_type; | |
| | | typedef details::buffer image_type; | |
| | | | |
| | | static void | |
| | | set_value (value_type& v, | |
| | | const details::buffer& b, | |
| | | std::size_t n, | |
| | | bool is_null) | |
| | | { | |
| | | if (!is_null) | |
| | | { | |
| | | const unsigned char* d ( | |
| | | reinterpret_cast<const unsigned char*> (b.data ())); | |
| | | v.assign (d, d + n); | |
| | | } | |
| | | else | |
| | | v.clear (); | |
| | | } | |
| | | | |
| | | static void | |
| | | set_image (details::buffer&, | |
| | | std::size_t& n, | |
| | | bool& is_null, | |
| | | const value_type&); | |
| | | }; | |
| | | | |
| | | // char[n] (buffer) specialization. | |
| | | // | |
| | | template <std::size_t N> | |
| | | struct default_value_traits<char[N], id_bytea> | |
| | | { | |
| | | public: | |
| | | typedef char* value_type; | |
| | | typedef const char* query_type; | |
| | | typedef details::buffer image_type; | |
| | | | |
| | | static void | |
| | | set_value (char* const& v, | |
| | | const details::buffer& b, | |
| | | std::size_t n, | |
| | | bool is_null) | |
| | | { | |
| | | if (!is_null) | |
| | | std::memcpy (v, b.data (), (n < N ? n : N)); | |
| | | else | |
| | | std::memset (v, 0, N); | |
| | | } | |
| | | | |
| | | static void | |
| | | set_image (details::buffer& b, | |
| | | std::size_t& n, | |
| | | bool& is_null, | |
| | | const char* v) | |
| | | { | |
| | | is_null = false; | |
| | | n = N; | |
| | | | |
| | | if (n > b.capacity ()) | |
| | | b.capacity (n); | |
| | | | |
| | | std::memcpy (b.data (), v, n); | |
| | | } | |
| | | }; | |
| | | | |
| | | // unsigned char[n] (buffer) specialization. | |
| | | // | |
| | | template <std::size_t N> | |
| | | struct default_value_traits<unsigned char[N], id_bytea> | |
| | | { | |
| | | public: | |
| | | typedef unsigned char* value_type; | |
| | | typedef const unsigned char* query_type; | |
| | | typedef details::buffer image_type; | |
| | | | |
| | | static void | |
| | | set_value (unsigned char* const& v, | |
| | | const details::buffer& b, | |
| | | std::size_t n, | |
| | | bool is_null) | |
| | | { | |
| | | if (!is_null) | |
| | | std::memcpy (v, b.data (), (n < N ? n : N)); | |
| | | else | |
| | | std::memset (v, 0, N); | |
| | | } | |
| | | | |
| | | static void | |
| | | set_image (details::buffer& b, | |
| | | std::size_t& n, | |
| | | bool& is_null, | |
| | | const unsigned char* v) | |
| | | { | |
| | | is_null = false; | |
| | | n = N; | |
| | | | |
| | | if (n > b.capacity ()) | |
| | | b.capacity (n); | |
| | | | |
| | | std::memcpy (b.data (), v, n); | |
| | | } | |
| | | }; | |
| | | | |
| // | | // | |
| // type_traits | | // type_traits | |
| // | | // | |
| | | | |
| template <typename T> | | template <typename T> | |
| struct default_type_traits; | | struct default_type_traits; | |
| | | | |
| template <typename T> | | template <typename T> | |
| class type_traits: public default_type_traits<T> | | class type_traits: public default_type_traits<T> | |
| { | | { | |
| | | | |
End of changes. 6 change blocks. |
| 6 lines changed or deleted | | 119 lines changed or added | |
|