aboutsummaryrefslogtreecommitdiff
path: root/odb/relational
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-12-04 11:30:33 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-12-04 11:30:33 +0200
commit3417fc7c0df3b1b01750874587c4f3bb2ef02f45 (patch)
treea35f2439f7f72212d8ad05d3b8175e992d9a917f /odb/relational
parenta0bf13c2522cc9c029af53f40970a3d0c19e178f (diff)
Implement on_delete pragma for object pointers
Translates to the ON DELETE SQL clause.
Diffstat (limited to 'odb/relational')
-rw-r--r--odb/relational/mssql/schema.cxx19
-rw-r--r--odb/relational/mysql/schema.cxx18
-rw-r--r--odb/relational/schema.hxx10
-rw-r--r--odb/relational/validator.cxx38
4 files changed, 83 insertions, 2 deletions
diff --git a/odb/relational/mssql/schema.cxx b/odb/relational/mssql/schema.cxx
index 2480e75..7b6c7ca 100644
--- a/odb/relational/mssql/schema.cxx
+++ b/odb/relational/mssql/schema.cxx
@@ -237,6 +237,20 @@ namespace relational
{
create_foreign_key (base const& x): base (x) {}
+ void
+ diagnose (sema_rel::foreign_key& fk)
+ {
+ if (fk.on_delete () != sema_rel::foreign_key::no_action)
+ {
+ cerr << "warning: foreign key '" << fk.name () << "' has " <<
+ "ON DELETE clause but is disabled in SQL Server due to lack "
+ "of deferrable constraint support" << endl;
+
+ cerr << "info: consider using non-deferrable foreign keys (" <<
+ "--fkeys-deferrable-mode)" << endl;
+ }
+ }
+
virtual void
traverse_create (sema_rel::foreign_key& fk)
{
@@ -248,6 +262,8 @@ namespace relational
base::traverse_create (fk);
else
{
+ diagnose (fk);
+
// Don't bloat C++ code with comment strings if we are
// generating embedded schema.
//
@@ -268,6 +284,9 @@ namespace relational
{
bool c (!fk.not_deferrable () && !in_comment);
+ if (c)
+ diagnose (fk);
+
if (c && format_ != schema_format::sql)
return;
diff --git a/odb/relational/mysql/schema.cxx b/odb/relational/mysql/schema.cxx
index f06914a..473e746 100644
--- a/odb/relational/mysql/schema.cxx
+++ b/odb/relational/mysql/schema.cxx
@@ -145,6 +145,20 @@ namespace relational
{
create_foreign_key (base const& x): base (x) {}
+ void
+ diagnose (sema_rel::foreign_key& fk)
+ {
+ if (fk.on_delete () != sema_rel::foreign_key::no_action)
+ {
+ cerr << "warning: foreign key '" << fk.name () << "' has " <<
+ "ON DELETE clause but is disabled in MySQL due to lack "
+ "of deferrable constraint support" << endl;
+
+ cerr << "info: consider using non-deferrable foreign keys (" <<
+ "--fkeys-deferrable-mode)" << endl;
+ }
+ }
+
virtual void
traverse_create (sema_rel::foreign_key& fk)
{
@@ -156,6 +170,8 @@ namespace relational
base::traverse_create (fk);
else
{
+ diagnose (fk);
+
// Don't bloat C++ code with comment strings if we are
// generating embedded schema.
//
@@ -178,6 +194,8 @@ namespace relational
base::traverse_add (fk);
else
{
+ diagnose (fk);
+
if (format_ != schema_format::sql)
return;
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index 0de7036..4903e3a 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -857,14 +857,20 @@ namespace relational
switch (a)
{
+ case foreign_key::no_action:
+ break;
case foreign_key::cascade:
{
os << endl
<< " ON DELETE CASCADE";
break;
}
- case foreign_key::no_action:
- break;
+ case foreign_key::set_null:
+ {
+ os << endl
+ << " ON DELETE SET NULL";
+ break;
+ }
}
}
diff --git a/odb/relational/validator.cxx b/odb/relational/validator.cxx
index c620a58..3218b57 100644
--- a/odb/relational/validator.cxx
+++ b/odb/relational/validator.cxx
@@ -51,6 +51,44 @@ namespace relational
}
}
}
+
+ // Check on-delete.
+ //
+ if (m.count ("on-delete"))
+ {
+ const char* kp (container (m) ? "value" : "");
+ location l (m.location ());
+
+ // Make sure it is a pointer.
+ //
+ if (!object_pointer (member_utype (m, kp)))
+ {
+ error (l) << "on_delete specified for non-object pointer" << endl;
+ valid_ = false;
+ }
+
+ // Make sure it is not inverse.
+ //
+ if (inverse (m, kp))
+ {
+ error (l) << "on_delete specified for inverse object " <<
+ "pointer" << endl;
+ valid_ = false;
+ }
+
+ // Make sure the pointer is nullable if asked to set it to NULL.
+ //
+ using sema_rel::foreign_key;
+
+ if (m.get<foreign_key::action_type> ("on-delete") ==
+ foreign_key::set_null &&
+ !null (m, kp))
+ {
+ error (l) << "set_null specified for non-nullable object "
+ "pointer" << endl;
+ valid_ = false;
+ }
+ }
}
bool& valid_;