aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-09-15 13:43:39 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-09-15 13:43:39 +0200
commitc17f5ff5b2f1523e92e048623f51638f83b34022 (patch)
treedce2d719943a49ff8e4160b691423d6312ff94d5
parent51956f409ec7ebea8b6790b0c5d4f0b51513d683 (diff)
Diagnose change of polymorphic base, table kind
-rw-r--r--odb/relational/changelog.cxx55
-rw-r--r--odb/relational/model.hxx7
-rw-r--r--odb/relational/schema.hxx6
-rw-r--r--odb/relational/sqlite/schema.cxx6
4 files changed, 58 insertions, 16 deletions
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<location> ("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<foreign_key> ()))
+ {
+ location const& l (t.get<location> ("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<location> ("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> (""));
primary_key& dkey (*t.find<primary_key> (""));