aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-08-19 11:08:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-08-19 11:08:12 +0200
commit6ed5736f519caf6f3637051a2e142e8ce6575707 (patch)
treed6ba6e102b2388337ae69b6f3055dc1da5b78840
parent280c36de4544fc17dc3d4f1ea168e7d2dc859129 (diff)
Make container object_id reference the object
Make it ON DELETE CASCADE. Also in erase(), delete the container rows first.
-rw-r--r--odb/relational/pgsql/schema.cxx40
-rw-r--r--odb/relational/schema.hxx15
-rw-r--r--odb/relational/source.hxx14
3 files changed, 56 insertions, 13 deletions
diff --git a/odb/relational/pgsql/schema.cxx b/odb/relational/pgsql/schema.cxx
index 6530e82..191d522 100644
--- a/odb/relational/pgsql/schema.cxx
+++ b/odb/relational/pgsql/schema.cxx
@@ -136,20 +136,36 @@ namespace relational
virtual bool
column (semantics::data_member& m, string const& name, bool)
{
- semantics::class_* c (object_pointer (member_type (m, prefix_)));
+ if (inverse (m))
+ return false;
- if (c != 0 && !inverse (m))
+ if (semantics::class_* c = object_pointer (member_type (m, prefix_)))
{
pre_statement ();
os << "ALTER TABLE " << quote_id (table_) << endl
- << " ADD FOREIGN KEY (" << quote_id (name) << ")" <<
- endl
- << " REFERENCES " << quote_id (table_name (*c)) << endl
+ << " ADD FOREIGN KEY (" << quote_id (name) << ")" << endl
+ << " REFERENCES " << table_qname (*c) << endl
<< " INITIALLY DEFERRED" << endl;
post_statement ();
}
+ else if (prefix_ == "id")
+ {
+ semantics::class_& c (*context::top_object);
+
+ pre_statement ();
+
+ // We don't need INITIALLY DEFERRED here since the object row
+ // must exist before any container row.
+ //
+ os << "ALTER TABLE " << quote_id (table_) << endl
+ << " ADD FOREIGN KEY (" << quote_id (name) << ")" << endl
+ << " REFERENCES " << table_qname (c) << endl
+ << " ON DELETE CASCADE" << endl;
+
+ post_statement ();
+ }
return true;
}
@@ -188,6 +204,16 @@ namespace relational
type& t (m.type ());
type& vt (container_vt (t));
+ // object_id
+ //
+ {
+ object_columns_references ocr (e_, os_, name, "id");
+ string id_name (column_name (m, "id", "object_id"));
+ ocr.column (m, id_name, true);
+ }
+
+ // value
+ //
if (semantics::class_* cvt = comp_value (vt))
{
object_columns_references ocr (e_, os_, name);
@@ -196,8 +222,8 @@ namespace relational
else
{
object_columns_references ocr (e_, os_, name, "value");
- string const& name (column_name (m, "value", "value"));
- ocr.column (m, name, true);
+ string const& value_name (column_name (m, "value", "value"));
+ ocr.column (m, value_name, true);
}
tables_.insert (name);
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index 6ada960..9dbe067 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -277,8 +277,19 @@ namespace relational
{
if (semantics::class_* c = object_pointer (member_type (m, prefix_)))
{
- os << " REFERENCES " << quote_id (table_name (*c)) << " (" <<
- quote_id (column_name (*id_member (*c))) << ")";
+ os << " REFERENCES " << table_qname (*c) << " (" <<
+ column_qname (*id_member (*c)) << ")";
+ }
+ else if (prefix_ == "id")
+ {
+ // Container id column references the object table. It also
+ // cascades on delete so that we can delete the object with
+ // a single delete statement (needed for query_erase()).
+ //
+ semantics::class_& c (*context::top_object);
+
+ os << " REFERENCES " << table_qname (c) << " (" <<
+ column_qname (*id_member (c)) << ") ON DELETE CASCADE";
}
}
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index 6f80bbe..741b97d 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -2279,17 +2279,23 @@ namespace relational
<< "bind (idb.bind, i);"
<< "sts.id_image_version (i.version);"
<< "idb.version++;"
- << "}"
- << "if (sts.erase_statement ().execute () != 1)" << endl
- << "throw object_not_persistent ();";
+ << "}";
+ // Erase containers first so that there are no reference
+ // violations (we don't want to reply on ON DELETE CASCADE
+ // here since in case of a custom schema, it might not be
+ // there).
+ //
if (straight_containers)
{
- os << endl;
instance<container_calls> t (container_calls::erase_call);
t->traverse (c);
+ os << endl;
}
+ os << "if (sts.erase_statement ().execute () != 1)" << endl
+ << "throw object_not_persistent ();";
+
os << "}";
// find ()