| object-result.hxx | | object-result.hxx | |
| | | | |
| skipping to change at line 25 | | skipping to change at line 25 | |
| #include <odb/mysql/version.hxx> | | #include <odb/mysql/version.hxx> | |
| #include <odb/mysql/forward.hxx> // query, object_statements | | #include <odb/mysql/forward.hxx> // query, object_statements | |
| #include <odb/mysql/result.hxx> | | #include <odb/mysql/result.hxx> | |
| #include <odb/mysql/statement.hxx> | | #include <odb/mysql/statement.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
| template <typename T> | | template <typename T> | |
|
| class result_impl<T, class_object>: | | class object_result_impl: public odb::object_result_impl<T> | |
| public odb::result_impl<T, class_object> | | | |
| { | | { | |
| public: | | public: | |
|
| typedef odb::result_impl<T, class_object> base_type; | | typedef odb::object_result_impl<T> base_type; | |
| | | | |
| typedef typename base_type::object_type object_type; | | typedef typename base_type::object_type object_type; | |
| typedef typename base_type::object_traits object_traits; | | typedef typename base_type::object_traits object_traits; | |
| typedef typename base_type::id_type id_type; | | typedef typename base_type::id_type id_type; | |
| | | | |
| typedef typename base_type::pointer_type pointer_type; | | typedef typename base_type::pointer_type pointer_type; | |
| typedef typename base_type::pointer_traits pointer_traits; | | typedef typename base_type::pointer_traits pointer_traits; | |
| | | | |
| virtual | | virtual | |
|
| ~result_impl (); | | ~object_result_impl (); | |
| | | | |
|
| result_impl (const query&, | | object_result_impl (const query&, | |
| details::shared_ptr<select_statement>, | | details::shared_ptr<select_statement>, | |
| object_statements<object_type>&); | | object_statements<object_type>&); | |
| | | | |
| virtual void | | virtual void | |
|
| load (object_type&); | | load (object_type&, bool fetch); | |
| | | | |
| virtual id_type | | virtual id_type | |
| load_id (); | | load_id (); | |
| | | | |
| virtual void | | virtual void | |
| next (); | | next (); | |
| | | | |
| virtual void | | virtual void | |
| cache (); | | cache (); | |
| | | | |
| virtual std::size_t | | virtual std::size_t | |
| size (); | | size (); | |
| | | | |
| using base_type::current; | | using base_type::current; | |
| | | | |
| private: | | private: | |
| void | | void | |
|
| fetch (); | | fetch (bool next = true); | |
| | | | |
| private: | | private: | |
| details::shared_ptr<select_statement> statement_; | | details::shared_ptr<select_statement> statement_; | |
| object_statements<object_type>& statements_; | | object_statements<object_type>& statements_; | |
| std::size_t count_; | | std::size_t count_; | |
| }; | | }; | |
|
| | | | |
| | | template <typename T> | |
| | | class object_result_impl_no_id: public odb::object_result_impl_no_id<T> | |
| | | { | |
| | | public: | |
| | | typedef odb::object_result_impl_no_id<T> base_type; | |
| | | | |
| | | typedef typename base_type::object_type object_type; | |
| | | typedef typename base_type::object_traits object_traits; | |
| | | | |
| | | typedef typename base_type::pointer_type pointer_type; | |
| | | typedef typename base_type::pointer_traits pointer_traits; | |
| | | | |
| | | virtual | |
| | | ~object_result_impl_no_id (); | |
| | | | |
| | | object_result_impl_no_id (const query&, | |
| | | details::shared_ptr<select_statement>, | |
| | | object_statements_no_id<object_type>&); | |
| | | | |
| | | virtual void | |
| | | load (object_type&); | |
| | | | |
| | | virtual void | |
| | | next (); | |
| | | | |
| | | virtual void | |
| | | cache (); | |
| | | | |
| | | virtual std::size_t | |
| | | size (); | |
| | | | |
| | | using base_type::current; | |
| | | | |
| | | private: | |
| | | void | |
| | | fetch (); | |
| | | | |
| | | private: | |
| | | details::shared_ptr<select_statement> statement_; | |
| | | object_statements_no_id<object_type>& statements_; | |
| | | std::size_t count_; | |
| | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/mysql/object-result.txx> | | #include <odb/mysql/object-result.txx> | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
| #endif // ODB_MYSQL_OBJECT_RESULT_HXX | | #endif // ODB_MYSQL_OBJECT_RESULT_HXX | |
| | | | |
End of changes. 7 change blocks. |
| 9 lines changed or deleted | | 51 lines changed or added | |
|
| object-result.txx | | object-result.txx | |
| | | | |
| skipping to change at line 15 | | skipping to change at line 15 | |
| | | | |
| #include <odb/callback.hxx> | | #include <odb/callback.hxx> | |
| #include <odb/exceptions.hxx> | | #include <odb/exceptions.hxx> | |
| | | | |
| #include <odb/mysql/object-statements.hxx> | | #include <odb/mysql/object-statements.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
|
| | | // | |
| | | // 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), | |
| count_ (0) | | count_ (0) | |
| { | | { | |
| } | | } | |
| | | | |
| 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 f) | |
| { | | { | |
| if (count_ > statement_->fetched ()) | | if (count_ > statement_->fetched ()) | |
| fetch (); | | fetch (); | |
|
| | | else if (f && statement_->cached ()) | |
| | | { | |
| | | // We have to re-load the image in case it has been overwritten | |
| | | // between the last time we fetched and this call to load(). | |
| | | // | |
| | | fetch (false); | |
| | | } | |
| | | | |
| // 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 72 | | skipping to change at line 83 | |
| 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 () | |
| { | | { | |
| if (count_ > statement_->fetched ()) | | if (count_ > statement_->fetched ()) | |
| fetch (); | | fetch (); | |
|
| | | else if (statement_->cached ()) | |
| | | { | |
| | | // We have to re-load the image in case it has been overwritten | |
| | | // between the last time we fetched and this call to load_id(). | |
| | | // | |
| | | fetch (false); | |
| | | } | |
| | | | |
| 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 () | |
| | | { | |
| | | this->current (pointer_type ()); | |
| | | | |
| | | // If we are cached, simply increment the position and | |
| | | // postpone the actual row fetching until later. This way | |
| | | // if the same object is loaded in between iteration, the | |
| | | // image won't be messed up. | |
| | | // | |
| | | count_++; | |
| | | | |
| | | if (statement_->cached ()) | |
| | | this->end_ = count_ > statement_->result_size (); | |
| | | else | |
| | | fetch (); | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl<T>:: | |
| | | fetch (bool next) | |
| | | { | |
| | | // If the result is cached, the image can grow between calls | |
| | | // to fetch() as a result of other statements execution. | |
| | | // | |
| | | if (statement_->cached ()) | |
| | | { | |
| | | 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++; | |
| | | } | |
| | | } | |
| | | | |
| | | while (!this->end_ && (!next || count_ > statement_->fetched ())) | |
| | | { | |
| | | select_statement::result r (statement_->fetch (next)); | |
| | | | |
| | | switch (r) | |
| | | { | |
| | | case select_statement::truncated: | |
| | | { | |
| | | // Don't re-fetch data we are skipping. | |
| | | // | |
| | | if (next && count_ != statement_->fetched ()) | |
| | | continue; | |
| | | | |
| | | typename object_traits::image_type& im (statements_.image ()); | |
| | | | |
| | | 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_->refetch (); | |
| | | } | |
| | | // Fall throught. | |
| | | } | |
| | | case select_statement::success: | |
| | | { | |
| | | break; | |
| | | } | |
| | | case select_statement::no_data: | |
| | | { | |
| | | this->end_ = true; | |
| | | break; | |
| | | } | |
| | | } | |
| | | | |
| | | // If we are refetching the current row, then we are done. | |
| | | // | |
| | | if (!next) | |
| | | break; | |
| | | } | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl<T>:: | |
| | | cache () | |
| | | { | |
| | | if (!statement_->cached ()) | |
| | | { | |
| | | statement_->cache (); | |
| | | | |
| | | if (count_ >= statement_->result_size ()) | |
| | | this->end_ = true; | |
| | | } | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | std::size_t object_result_impl<T>:: | |
| | | size () | |
| | | { | |
| | | if (!statement_->cached ()) | |
| | | throw result_not_cached (); | |
| | | | |
| | | 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), | |
| | | count_ (0) | |
| | | { | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl_no_id<T>:: | |
| | | load (object_type& obj) | |
| | | { | |
| | | if (count_ > statement_->fetched ()) | |
| | | fetch (); | |
| | | | |
| | | odb::database& db (this->database ()); | |
| | | | |
| | | object_traits::callback (db, obj, callback_event::pre_load); | |
| | | object_traits::init (obj, statements_.image (), db); | |
| | | object_traits::callback (db, obj, callback_event::post_load); | |
| | | } | |
| | | | |
| | | template <typename T> | |
| | | void object_result_impl_no_id<T>:: | |
| next () | | next () | |
| { | | { | |
| this->current (pointer_type ()); | | this->current (pointer_type ()); | |
| | | | |
| // If we are cached, simply increment the position and | | // If we are cached, simply increment the position and | |
| // postpone the actual row fetching until later. This way | | // postpone the actual row fetching until later. This way | |
| // if the same object is loaded in between iteration, the | | // if the same object is loaded in between iteration, the | |
| // image won't be messed up. | | // image won't be messed up. | |
| // | | // | |
| count_++; | | count_++; | |
| | | | |
| if (statement_->cached ()) | | if (statement_->cached ()) | |
| this->end_ = count_ > statement_->result_size (); | | this->end_ = count_ > statement_->result_size (); | |
| else | | else | |
| fetch (); | | fetch (); | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl_no_id<T>:: | |
| fetch () | | fetch () | |
| { | | { | |
| // If the result is cached, the image can grow between calls | | // If the result is cached, the image can grow between calls | |
| // to fetch() as a result of other statements execution. | | // to fetch() as a result of other statements execution. | |
| // | | // | |
| if (statement_->cached ()) | | if (statement_->cached ()) | |
| { | | { | |
| 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++; | |
| } | | } | |
| } | | } | |
| | | | |
| while (!this->end_ && count_ > statement_->fetched ()) | | while (!this->end_ && count_ > statement_->fetched ()) | |
| { | | { | |
| select_statement::result r (statement_->fetch ()); | | select_statement::result r (statement_->fetch ()); | |
| | | | |
| switch (r) | | switch (r) | |
| { | | { | |
| case select_statement::truncated: | | case select_statement::truncated: | |
| { | | { | |
| // Don't re-fetch data we are skipping. | | // Don't re-fetch data we are skipping. | |
| // | | // | |
| if (count_ != statement_->fetched ()) | | if (count_ != statement_->fetched ()) | |
| continue; | | continue; | |
| | | | |
| typename object_traits::image_type& im (statements_.image ()); | | typename object_traits::image_type& im (statements_.image ()); | |
| | | | |
|
| 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_->refetch (); | | statement_->refetch (); | |
| } | | } | |
| // Fall throught. | | // Fall throught. | |
| } | | } | |
| case select_statement::success: | | case select_statement::success: | |
| { | | { | |
| break; | | break; | |
| } | | } | |
| case select_statement::no_data: | | case select_statement::no_data: | |
| { | | { | |
| this->end_ = true; | | this->end_ = true; | |
| break; | | break; | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_object>:: | | void object_result_impl_no_id<T>:: | |
| cache () | | cache () | |
| { | | { | |
| if (!statement_->cached ()) | | if (!statement_->cached ()) | |
| { | | { | |
| statement_->cache (); | | statement_->cache (); | |
| | | | |
| if (count_ >= statement_->result_size ()) | | if (count_ >= statement_->result_size ()) | |
| this->end_ = true; | | this->end_ = true; | |
| } | | } | |
| } | | } | |
| | | | |
| 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 () | |
| { | | { | |
| if (!statement_->cached ()) | | if (!statement_->cached ()) | |
| throw result_not_cached (); | | throw result_not_cached (); | |
| | | | |
| return statement_->result_size (); | | return statement_->result_size (); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 16 change blocks. |
| 24 lines changed or deleted | | 189 lines changed or added | |
|
| object-statements.hxx | | object-statements.hxx | |
| | | | |
| skipping to change at line 32 | | skipping to change at line 32 | |
| #include <odb/mysql/version.hxx> | | #include <odb/mysql/version.hxx> | |
| #include <odb/mysql/statement.hxx> | | #include <odb/mysql/statement.hxx> | |
| #include <odb/mysql/statements-base.hxx> | | #include <odb/mysql/statements-base.hxx> | |
| | | | |
| #include <odb/mysql/details/export.hxx> | | #include <odb/mysql/details/export.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
|
| | | 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_MYSQL_EXPORT object_statements_base: public statements_bas
e | | class LIBODB_MYSQL_EXPORT object_statements_base: public statements_bas
e | |
| { | | { | |
| // Locking. | | // Locking. | |
| // | | // | |
| public: | | public: | |
| 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 (MYSQL_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 (MYSQL_BIND*) {} | |
| | | }; | |
| | | | |
| 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 mysql::insert_statement persist_statement_type; | | typedef mysql::insert_statement insert_statement_type; | |
| typedef mysql::select_statement find_statement_type; | | typedef mysql::select_statement select_statement_type; | |
| typedef mysql::update_statement update_statement_type; | | typedef mysql::update_statement update_statement_type; | |
|
| typedef mysql::delete_statement erase_statement_type; | | typedef mysql::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 226 | |
| 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_; | | | |
| } | | | |
| | | | |
| my_bool* | | my_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_;} | |
| | | | |
|
| persist_statement_type& | | 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 () | | 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_, object_traits::persist_statement, in_image_binding_)); | | conn_, | |
| | | object_traits::persist_statement, | |
| | | insert_image_binding_, | |
| | | 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, | | object_traits::find_statement, | |
| id_image_binding_, | | id_image_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, | | object_traits::update_statement, | |
|
| id_image_binding_, | | update_image_binding_, | |
| in_image_binding_)); | | false)); | |
| | | | |
| 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, | | object_traits::erase_statement, | |
|
| id_image_binding_)); | | id_image_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, | |
| | | od_.id_image_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. The | | // Select binding. | |
| // update statement depends on this being one contiguous arrays. | | | |
| // | | | |
| std::size_t in_image_version_; | | | |
| binding in_image_binding_; | | | |
| MYSQL_BIND in_image_bind_[object_traits::in_column_count + 1]; | | | |
| | | | |
| // Out (receive) binding. | | | |
| // | | // | |
|
| std::size_t out_image_version_; | | std::size_t select_image_version_; | |
| binding out_image_binding_; | | binding select_image_binding_; | |
| MYSQL_BIND out_image_bind_[object_traits::out_column_count]; | | MYSQL_BIND select_image_bind_[select_column_count]; | |
| my_bool out_image_truncated_[object_traits::out_column_count]; | | my_bool select_image_truncated_[select_column_count]; | |
| | | | |
| | | // Insert binding. | |
| | | // | |
| | | std::size_t insert_image_version_; | |
| | | binding insert_image_binding_; | |
| | | MYSQL_BIND insert_image_bind_[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_; | |
| | | MYSQL_BIND update_image_bind_[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_; | |
| | | | |
|
| 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 395 | | skipping to change at line 500 | |
| { | | { | |
| 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 mysql::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_;} | |
| | | | |
| | | my_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, | |
| | | 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 select_column_count = | |
| | | object_traits::column_count; | |
| | | | |
| | | static const std::size_t insert_column_count = | |
| | | object_traits::column_count; | |
| | | | |
| | | private: | |
| | | image_type image_; | |
| | | | |
| | | // Select binding. | |
| | | // | |
| | | std::size_t select_image_version_; | |
| | | binding select_image_binding_; | |
| | | MYSQL_BIND select_image_bind_[select_column_count]; | |
| | | my_bool select_image_truncated_[select_column_count]; | |
| | | | |
| | | // Insert binding. | |
| | | // | |
| | | std::size_t insert_image_version_; | |
| | | binding insert_image_binding_; | |
| | | MYSQL_BIND insert_image_bind_[insert_column_count]; | |
| | | | |
| | | details::shared_ptr<insert_statement_type> persist_; | |
| | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/mysql/object-statements.ixx> | | #include <odb/mysql/object-statements.ixx> | |
| #include <odb/mysql/object-statements.txx> | | #include <odb/mysql/object-statements.txx> | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
| #endif // ODB_MYSQL_OBJECT_STATEMENTS_HXX | | #endif // ODB_MYSQL_OBJECT_STATEMENTS_HXX | |
| | | | |
End of changes. 36 change blocks. |
| 79 lines changed or deleted | | 288 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/mysql/connection.hxx> | | #include <odb/mysql/connection.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
|
| | | // | |
| | | // optimistic_data | |
| | | // | |
| | | | |
| | | template <typename T> | |
| | | optimistic_data<T, true>:: | |
| | | optimistic_data (MYSQL_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> | | 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_image_binding_ (select_image_bind_, select_column_count), | |
| ), | | insert_image_binding_ (insert_image_bind_, insert_column_count), | |
| out_image_binding_ (out_image_bind_, object_traits::out_column_co | | update_image_binding_ (update_image_bind_, | |
| unt), | | update_column_count + id_column_count + | |
| id_image_binding_ (in_image_bind_ + object_traits::in_column_coun | | managed_optimistic_column_count), | |
| t, 1) | | id_image_binding_ (update_image_bind_ + update_column_count, | |
| | | id_column_count), | |
| | | od_ (update_image_bind_ + 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].error = out_image_truncated_ + i; | | select_image_bind_[i].error = 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 113 | | skipping to change at line 141 | |
| { | | { | |
| 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 | |
| | | // | |
| | | | |
| | | 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; | |
| | | | |
| | | 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].error = select_image_truncated_ + i; | |
| | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 6 change blocks. |
| 13 lines changed or deleted | | 68 lines changed or added | |
|
| statement.hxx | | statement.hxx | |
| | | | |
| skipping to change at line 15 | | skipping to change at line 15 | |
| | | | |
| #ifndef ODB_MYSQL_STATEMENT_HXX | | #ifndef ODB_MYSQL_STATEMENT_HXX | |
| #define ODB_MYSQL_STATEMENT_HXX | | #define ODB_MYSQL_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/forward.hxx> | | #include <odb/forward.hxx> | |
|
| #include <odb/details/shared-ptr.hxx> | | #include <odb/statement.hxx> | |
| | | | |
| #include <odb/mysql/mysql.hxx> | | #include <odb/mysql/mysql.hxx> | |
| #include <odb/mysql/version.hxx> | | #include <odb/mysql/version.hxx> | |
| #include <odb/mysql/binding.hxx> | | #include <odb/mysql/binding.hxx> | |
| #include <odb/mysql/auto-handle.hxx> | | #include <odb/mysql/auto-handle.hxx> | |
| | | | |
| #include <odb/mysql/details/export.hxx> | | #include <odb/mysql/details/export.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
| class connection; | | class connection; | |
| | | | |
|
| class LIBODB_MYSQL_EXPORT statement: public details::shared_base | | class LIBODB_MYSQL_EXPORT statement: public odb::statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~statement () = 0; | | ~statement () = 0; | |
| | | | |
|
| | | MYSQL_STMT* | |
| | | handle () const | |
| | | { | |
| | | return stmt_; | |
| | | } | |
| | | | |
| | | virtual const char* | |
| | | text () const; | |
| | | | |
| // Cancel the statement execution (e.g., result fetching) so | | // Cancel the statement execution (e.g., result fetching) so | |
| // that another statement can be executed on the connection. | | // that another statement can be executed on the connection. | |
| // | | // | |
| virtual void | | virtual void | |
| cancel (); | | cancel (); | |
| | | | |
| protected: | | protected: | |
|
| statement (connection&); | | statement (connection&, const std::string& text); | |
| | | statement (connection&, const char* text, bool copy_text); | |
| | | | |
| | | private: | |
| | | void | |
| | | init (std::size_t text_size); | |
| | | | |
| protected: | | protected: | |
| connection& conn_; | | connection& conn_; | |
|
| | | std::string text_copy_; | |
| | | const char* text_; | |
| auto_handle<MYSQL_STMT> stmt_; | | auto_handle<MYSQL_STMT> stmt_; | |
| }; | | }; | |
| | | | |
| class LIBODB_MYSQL_EXPORT select_statement: public statement | | class LIBODB_MYSQL_EXPORT select_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~select_statement (); | | ~select_statement (); | |
| | | | |
| select_statement (connection& conn, | | select_statement (connection& conn, | |
|
| const std::string& statement, | | const std::string& text, | |
| binding& cond, | | binding& param, | |
| binding& data); | | binding& result); | |
| | | | |
| | | select_statement (connection& conn, | |
| | | const char* text, | |
| | | binding& param, | |
| | | binding& result, | |
| | | bool copy_text = true); | |
| | | | |
| select_statement (connection& conn, | | select_statement (connection& conn, | |
|
| const std::string& statement, | | const std::string& text, | |
| binding& data); | | binding& result); | |
| | | | |
| | | select_statement (connection& conn, | |
| | | const char* text, | |
| | | binding& result, | |
| | | bool copy_text = true); | |
| | | | |
| enum result | | enum result | |
| { | | { | |
| success, | | success, | |
| no_data, | | no_data, | |
| truncated | | truncated | |
| }; | | }; | |
| | | | |
| void | | void | |
| execute (); | | execute (); | |
| | | | |
| skipping to change at line 100 | | skipping to change at line 127 | |
| } | | } | |
| | | | |
| // Number of rows already fetched. | | // Number of rows already fetched. | |
| // | | // | |
| std::size_t | | std::size_t | |
| fetched () const | | fetched () const | |
| { | | { | |
| return rows_; | | return rows_; | |
| } | | } | |
| | | | |
|
| | | // Fetch next or current row depending on the next argument. | |
| | | // Note that fetching of the current row is only supported | |
| | | // if the result is cached. | |
| | | // | |
| result | | result | |
|
| fetch (); | | fetch (bool next = true); | |
| | | | |
| void | | void | |
| refetch (); | | refetch (); | |
| | | | |
| void | | void | |
| free_result (); | | free_result (); | |
| | | | |
| virtual void | | virtual void | |
| cancel (); | | cancel (); | |
| | | | |
| 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: | |
| bool end_; | | bool end_; | |
| bool cached_; | | bool cached_; | |
| std::size_t rows_; | | std::size_t rows_; | |
| std::size_t size_; | | std::size_t size_; | |
| | | | |
|
| binding* cond_; | | binding* param_; | |
| std::size_t cond_version_; | | std::size_t param_version_; | |
| | | | |
|
| binding& data_; | | binding& result_; | |
| std::size_t data_version_; | | std::size_t result_version_; | |
| }; | | }; | |
| | | | |
| class LIBODB_MYSQL_EXPORT insert_statement: public statement | | class LIBODB_MYSQL_EXPORT insert_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~insert_statement (); | | ~insert_statement (); | |
| | | | |
| insert_statement (connection& conn, | | insert_statement (connection& conn, | |
|
| const std::string& statement, | | const std::string& text, | |
| binding& data); | | binding& param); | |
| | | | |
| | | insert_statement (connection& conn, | |
| | | const char* text, | |
| | | binding& param, | |
| | | bool copy_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 (); | |
| | | | |
| 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_; | |
| std::size_t data_version_; | | std::size_t param_version_; | |
| }; | | }; | |
| | | | |
| class LIBODB_MYSQL_EXPORT update_statement: public statement | | class LIBODB_MYSQL_EXPORT update_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~update_statement (); | | ~update_statement (); | |
| | | | |
|
| // Asssumes that cond.bind is a suffix of data.bind. | | | |
| // | | | |
| update_statement (connection& conn, | | update_statement (connection& conn, | |
|
| const std::string& statement, | | const std::string& text, | |
| binding& cond, | | binding& param); | |
| binding& data); | | | |
| void | | update_statement (connection& conn, | |
| | | const char* text, | |
| | | binding& param, | |
| | | bool copy_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_; | |
| std::size_t cond_version_; | | std::size_t param_version_; | |
| | | | |
| binding& data_; | | | |
| std::size_t data_version_; | | | |
| }; | | }; | |
| | | | |
| class LIBODB_MYSQL_EXPORT delete_statement: public statement | | class LIBODB_MYSQL_EXPORT delete_statement: public statement | |
| { | | { | |
| public: | | public: | |
| virtual | | virtual | |
| ~delete_statement (); | | ~delete_statement (); | |
| | | | |
| delete_statement (connection& conn, | | delete_statement (connection& conn, | |
|
| const std::string& statement, | | const std::string& text, | |
| binding& cond); | | binding& param); | |
| | | | |
| | | delete_statement (connection& conn, | |
| | | const char* text, | |
| | | binding& param, | |
| | | bool copy_text = true); | |
| | | | |
| 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_; | |
| std::size_t cond_version_; | | std::size_t param_version_; | |
| }; | | }; | |
| } | | } | |
| } | | } | |
| | | | |
| #include <odb/post.hxx> | | #include <odb/post.hxx> | |
| | | | |
| #endif // ODB_MYSQL_STATEMENT_HXX | | #endif // ODB_MYSQL_STATEMENT_HXX | |
| | | | |
End of changes. 18 change blocks. |
| 32 lines changed or deleted | | 73 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_MYSQL_TRAITS_HXX | | #ifndef ODB_MYSQL_TRAITS_HXX | |
| #define ODB_MYSQL_TRAITS_HXX | | #define ODB_MYSQL_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/mysql/version.hxx> | | #include <odb/mysql/version.hxx> | |
| #include <odb/mysql/mysql-types.hxx> | | #include <odb/mysql/mysql-types.hxx> | |
| | | | |
| #include <odb/details/buffer.hxx> | | #include <odb/details/buffer.hxx> | |
| #include <odb/details/wrapper-p.hxx> | | #include <odb/details/wrapper-p.hxx> | |
| | | | |
| | | | |
| skipping to change at line 172 | | skipping to change at line 173 | |
| }; | | }; | |
| | | | |
| // 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 229 | | skipping to change at line 230 | |
| const W& v) | | const W& v) | |
| { | | { | |
| vtraits::set_image (i, c, n, is_null, wtraits::get_ref (v)); | | vtraits::set_image (i, c, n, 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 522 | | skipping to change at line 523 | |
| 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_MYSQL_EXPORT default_value_traits< | |
| | | std::vector<unsigned char>, id_blob> | |
| | | { | |
| | | 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_blob> | |
| | | { | |
| | | 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_blob> | |
| | | { | |
| | | 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. 4 change blocks. |
| 2 lines changed or deleted | | 113 lines changed or added | |
|
| view-result.txx | | view-result.txx | |
| | | | |
| skipping to change at line 16 | | skipping to change at line 16 | |
| #include <odb/callback.hxx> | | #include <odb/callback.hxx> | |
| #include <odb/exceptions.hxx> | | #include <odb/exceptions.hxx> | |
| | | | |
| #include <odb/mysql/view-statements.hxx> | | #include <odb/mysql/view-statements.hxx> | |
| | | | |
| namespace odb | | namespace odb | |
| { | | { | |
| namespace mysql | | namespace mysql | |
| { | | { | |
| template <typename T> | | template <typename T> | |
|
| result_impl<T, class_view>:: | | view_result_impl<T>:: | |
| ~result_impl () | | ~view_result_impl () | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| result_impl<T, class_view>:: | | view_result_impl<T>:: | |
| result_impl (const query&, | | view_result_impl (const query&, | |
| details::shared_ptr<select_statement> statement, | | details::shared_ptr<select_statement> statement, | |
| view_statements<view_type>& statements) | | view_statements<view_type>& statements) | |
| : base_type (statements.connection ().database ()), | | : base_type (statements.connection ().database ()), | |
| statement_ (statement), | | statement_ (statement), | |
| statements_ (statements), | | statements_ (statements), | |
| count_ (0) | | count_ (0) | |
| { | | { | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_view>:: | | void view_result_impl<T>:: | |
| load (view_type& view) | | load (view_type& view) | |
| { | | { | |
| if (count_ > statement_->fetched ()) | | if (count_ > statement_->fetched ()) | |
| fetch (); | | fetch (); | |
| | | | |
| odb::database& db (this->database ()); | | odb::database& db (this->database ()); | |
| | | | |
| view_traits::callback (db, view, callback_event::pre_load); | | view_traits::callback (db, view, callback_event::pre_load); | |
| view_traits::init (view, statements_.image (), db); | | view_traits::init (view, statements_.image (), db); | |
| view_traits::callback (db, view, callback_event::post_load); | | view_traits::callback (db, view, callback_event::post_load); | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_view>:: | | void view_result_impl<T>:: | |
| next () | | next () | |
| { | | { | |
| this->current (pointer_type ()); | | this->current (pointer_type ()); | |
| | | | |
| // If we are cached, simply increment the position and | | // If we are cached, simply increment the position and | |
| // postpone the actual row fetching until later. This way | | // postpone the actual row fetching until later. This way | |
| // if the same view is loaded in between iteration, the | | // if the same view is loaded in between iteration, the | |
| // image won't be messed up. | | // image won't be messed up. | |
| // | | // | |
| count_++; | | count_++; | |
| | | | |
| if (statement_->cached ()) | | if (statement_->cached ()) | |
| this->end_ = count_ > statement_->result_size (); | | this->end_ = count_ > statement_->result_size (); | |
| else | | else | |
| fetch (); | | fetch (); | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_view>:: | | void view_result_impl<T>:: | |
| fetch () | | fetch () | |
| { | | { | |
| // If the result is cached, the image can grow between calls | | // If the result is cached, the image can grow between calls | |
| // to fetch() as a result of other statements execution. | | // to fetch() as a result of other statements execution. | |
| // | | // | |
| if (statement_->cached ()) | | if (statement_->cached ()) | |
| { | | { | |
| typename view_traits::image_type& im (statements_.image ()); | | typename view_traits::image_type& im (statements_.image ()); | |
| | | | |
| if (im.version != statements_.image_version ()) | | if (im.version != statements_.image_version ()) | |
| | | | |
| skipping to change at line 128 | | skipping to change at line 128 | |
| case select_statement::no_data: | | case select_statement::no_data: | |
| { | | { | |
| this->end_ = true; | | this->end_ = true; | |
| break; | | break; | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| void result_impl<T, class_view>:: | | void view_result_impl<T>:: | |
| cache () | | cache () | |
| { | | { | |
| if (!statement_->cached ()) | | if (!statement_->cached ()) | |
| { | | { | |
| statement_->cache (); | | statement_->cache (); | |
| | | | |
| if (count_ >= statement_->result_size ()) | | if (count_ >= statement_->result_size ()) | |
| this->end_ = true; | | this->end_ = true; | |
| } | | } | |
| } | | } | |
| | | | |
| template <typename T> | | template <typename T> | |
|
| std::size_t result_impl<T, class_view>:: | | std::size_t view_result_impl<T>:: | |
| size () | | size () | |
| { | | { | |
| if (!statement_->cached ()) | | if (!statement_->cached ()) | |
| throw result_not_cached (); | | throw result_not_cached (); | |
| | | | |
| return statement_->result_size (); | | return statement_->result_size (); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
End of changes. 7 change blocks. |
| 11 lines changed or deleted | | 11 lines changed or added | |
|