From c17f5ff5b2f1523e92e048623f51638f83b34022 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 15 Sep 2013 13:43:39 +0200 Subject: Diagnose change of polymorphic base, table kind --- odb/relational/changelog.cxx | 55 +++++++++++++++++++++++++++++++++++----- odb/relational/model.hxx | 7 +++-- odb/relational/schema.hxx | 6 ++--- odb/relational/sqlite/schema.cxx | 6 ++--- 4 files changed, 58 insertions(+), 16 deletions(-) (limited to 'odb') diff --git a/odb/relational/changelog.cxx b/odb/relational/changelog.cxx index bb8399a..a66a9e3 100644 --- a/odb/relational/changelog.cxx +++ b/odb/relational/changelog.cxx @@ -277,6 +277,8 @@ namespace relational diagnose_foreign_key (fk, "on delete action"); if (fk.referenced_table () != ofk->referenced_table ()) + // See diagnose_foreign_key() if changing this name. + // diagnose_foreign_key (fk, "pointed-to class"); if (fk.referenced_columns () != ofk->referenced_columns ()) @@ -409,13 +411,50 @@ namespace relational void diagnose_foreign_key (sema_rel::foreign_key& fk, char const* name) { - location const& l (fk.get ("cxx-location")); + // This can be an object pointer or a polymorphic base link. + // The latter will trigger this call if we change one base + // to another. + // + using sema_rel::table; + using sema_rel::foreign_key; - error (l) << "changing object pointer " << name << " is not " << - "supported" << endl; - info (l) << "consider re-implementing this change by adding " << - "a new object pointer with the desired " << name << ", " << - "migrating the data, and deleteing the old pointer" << endl; + // Polymorphic base link is the first foreign key. + // + table& t (fk.table ()); + table::names_iterator p (t.find (fk.name ())); + + if (t.extra ()["kind"] == "polymorphic derived object" && + (p == t.names_begin () || !(--p)->is_a ())) + { + location const& l (t.get ("cxx-location")); + + if (name == string ("pointed-to class")) + { + error (l) << "changing polymorphic base is not " << + "supported" << endl; + info (l) << "consider re-implementing this change by adding " << + "a new derived class with the desired base, migrating the " << + "data, and deleteing the old class" << endl; + } + else + { + error (l) << "changing polymorphic base " << name << + " is not supported" << endl; + info (l) << "consider re-implementing this change by adding " << + "a new derived class with the desired " << name << ", " << + "migrating the data, and deleteing the old class" << endl; + } + } + else + { + location const& l (fk.get ("cxx-location")); + + error (l) << "changing object pointer " << name << " is not " << + "supported" << endl; + info (l) << "consider re-implementing this change by adding " << + "a new object pointer with the desired " << name << ", " << + "migrating the data, and deleteing the old pointer" << endl; + } throw operation_failed (); } @@ -498,6 +537,10 @@ namespace relational if (t.options () != ot->options ()) diagnose_table (t, "options", ot->options (), t.options ()); + if (ot->extra ()["kind"] != t.extra ()["kind"]) + diagnose_table (t, "kind", + ot->extra ()["kind"], t.extra ()["kind"]); + { trav_rel::table table; trav_rel::unames names; diff --git a/odb/relational/model.hxx b/odb/relational/model.hxx index 325e614..3ff5e06 100644 --- a/odb/relational/model.hxx +++ b/odb/relational/model.hxx @@ -766,8 +766,11 @@ namespace relational t.options (table_options (c)); - if (poly != 0 && poly != &c) - t.extra ()["kind"] = "polymorphic"; + t.extra ()["kind"] =(poly == 0 + ? "object" + : (poly == &c + ? "polymorphic root object" + : "polymorphic derived object")); // Add columns. // diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx index 3edb6b2..93850a6 100644 --- a/odb/relational/schema.hxx +++ b/odb/relational/schema.hxx @@ -377,9 +377,7 @@ namespace relational } else { - if (migration && - t.extra ().count ("kind") != 0 && - t.extra ()["kind"] == "polymorphic") + if (migration && t.extra ()["kind"] == "polymorphic derived object") { // If we are dropping a polymorphic derived object, then we // also have to clean the base tables. Note that this won't @@ -416,7 +414,7 @@ namespace relational assert (rkey.contains_size () == dkey.contains_size ()); delete_ (p->name (), t.name (), rkey, dkey); } - while (p->extra ().count ("kind") != 0); + while (p->extra ()["kind"] != "polymorphic root object"); } drop (t, migration); diff --git a/odb/relational/sqlite/schema.cxx b/odb/relational/sqlite/schema.cxx index 24bc2ef..ac9a753 100644 --- a/odb/relational/sqlite/schema.cxx +++ b/odb/relational/sqlite/schema.cxx @@ -54,9 +54,7 @@ namespace relational // around this problem is to delete from the root table and rely // on the cascade to clean up the rest. // - if (migration && - t.extra ().count ("kind") != 0 && - t.extra ()["kind"] == "polymorphic") + if (migration && t.extra ()["kind"] == "polymorphic derived object") { using sema_rel::model; using sema_rel::table; @@ -82,7 +80,7 @@ namespace relational } } } - while (p->extra ().count ("kind") != 0); + while (p->extra ()["kind"] != "polymorphic root object"); primary_key& rkey (*p->find ("")); primary_key& dkey (*t.find ("")); -- cgit v1.1