diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | doc/manual.xhtml | 59 | ||||
-rw-r--r-- | odb/relational/header.hxx | 11 | ||||
-rw-r--r-- | odb/relational/mysql/source.cxx | 2 | ||||
-rw-r--r-- | odb/relational/pgsql/source.cxx | 2 | ||||
-rw-r--r-- | odb/relational/source.hxx | 70 | ||||
-rw-r--r-- | odb/relational/sqlite/source.cxx | 2 |
7 files changed, 56 insertions, 95 deletions
@@ -70,6 +70,11 @@ Version 1.6.0 For more information, refer to Section 11.2, "MySQL Database Class" in the ODB manual. + * Object cache maintained by a session nor longer distinguishes between + const and non-const objects. Instead, const objects are treated as + non-const by casting away constness. For more information on this new + behavior, refer to Section 9.1, "Object Cache" in the ODB manual. + Version 1.5.0 * Support for the PostgreSQL database. The provided connection factories diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 13c694f..7e68f6f 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -3060,12 +3060,6 @@ namespace odb what () const throw (); }; - struct const_object: exception - { - virtual const char* - what () const throw (); - }; - // Database operations exceptions. // struct recoverable: exception @@ -3137,11 +3131,9 @@ namespace odb <code>odb::transaction</code> class and are discussed in <a href="#3.4">Section 3.4, "Transactions"</a>.</p> - <p>The next three exceptions (<code>already_in_session</code>, - <code>not_in_session</code>, and - <code>const_object</code>) are thrown by the - <code>odb::session</code> class and are discussed - in <a href="#9">Chapter 9, "Session"</a>.</p> + <p>The next two exceptions (<code>already_in_session</code>, and + <code>not_in_session</code>) are thrown by the <code>odb::session</code> + class and are discussed in <a href="#9">Chapter 9, "Session"</a>.</p> <p>The <code>recoverable</code> exception serves as a common base for all the recoverable exceptions, which are: <code>connection_lost</code>, @@ -6051,26 +6043,43 @@ t.commit (); a pre-allocated instance, the object is only cached if its object pointer is a raw pointer.</p> - <p>Finally, the session caches both constant and unrestricted objects, - depending on whether a constant reference or constant pointer was - passed to the <code>database::persist()</code> function (in contrast, - when loaded, objects are always created and cached as unrestricted). - If we try to load an object as unrestricted that was previously - persisted and cached as constant, the <code>odb::const_object</code> - exception is thrown. The following transaction shows the - situation where this would happen:</p> + <p>Also note that when we persist an object as a constant reference + or constant pointer, the session caches such an object as + unrestricted (non-<code>const</code>). This can lead to undefined + behavior if the object being persisted was actually created as + <code>const</code> and is later found in the session cache and + used as non-<code>const</code>. As a result, when using sessions, + it is recommended that all persistent objects are created as + non-<code>const</code> instances. The following code fragment + illustrates this point:</p> <pre class="c++"> -shared_ptr<const person> p (new person ("John", "Doe")); +void save (database& db, shared_ptr<const person> p) +{ + transaction t (db.begin ()); + db.persist (p); // Persisted as const pointer. + t.commit (); +} session s; -transaction t (db.begin ()); -unsigned long id (db.persist (p)); -shared_ptr<const person> p1 (db.load<const person> (id)); // Ok. -shared_ptr<person> p2 (db.load<person> (id)); // Exception. +shared_ptr<const person> p1 (new const person ("John", "Doe")); +unsigned long id1 (save (db, p1)); // p1 is cached in s as non-const. -t.commit (); +{ + transaction t (db.begin ()); + shared_ptr<person> p (db.load<person> (id1)); // p == p1 + p->age (30); // Undefined behavior since p1 was created const. +} + +shared_ptr<const person> p2 (new person ("Jane", "Doe")); +unsigned long id2 (save (db, p2)); // p2 is cached in s as non-const. + +{ + transaction t (db.begin ()); + shared_ptr<person> p (db.load<person> (id2)); // p == p2 + p->age (30); // Ok, since p2 was not created const. +} </pre> diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index e4933a0..50a40b2 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -1163,8 +1163,7 @@ namespace relational // if (options.generate_query ()) { - os << "template<typename T>" << endl - << "static result<T>" << endl + os << "static result<object_type>" << endl << "query (database&, const query_base_type&);" << endl; @@ -1204,14 +1203,6 @@ namespace relational "object_type&);" << endl; - if (options.generate_query ()) - os << "static void" << endl - << "query_ (database&," << endl - << "const query_base_type&," << endl - << db << "::object_statements< object_type >&," << endl - << "details::shared_ptr< " << db << "::select_statement >&);" - << endl; - os << "};"; } diff --git a/odb/relational/mysql/source.cxx b/odb/relational/mysql/source.cxx index 8f80a5a..bea559e 100644 --- a/odb/relational/mysql/source.cxx +++ b/odb/relational/mysql/source.cxx @@ -885,7 +885,7 @@ namespace relational << "// cannot be initialized from an object pointer." << endl << "//" << endl << member << " = ptr_traits::pointer_type (" << endl - << "db.load< ptr_traits::element_type > (id));"; + << "db.load< obj_traits::object_type > (id));"; os << "}" << "}"; diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 6c4a656..5b77e41 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -761,7 +761,7 @@ namespace relational << "// cannot be initialized from an object pointer." << endl << "//" << endl << member << " = ptr_traits::pointer_type (" << endl - << "db.load< ptr_traits::element_type > (id));"; + << "db.load< obj_traits::object_type > (id));"; os << "}" << "}"; diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 92a406b..3474f15 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -2706,12 +2706,9 @@ namespace relational { // query () // - os << "template<>" << endl - << "result< " << traits << "::object_type >" << endl + os << "result< " << traits << "::object_type >" << endl << traits << "::" << endl - << "query< " << traits << "::object_type > (" << endl - << "database& db," << endl - << "const query_base_type& q)" + << "query (database&, const query_base_type& q)" << "{" << "using namespace " << db << ";" << "using odb::details::shared;" @@ -2722,55 +2719,6 @@ namespace relational << endl << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find_object<object_type> ());" - << "shared_ptr<select_statement> st;" - << endl - << "query_ (db, q, sts, st);" - << endl - << "shared_ptr<odb::result_impl<object_type, " << - "class_object> > r (" << endl - << "new (shared) " << db << - "::result_impl<object_type, class_object> (" << endl - << "q, st, sts));" - << endl - << "return result<object_type> (r);" - << "}"; - - os << "template<>" << endl - << "result< const " << traits << "::object_type >" << endl - << traits << "::" << endl - << "query< const " << traits << "::object_type > (" << endl - << "database& db," << endl - << "const query_base_type& q)" - << "{" - << "using namespace " << db << ";" - << "using odb::details::shared;" - << "using odb::details::shared_ptr;" - << endl - << db << "::connection& conn (" << endl - << db << "::transaction::current ().connection ());" - << endl - << "object_statements< object_type >& sts (" << endl - << "conn.statement_cache ().find_object<object_type> ());" - << "shared_ptr<select_statement> st;" - << endl - << "query_ (db, q, sts, st);" - << endl - << "shared_ptr<odb::result_impl<" << - "const object_type, class_object> > r (" << endl - << "new (shared) " << db << - "::result_impl<const object_type, class_object> (" << endl - << "q, st, sts));" - << endl - << "return result<const object_type> (r);" - << "}"; - - os << "void " << traits << "::" << endl - << "query_ (database&," << endl - << "const query_base_type& q," << endl - << db << "::object_statements< object_type >& sts," << endl - << "odb::details::shared_ptr<" << db << "::select_statement>& st)" - << "{" - << "using namespace " << db << ";" << endl << "image_type& im (sts.image ());" << "binding& imb (sts.out_image_binding ());" @@ -2781,8 +2729,8 @@ namespace relational << "sts.out_image_version (im.version);" << "imb.version++;" << "}" - << "st.reset (new (odb::details::shared) select_statement (" - << endl; + << "shared_ptr<select_statement> st (" << endl + << "new (shared) select_statement (" << endl; object_query_statement_ctor_args (c); @@ -2791,7 +2739,15 @@ namespace relational post_query_ (c); - os << "}"; + os << endl + << "shared_ptr<odb::result_impl<object_type, " << + "class_object> > r (" << endl + << "new (shared) " << db << + "::result_impl<object_type, class_object> (" << endl + << "q, st, sts));" + << endl + << "return result<object_type> (r);" + << "}"; // erase_query // diff --git a/odb/relational/sqlite/source.cxx b/odb/relational/sqlite/source.cxx index 4a2b0ab..8b02e6c 100644 --- a/odb/relational/sqlite/source.cxx +++ b/odb/relational/sqlite/source.cxx @@ -512,7 +512,7 @@ namespace relational << "// cannot be initialized from an object pointer." << endl << "//" << endl << member << " = ptr_traits::pointer_type (" << endl - << "db.load< ptr_traits::element_type > (id));"; + << "db.load< obj_traits::object_type > (id));"; os << "}" << "}"; |