aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-08-22 11:47:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-08-22 11:47:55 +0200
commitb79afa6dbea19905b2a035365274616dd1dae2b1 (patch)
tree428110d79f2dfdeaef4405c5b27cd2fdd1ab969b
parent3e57c662b42831555498607d607c349f30c5b7de (diff)
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).
-rw-r--r--NEWS6
-rw-r--r--doc/manual.xhtml48
-rw-r--r--odb/relational/header.hxx13
-rw-r--r--odb/relational/pgsql/header.cxx3
-rw-r--r--odb/relational/pgsql/source.cxx28
-rw-r--r--odb/relational/source.hxx77
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&amp; db,
<h2><a name="3.9">3.9 Deleting Persistent Objects</a></h2>
<p>To delete a persistent object's state from the database we use the
- <code>database::erase()</code> function template. If the application
- still has an instance of the erased object, this instance becomes
- transient. The <code>erase()</code> function has the following
- overloaded versions:</p>
+ <code>database::erase()</code> or <code>database::erase_query()</code>
+ function templates. If the application still has an instance of the
+ erased object, this instance becomes transient. The <code>erase()</code>
+ function has the following overloaded versions:</p>
<pre class="c++">
template &lt;typename T>
@@ -2709,6 +2709,43 @@ db.erase&lt;person> (joe_id);
t.commit ();
</pre>
+ <p>The <code>erase_query()</code> function allows us to delete
+ the state of multiple objects matching certain criteria. It uses
+ the query expression of the <code>database::query()</code> function
+ (<a href="#4">Chapter 4, "Querying the Database"</a>) and,
+ because the ODB query facility is optional, it is only available
+ if the <code>--generate-query</code> ODB compiler option was
+ specified. The <code>erase_query()</code> function has the
+ following overloaded versions:</p>
+
+ <pre class="c++">
+ template &lt;typename T>
+ unsigned long long
+ erase_query ();
+
+ template &lt;typename T>
+ unsigned long long
+ erase_query (const odb::query&lt;T>&amp;);
+ </pre>
+
+ <p>The first <code>erase_query()</code> 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 <code>erase_query()</code> function, we have to explicitly
+ specify the object type we are erasing. For example:</p>
+
+ <pre class="c++">
+typedef odb::query&lt;person> query;
+
+transaction t (db.begin ());
+
+db.erase_query&lt;person> (query::last == "Doe" &amp;&amp; query::are &lt; 30);
+
+t.commit ();
+ </pre>
+
<h2><a name="3.10">3.10 Executing Native SQL Statements</a></h2>
<p>In some situations we may need to execute native SQL statements
@@ -8926,7 +8963,8 @@ class person
<p>If foreign key constraints checking is disabled or not available,
then inconsistencies in object relationships will not be detected.
- Furthermore, using the <code>erase_query()</code> function (@@ ref)
+ Furthermore, using the <code>erase_query()</code> function
+ (<a href="#3.9">Section 3.9, "Deleting Persistent Objects"</a>)
to delete persistent objects that contain containers will not work
correctly. Container data for such objects will not be deleted.</p>
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<typename T>" << endl
<< "static result<T>" << 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<object_joins> 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<object_type> ());"
@@ -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<object_type> ());"
@@ -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<object_type> ());"
@@ -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<object_type> ());"
@@ -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<object_type> ());"
@@ -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)