From 6ed5736f519caf6f3637051a2e142e8ce6575707 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 19 Aug 2011 11:08:12 +0200 Subject: Make container object_id reference the object Make it ON DELETE CASCADE. Also in erase(), delete the container rows first. --- odb/relational/pgsql/schema.cxx | 40 +++++++++++++++++++++++++++++++++------- odb/relational/schema.hxx | 15 +++++++++++++-- odb/relational/source.hxx | 14 ++++++++++---- 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 t (container_calls::erase_call); t->traverse (c); + os << endl; } + os << "if (sts.erase_statement ().execute () != 1)" << endl + << "throw object_not_persistent ();"; + os << "}"; // find () -- cgit v1.1