From b79afa6dbea19905b2a035365274616dd1dae2b1 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 22 Aug 2011 11:47:55 +0200 Subject: Add database::erase_query() function New test: common/erase-query. Documentation is in Section 3.9, "Deleting Persistent Objects". The current implementation does not work well with the session (no removal of the erased objects from the cache). --- NEWS | 6 ++++ doc/manual.xhtml | 48 ++++++++++++++++++++++--- odb/relational/header.hxx | 13 ++++++- odb/relational/pgsql/header.cxx | 3 +- odb/relational/pgsql/source.cxx | 28 ++++++++++----- odb/relational/source.hxx | 77 +++++++++++++++++++++++++++++++---------- 6 files changed, 141 insertions(+), 34 deletions(-) diff --git a/NEWS b/NEWS index 0d5db63..2cc9f12 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,12 @@ Version 1.6.0 call to schema_catalog::create_schema()). For more information, refer to Section 12.5.3, "Foreign Key Constraints" in the ODB manual. + * New function, database::erase_query(), allows the deletion of the + database state of multiple objects matching certain criteria. It uses + the same query expression as the database::query() function. For more + information, refer to Section 3.9, "Deleting Persistent Objects" in + the ODB manual. + * Support for value wrappers. An ODB value wrapper is a class template that wraps a value type. Common examples of wrappers are smart pointers, holders, and "optional value" containers such as boost::optional. A diff --git a/doc/manual.xhtml b/doc/manual.xhtml index 246f4af..e5c7419 100644 --- a/doc/manual.xhtml +++ b/doc/manual.xhtml @@ -2657,10 +2657,10 @@ transfer (database& db,

3.9 Deleting Persistent Objects

To delete a persistent object's state from the database we use the - database::erase() function template. If the application - still has an instance of the erased object, this instance becomes - transient. The erase() function has the following - overloaded versions:

+ database::erase() or database::erase_query() + function templates. If the application still has an instance of the + erased object, this instance becomes transient. The erase() + function has the following overloaded versions:

   template <typename T>
@@ -2709,6 +2709,43 @@ db.erase<person> (joe_id);
 t.commit ();
   
+

The erase_query() function allows us to delete + the state of multiple objects matching certain criteria. It uses + the query expression of the database::query() function + (Chapter 4, "Querying the Database") and, + because the ODB query facility is optional, it is only available + if the --generate-query ODB compiler option was + specified. The erase_query() function has the + following overloaded versions:

+ +
+  template <typename T>
+  unsigned long long
+  erase_query ();
+
+  template <typename T>
+  unsigned long long
+  erase_query (const odb::query<T>&);
+  
+ +

The first erase_query() function is used to delete + the state of all the persistent objects of a given type stored + in the database. The second function uses the passed query instance + to only delete the state of objects matching the query criteria. + Both functions return the number of objects erased. When calling + the erase_query() function, we have to explicitly + specify the object type we are erasing. For example:

+ +
+typedef odb::query<person> query;
+
+transaction t (db.begin ());
+
+db.erase_query<person> (query::last == "Doe" && query::are < 30);
+
+t.commit ();
+  
+

3.10 Executing Native SQL Statements

In some situations we may need to execute native SQL statements @@ -8926,7 +8963,8 @@ class person

If foreign key constraints checking is disabled or not available, then inconsistencies in object relationships will not be detected. - Furthermore, using the erase_query() function (@@ ref) + Furthermore, using the erase_query() function + (Section 3.9, "Deleting Persistent Objects") to delete persistent objects that contain containers will not work correctly. Container data for such objects will not be deleted.

diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx index ceca095..49de640 100644 --- a/odb/relational/header.hxx +++ b/odb/relational/header.hxx @@ -948,7 +948,12 @@ namespace relational << "static const char* const erase_statement;"; if (options.generate_query ()) - os << "static const char* const query_clause;"; + { + os << "static const char* const query_clause;" + << "static const char* const erase_query_clause;" + << endl + << "static const char* const table_name;"; + } os << endl; @@ -999,11 +1004,17 @@ namespace relational // query () // if (options.generate_query ()) + { os << "template" << endl << "static result" << endl << "query (database&, const query_type&);" << endl; + os << "static unsigned long long" << endl + << "erase_query (database&, const query_type&);" + << endl; + } + // create_schema () // if (embedded_schema) diff --git a/odb/relational/pgsql/header.cxx b/odb/relational/pgsql/header.cxx index 64b02d8..edf9355 100644 --- a/odb/relational/pgsql/header.cxx +++ b/odb/relational/pgsql/header.cxx @@ -36,7 +36,8 @@ namespace relational // Query statement name. // if (options.generate_query ()) - os << "static const char* const query_statement_name;"; + os << "static const char* const query_statement_name;" + << "static const char* const erase_query_statement_name;"; os << endl; diff --git a/odb/relational/pgsql/source.cxx b/odb/relational/pgsql/source.cxx index 83aa8c4..bfc26ba 100644 --- a/odb/relational/pgsql/source.cxx +++ b/odb/relational/pgsql/source.cxx @@ -873,6 +873,10 @@ namespace relational { os << name_decl << endl << "query_statement_name = " << strlit (fn + "_query") << ";" + << endl + << name_decl << endl + << "erase_query_statement_name = " << + strlit (fn + "_erase_query") << ";" << endl; } @@ -936,21 +940,29 @@ namespace relational } virtual void - query_statement_ctor (type& c) + query_statement_ctor_args (type&) { - string const& type (c.fq_name ()); - string traits ("access::object_traits< " + type + " >"); - - os << "select_statement (" << endl - << "sts.connection ()," << endl + os << "sts.connection ()," << endl << "query_statement_name," << endl - << "query_clause + q.clause ()," << endl + << "query_clause + q.clause (table_name)," << endl << "q.parameter_types ()," << endl << "q.parameter_count ()," << endl << "q.parameters_binding ()," << endl - << "imb)"; + << "imb"; + } + + virtual void + erase_query_statement_ctor_args (type&) + { + os << "conn," << endl + << "erase_query_statement_name," << endl + << "erase_query_clause + q.clause (table_name)," << endl + << "q.parameter_types ()," << endl + << "q.parameter_count ()," << endl + << "q.parameters_binding ()"; } + virtual void post_query_ (type&) { diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx index 9289206..14589ac 100644 --- a/odb/relational/source.hxx +++ b/odb/relational/source.hxx @@ -1872,13 +1872,20 @@ namespace relational } virtual void - query_statement_ctor (type&) + query_statement_ctor_args (type&) { - os << "select_statement (" << endl - << "sts.connection ()," << endl - << "query_clause + q.clause ()," << endl + os << "sts.connection ()," << endl + << "query_clause + q.clause (table_name)," << endl << "q.parameters_binding ()," << endl - << "imb)"; + << "imb"; + } + + virtual void + erase_query_statement_ctor_args (type&) + { + os << "conn," << endl + << "erase_query_clause + q.clause (table_name)," << endl + << "q.parameters_binding ()"; } virtual void @@ -2147,10 +2154,10 @@ namespace relational << endl; } - // query_clause - // if (options.generate_query ()) { + // query_clause + // bool t (true); instance oj (c, t); //@@ (im)perfect forwarding oj->traverse (c); @@ -2170,6 +2177,18 @@ namespace relational oj->write (); os << strlit (" ") << ";" << endl; + + // erase_query_clause + // + os << "const char* const " << traits << "::erase_query_clause =" << endl + << strlit ("DELETE FROM " + table + " ") << ";" + << endl; + + // table_name + // + os << "const char* const " << traits << "::table_name =" << endl + << strlit (table) << ";" + << endl; } // persist () @@ -2180,7 +2199,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2242,7 +2261,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2294,7 +2313,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2341,7 +2360,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2383,7 +2402,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << "object_statements< object_type >& sts (" << endl << "conn.statement_cache ().find ());" @@ -2487,10 +2506,10 @@ namespace relational os << "}"; } - // query () - // if (options.generate_query ()) { + // query () + // os << "template<>" << endl << "result< " << traits << "::object_type >" << endl << traits << "::" << endl @@ -2500,7 +2519,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl @@ -2524,7 +2543,7 @@ namespace relational << "{" << "using namespace " << db << ";" << endl - << "connection& conn (" << db << + << db << "::connection& conn (" << db << "::transaction::current ().connection ());" << endl << "object_statements< object_type >& sts (" << endl @@ -2556,16 +2575,36 @@ namespace relational << "sts.out_image_version (im.version);" << "imb.version++;" << "}" - << "st.reset (new (odb::details::shared) "; + << "st.reset (new (odb::details::shared) select_statement (" + << endl; - query_statement_ctor (c); + query_statement_ctor_args (c); - os << ");" << endl + os << "));" << endl << "st->execute ();"; post_query_ (c); os << "}"; + + // erase_query + // + os << "unsigned long long " << traits << "::" << endl + << "erase_query (database&, const query_type& q)" + << "{" + << "using namespace " << db << ";" + << endl + << db << "::connection& conn (" << db << + "::transaction::current ().connection ());" + << endl + << "delete_statement st (" << endl; + + erase_query_statement_ctor_args (c); + + os << ");" + << endl + << "return st.execute ();" + << "}"; } if (embedded_schema) -- cgit v1.1