aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-03-28 16:04:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-04-10 18:46:44 +0200
commit2aa3cabf1b737e225178230882ee9aadfd817ce0 (patch)
tree85a6c7a90f8483ca11a4bc825cd2ef22114c3d97
parente999b1e7295acd8cdb646c2db7db1f5059f10c7d (diff)
Add changelog support for add/drop index/foreign key
Also diagnose changes to primary keys and establish the 'alters' association.
-rw-r--r--odb/relational/changelog.cxx357
-rw-r--r--odb/semantics/relational/changelog.cxx84
-rw-r--r--odb/semantics/relational/changeset.cxx10
-rw-r--r--odb/semantics/relational/changeset.hxx4
-rw-r--r--odb/semantics/relational/column.cxx29
-rw-r--r--odb/semantics/relational/column.hxx58
-rw-r--r--odb/semantics/relational/elements.cxx38
-rw-r--r--odb/semantics/relational/elements.hxx95
-rw-r--r--odb/semantics/relational/elements.txx39
-rw-r--r--odb/semantics/relational/foreign-key.cxx81
-rw-r--r--odb/semantics/relational/foreign-key.hxx48
-rw-r--r--odb/semantics/relational/index.cxx75
-rw-r--r--odb/semantics/relational/index.hxx48
-rw-r--r--odb/semantics/relational/key.cxx4
-rw-r--r--odb/semantics/relational/key.hxx14
-rw-r--r--odb/semantics/relational/model.cxx4
-rw-r--r--odb/semantics/relational/name.hxx12
-rw-r--r--odb/semantics/relational/table.cxx33
-rw-r--r--odb/semantics/relational/table.hxx18
-rw-r--r--odb/traversal/relational/foreign-key.hxx3
-rw-r--r--odb/traversal/relational/index.hxx2
21 files changed, 927 insertions, 129 deletions
diff --git a/odb/relational/changelog.cxx b/odb/relational/changelog.cxx
index 530c3a0..2208078 100644
--- a/odb/relational/changelog.cxx
+++ b/odb/relational/changelog.cxx
@@ -26,7 +26,10 @@ namespace relational
// diff
//
- struct diff_table: trav_rel::column
+ struct diff_table: trav_rel::column,
+ trav_rel::primary_key,
+ trav_rel::foreign_key,
+ trav_rel::index
{
enum mode_type {mode_add, mode_drop};
@@ -43,20 +46,28 @@ namespace relational
if (column* oc = other.find<column> (c.name ()))
{
if (c.type () != oc->type ())
- diagnose_unsupported (c, "type");
+ diagnose_column (c, "type", oc->type (), c.type ());
if (c.null () != oc->null ())
{
alter_column& ac (g.new_node<alter_column> (c.id ()));
+
+ // Set the alters edge.
+ //
+ column* b (at.lookup<column, drop_column> (c.name ()));
+ assert (b != 0);
+ g.new_edge<alters> (ac, *b);
+
ac.null (c.null ());
g.new_edge<unames> (at, ac, c.name ());
}
if (c.default_ () != oc->default_ ())
- diagnose_unsupported (c, "default value");
+ diagnose_column (
+ c, "default value", oc->default_ (), c.default_ ());
if (c.options () != oc->options ())
- diagnose_unsupported (c, "options");
+ diagnose_column (c, "options", oc->options (), c.options ());
}
else
{
@@ -66,7 +77,7 @@ namespace relational
}
else
{
- if (other.find<sema_rel::column> (c.name ()) == 0)
+ if (other.find<column> (c.name ()) == 0)
{
drop_column& dc (g.new_node<drop_column> (c.id ()));
g.new_edge<unames> (at, dc, c.name ());
@@ -74,27 +85,244 @@ namespace relational
}
}
+ virtual void
+ traverse (sema_rel::primary_key& pk)
+ {
+ using sema_rel::primary_key;
+
+ if (mode == mode_add)
+ {
+ if (primary_key* opk = other.find<primary_key> (pk.name ()))
+ {
+ if (pk.auto_ () != opk->auto_ ())
+ diagnose_primary_key (pk, "auto kind");
+
+ if (pk.contains_size () != opk->contains_size ())
+ diagnose_primary_key (pk, "member set");
+
+ for (primary_key::contains_size_type i (0);
+ i != pk.contains_size (); ++i)
+ {
+ sema_rel::contains& c (pk.contains_at (i));
+ sema_rel::contains& oc (opk->contains_at (i));
+
+ if (c.column ().name () != oc.column ().name ())
+ diagnose_primary_key (pk, "member set");
+ }
+ }
+ else
+ {
+ location const& l (pk.get<location> ("cxx-location"));
+ error (l) << "adding object id to an existing class is " <<
+ "not supported" << endl;
+ info (l) << "consider re-implementing this change by adding " <<
+ "a new class with the object id, migrating the data, and " <<
+ "deleteing the old class" << endl;
+ throw operation_failed ();
+ }
+ }
+ else
+ {
+ if (other.find<primary_key> (pk.name ()) == 0)
+ {
+ location const& l (other.get<location> ("cxx-location"));
+ error (l) << "deleting object id from an existing class is " <<
+ "not supported" << endl;
+ info (l) << "consider re-implementing this change by adding " <<
+ "a new class without the object id, migrating the data, " <<
+ "and deleteing the old class" << endl;
+ throw operation_failed ();
+ }
+ }
+ }
+
+ virtual void
+ traverse (sema_rel::foreign_key& fk)
+ {
+ using sema_rel::foreign_key;
+
+ if (mode == mode_add)
+ {
+ if (foreign_key* ofk = other.find<foreign_key> (fk.name ()))
+ {
+ if (fk.deferred () != ofk->deferred ())
+ diagnose_foreign_key (fk, "deferred kind");
+
+ if (fk.on_delete () != ofk->on_delete ())
+ diagnose_foreign_key (fk, "on delete action");
+
+ if (fk.referenced_table () != ofk->referenced_table ())
+ diagnose_foreign_key (fk, "pointed-to class");
+
+ if (fk.referenced_columns () != ofk->referenced_columns ())
+ diagnose_foreign_key (fk, "id member set");
+
+ if (fk.contains_size () != ofk->contains_size ())
+ diagnose_foreign_key (fk, "id member set");
+
+ for (foreign_key::contains_size_type i (0);
+ i != fk.contains_size (); ++i)
+ {
+ sema_rel::contains& c (fk.contains_at (i));
+ sema_rel::contains& oc (ofk->contains_at (i));
+
+ if (c.column ().name () != oc.column ().name ())
+ diagnose_foreign_key (fk, "id member set");
+ }
+ }
+ else
+ {
+ add_foreign_key& afk (g.new_node<add_foreign_key> (fk, at, g));
+ g.new_edge<unames> (at, afk, fk.name ());
+ }
+ }
+ else
+ {
+ if (other.find<foreign_key> (fk.name ()) == 0)
+ {
+ drop_foreign_key& dfk (g.new_node<drop_foreign_key> (fk.id ()));
+ g.new_edge<unames> (at, dfk, fk.name ());
+ }
+ }
+ }
+
+ virtual void
+ traverse (sema_rel::index& i)
+ {
+ using sema_rel::index;
+
+ if (mode == mode_add)
+ {
+ if (index* oi = other.find<index> (i.name ()))
+ {
+ if (i.type () != oi->type ())
+ diagnose_index (i, "type", oi->type (), i.type ());
+
+ if (i.method () != oi->method ())
+ diagnose_index (i, "method", oi->method (), i.method ());
+
+ if (i.options () != oi->options ())
+ diagnose_index (i, "options", oi->options (), i.options ());
+
+ if (i.contains_size () != oi->contains_size ())
+ diagnose_index (i, "member set", "", "");
+
+ for (index::contains_size_type j (0);
+ j != i.contains_size (); ++j)
+ {
+ sema_rel::contains& c (i.contains_at (j));
+ sema_rel::contains& oc (oi->contains_at (j));
+
+ if (c.column ().name () != oc.column ().name ())
+ diagnose_index (i, "member set", "", "");
+
+ if (c.options () != oc.options ())
+ diagnose_index (
+ i, "member options", oc.options (), c.options ());
+ }
+ }
+ else
+ {
+ add_index& ai (g.new_node<add_index> (i, at, g));
+ g.new_edge<unames> (at, ai, i.name ());
+ }
+ }
+ else
+ {
+ if (other.find<index> (i.name ()) == 0)
+ {
+ drop_index& di (g.new_node<drop_index> (i.id ()));
+ g.new_edge<unames> (at, di, i.name ());
+ }
+ }
+ }
+
void
- diagnose_unsupported (sema_rel::column& c, char const* name)
+ diagnose_column (sema_rel::column& c,
+ char const* name,
+ string const& ov,
+ string const& nv)
{
table& t (c.table ());
location const& tl (t.get<location> ("cxx-location"));
location const& cl (c.get<location> ("cxx-location"));
error (cl) << "change to data member results in the change of " <<
- "the corresponding column " << name << endl;
+ "the corresponding column " << name;
+
+ if (!ov.empty () || !nv.empty ())
+ cerr << " (old: '" << ov << "', new: '" << nv << "')";
+
+ cerr << endl;
+
error (cl) << "this change is not yet handled automatically" << endl;
info (cl) << "corresponding column '" << c.name () << "' " <<
"originates here" << endl;
info (tl) << "corresponding table '" << t.name () << "' " <<
"originates here" << endl;
- info (cl) << "consider re-implementing this change by creating " <<
+ info (cl) << "consider re-implementing this change by adding " <<
"a new data member with the desired " << name << ", migrating " <<
"the data, and deleting the old data member" << endl;
throw operation_failed ();
}
+ void
+ diagnose_primary_key (sema_rel::primary_key& pk, char const* name)
+ {
+ location const& l (pk.get<location> ("cxx-location"));
+
+ error (l) << "changing object id " << name << " in an existing " <<
+ "class is not supported" << endl;
+ info (l) << "consider re-implementing this change by adding " <<
+ "a new class with the desired object id " << name << ", " <<
+ "migrating the data, and deleteing the old class" << endl;
+
+ throw operation_failed ();
+ }
+
+ void
+ diagnose_foreign_key (sema_rel::foreign_key& fk, char const* name)
+ {
+ 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 ();
+ }
+
+ void
+ diagnose_index (sema_rel::index& i,
+ char const* name,
+ string const& ov,
+ string const& nv)
+ {
+ table& t (i.table ());
+ location const& tl (t.get<location> ("cxx-location"));
+ location const& il (i.get<location> ("cxx-location"));
+
+ error (il) << "change to index " << name;
+
+ if (!ov.empty () || !nv.empty ())
+ cerr << " (old: '" << ov << "', new: '" << nv << "')";
+
+ cerr << " is not yet handled automatically" << endl;
+
+ info (il) << "corresponding index '" << i.name () << "' " <<
+ "originates here" << endl;
+ info (tl) << "corresponding table '" << t.name () << "' " <<
+ "originates here" << endl;
+ info (il) << "consider re-implementing this change by adding " <<
+ "a new index with the desired " << name << " and deleting the " <<
+ "old one" << endl;
+
+ throw operation_failed ();
+ }
+
protected:
table& other;
mode_type mode;
@@ -122,6 +350,12 @@ namespace relational
//
alter_table& at (g.new_node<alter_table> (t.id ()));
+ // Set the alters edge for lookup.
+ //
+ table* bt (cs.lookup<table, drop_table> (t.name ()));
+ assert (bt != 0);
+ alters& ae (g.new_edge<alters> (at, *bt));
+
{
trav_rel::table table;
trav_rel::unames names;
@@ -141,7 +375,10 @@ namespace relational
if (!at.names_empty ())
g.new_edge<qnames> (cs, at, t.name ());
else
+ {
+ g.delete_edge (at, *bt, ae);
g.delete_node (at);
+ }
}
else
{
@@ -171,14 +408,21 @@ namespace relational
// Assumes the new model has cxx-location set.
//
changeset&
- diff (model& o, model& n, graph& g)
+ diff (model& o, model& n, changelog& l)
{
- changeset& r (g.new_node<changeset> (n.version ()));
+ changeset& r (l.new_node<changeset> (n.version ()));
+
+ // Set the alters edge for lookup.
+ //
+ l.new_edge<alters> (r,
+ l.contains_changeset_empty ()
+ ? static_cast<qscope&> (l.model ())
+ : l.contains_changeset_back ().changeset ());
{
trav_rel::model model;
trav_rel::qnames names;
- diff_model dmodel (o, diff_model::mode_add, r, g);
+ diff_model dmodel (o, diff_model::mode_add, r, l);
model >> names >> dmodel;
model.traverse (n);
}
@@ -186,7 +430,7 @@ namespace relational
{
trav_rel::model model;
trav_rel::qnames names;
- diff_model dmodel (n, diff_model::mode_drop, r, g);
+ diff_model dmodel (n, diff_model::mode_drop, r, l);
model >> names >> dmodel;
model.traverse (o);
}
@@ -200,7 +444,11 @@ namespace relational
struct patch_table: trav_rel::add_column,
trav_rel::drop_column,
- trav_rel::alter_column
+ trav_rel::alter_column,
+ trav_rel::add_index,
+ trav_rel::drop_index,
+ trav_rel::add_foreign_key,
+ trav_rel::drop_foreign_key
{
patch_table (table& tl, graph& gr): t (tl), g (gr) {}
@@ -251,6 +499,74 @@ namespace relational
}
}
+ virtual void
+ traverse (sema_rel::add_index& ai)
+ {
+ using sema_rel::index;
+
+ try
+ {
+ index& i (g.new_node<index> (ai, t, g));
+ g.new_edge<unames> (t, i, ai.name ());
+ }
+ catch (duplicate_name const&)
+ {
+ cerr << "error: invalid changelog: index '" << ai.name () <<
+ "' already exists in table '" << t.name () << "'" << endl;
+ throw operation_failed ();
+ }
+ }
+
+ virtual void
+ traverse (sema_rel::drop_index& di)
+ {
+ using sema_rel::index;
+ table::names_iterator i (t.find (di.name ()));
+
+ if (i == t.names_end () || !i->nameable ().is_a<index> ())
+ {
+ cerr << "error: invalid changelog: index '" << di.name () <<
+ "' does not exist in table '" << t.name () << "'" << endl;
+ throw operation_failed ();
+ }
+
+ g.delete_edge (t, i->nameable (), *i);
+ }
+
+ virtual void
+ traverse (sema_rel::add_foreign_key& afk)
+ {
+ using sema_rel::foreign_key;
+
+ try
+ {
+ foreign_key& fk (g.new_node<foreign_key> (afk, t, g));
+ g.new_edge<unames> (t, fk, afk.name ());
+ }
+ catch (duplicate_name const&)
+ {
+ cerr << "error: invalid changelog: foreign key '" << afk.name () <<
+ "' already exists in table '" << t.name () << "'" << endl;
+ throw operation_failed ();
+ }
+ }
+
+ virtual void
+ traverse (sema_rel::drop_foreign_key& dfk)
+ {
+ using sema_rel::foreign_key;
+ table::names_iterator i (t.find (dfk.name ()));
+
+ if (i == t.names_end () || !i->nameable ().is_a<foreign_key> ())
+ {
+ cerr << "error: invalid changelog: foreign key '" << dfk.name () <<
+ "' does not exist in table '" << t.name () << "'" << endl;
+ throw operation_failed ();
+ }
+
+ g.delete_edge (t, i->nameable (), *i);
+ }
+
protected:
table& t;
graph& g;
@@ -389,7 +705,7 @@ namespace relational
//
if (!mv.open)
{
- changeset& cs (diff (oldm, m, g));
+ changeset& cs (diff (oldm, m, *cl));
if (!cs.names_empty ())
{
@@ -432,7 +748,7 @@ namespace relational
if (!mv.open)
{
model& old (patch (*last, cs, g));
- changeset& cs (diff (old, m, g));
+ changeset& cs (diff (old, m, *cl));
if (!cs.names_empty ())
{
@@ -458,7 +774,14 @@ namespace relational
if (last->version () <= mv.base)
continue;
- g.new_edge<contains_changeset> (*cl, g.new_node<changeset> (cs, g));
+ changeset& c (
+ g.new_node<changeset> (
+ cs,
+ cl->contains_changeset_empty ()
+ ? static_cast<qscope&> (*base) // Cannot be NULL.
+ : cl->contains_changeset_back ().changeset (),
+ g));
+ g.new_edge<contains_changeset> (*cl, c);
}
// If we still haven't found the new base model, then take the
@@ -473,7 +796,7 @@ namespace relational
// Add a changeset for the current version.
//
- changeset& cs (diff (*last, m, g));
+ changeset& cs (diff (*last, m, *cl));
if (!cs.names_empty ())
g.new_edge<contains_changeset> (*cl, cs);
diff --git a/odb/semantics/relational/changelog.cxx b/odb/semantics/relational/changelog.cxx
index cd94494..fb304ca 100644
--- a/odb/semantics/relational/changelog.cxx
+++ b/odb/semantics/relational/changelog.cxx
@@ -3,6 +3,7 @@
// license : GNU GPL v3; see accompanying LICENSE file
#include <vector>
+#include <sstream>
#include <cutl/compiler/type-info.hxx>
@@ -10,6 +11,8 @@
#include <odb/semantics/relational/model.hxx>
#include <odb/semantics/relational/changeset.hxx>
+using namespace std;
+
namespace semantics
{
namespace relational
@@ -26,10 +29,12 @@ namespace semantics
if (p.attribute<unsigned int> ("version") != 1)
throw parsing (p, "unsupported changelog format version");
- // Get the changesets. Because they are stored in the reverse order,
- // first save them to the temporary vector.
+ // Because things are stored in the reverse order, first save the
+ // changesets as XML chunks and then re-parse them in the reverse
+ // order. We have to do it this way so that we can do lookups along
+ // the alters edges.
//
- typedef std::vector<changeset*> changesets;
+ typedef vector<string> changesets;
changesets cs;
for (parser::event_type e (p.peek ());
@@ -39,22 +44,79 @@ namespace semantics
if (p.qname () != xml::qname (xmlns, "changeset"))
break; // Not our elements.
- p.next ();
- cs.push_back (&new_node<changeset> (p, *this));
- p.next_expect (parser::end_element);
- }
+ ostringstream os;
+ os.exceptions (ios_base::badbit | ios_base::failbit);
+ serializer s (os, "changeset", 0); // No pretty-printing.
+ size_t depth (0);
- for (changesets::reverse_iterator i (cs.rbegin ()); i != cs.rend (); ++i)
- new_edge<contains_changeset> (*this, **i);
+ do
+ {
+ switch (p.next ())
+ {
+ case parser::start_element:
+ {
+ s.start_element (p.qname ());
+
+ if (depth == 0)
+ s.namespace_decl (xmlns, "");
+
+ typedef parser::attribute_map_type attr_map;
+ attr_map const& am (p.attribute_map ());
+
+ for (attr_map::const_iterator i (am.begin ());
+ i != am.end (); ++i)
+ s.attribute (i->first, i->second.value);
+
+ depth++;
+ break;
+ }
+ case parser::end_element:
+ {
+ depth--;
+ s.end_element ();
+ break;
+ }
+ case parser::characters:
+ {
+ s.characters (p.value ());
+ break;
+ }
+ default:
+ {
+ depth = 0;
+ break;
+ }
+ }
+ } while (depth != 0);
+
+ cs.push_back (os.str ());
+ }
// Get the model.
//
p.next_expect (parser::start_element, xmlns, "model");
-
model_type& m (new_node<model_type> (p, *this));
new_edge<contains_model_type> (*this, m);
-
p.next_expect (parser::end_element);
+
+ // Re-parse the changesets in reverse order.
+ //
+ qscope* base (&m);
+ for (changesets::reverse_iterator i (cs.rbegin ()); i != cs.rend (); ++i)
+ {
+ istringstream is (*i);
+ is.exceptions (ios_base::badbit | ios_base::failbit);
+ parser ip (is, p.input_name ());
+
+ ip.next_expect (parser::start_element, xmlns, "changeset");
+
+ changeset& c (new_node<changeset> (ip, *base, *this));
+ new_edge<contains_changeset> (*this, c);
+ base = &c;
+
+ ip.next_expect (parser::end_element);
+ }
+
p.next_expect (parser::end_element);
}
diff --git a/odb/semantics/relational/changeset.cxx b/odb/semantics/relational/changeset.cxx
index 8004844..fd5a17f 100644
--- a/odb/semantics/relational/changeset.cxx
+++ b/odb/semantics/relational/changeset.cxx
@@ -11,15 +11,15 @@ namespace semantics
namespace relational
{
changeset::
- changeset (changeset const& c, graph& g)
- : qscope (c, g),
- version_ (c.version_)
+ changeset (changeset const& c, qscope& b, graph& g)
+ : qscope (c, &b, g),
+ version_ (c.version_)
{
}
changeset::
- changeset (xml::parser& p, graph& g)
- : qscope (p, g),
+ changeset (xml::parser& p, qscope& b, graph& g)
+ : qscope (p, &b, g),
version_ (p.attribute<version_type> ("version"))
{
}
diff --git a/odb/semantics/relational/changeset.hxx b/odb/semantics/relational/changeset.hxx
index 575eb7b..76fd683 100644
--- a/odb/semantics/relational/changeset.hxx
+++ b/odb/semantics/relational/changeset.hxx
@@ -21,8 +21,8 @@ namespace semantics
public:
changeset (version_type v): version_ (v) {}
- changeset (changeset const&, graph&);
- changeset (xml::parser&, graph&);
+ changeset (changeset const&, qscope& base, graph&);
+ changeset (xml::parser&, qscope& base, graph&);
virtual string
kind () const {return "changeset";}
diff --git a/odb/semantics/relational/column.cxx b/odb/semantics/relational/column.cxx
index f90b94e..1a47ef7 100644
--- a/odb/semantics/relational/column.cxx
+++ b/odb/semantics/relational/column.cxx
@@ -104,20 +104,26 @@ namespace semantics
// alter_column
//
alter_column::
- alter_column (alter_column const& ac, uscope&, graph& g)
- : unameable (ac, g),
- null_altered_ (ac.null_altered_),
- null_ (ac.null_)
+ alter_column (alter_column const& ac, uscope& s, graph& g)
+ : column (ac, s, g),
+ alters_ (0),
+ null_altered_ (ac.null_altered_)
{
+ column* b (s.lookup<column, drop_column> (ac.name ()));
+ assert (b != 0);
+ g.new_edge<alters> (*this, *b);
}
alter_column::
- alter_column (xml::parser& p, uscope&, graph& g)
- : unameable (p, g),
- null_altered_ (p.attribute_present ("null")),
- null_ (null_altered_ ? p.attribute<bool> ("null") : false)
+ alter_column (xml::parser& p, uscope& s, graph& g)
+ : column (p, s, g),
+ alters_ (0),
+ null_altered_ (p.attribute_present ("null"))
{
- p.content (xml::parser::empty);
+ name_type n (p.attribute<name_type> ("name"));
+ column* b (s.lookup<column, drop_column> (n));
+ assert (b != 0);
+ g.new_edge<alters> (*this, *b);
}
alter_column& alter_column::
@@ -130,6 +136,9 @@ namespace semantics
serialize (xml::serializer& s) const
{
s.start_element (xmlns, "alter-column");
+
+ // Here we override the standard column logic.
+ //
unameable::serialize_attributes (s);
if (null_altered_)
@@ -183,7 +192,7 @@ namespace semantics
//
{
type_info ti (typeid (alter_column));
- ti.add_base (typeid (unameable));
+ ti.add_base (typeid (column));
insert (ti);
}
}
diff --git a/odb/semantics/relational/column.hxx b/odb/semantics/relational/column.hxx
index 7702a13..11a76e0 100644
--- a/odb/semantics/relational/column.hxx
+++ b/odb/semantics/relational/column.hxx
@@ -19,35 +19,32 @@ namespace semantics
typedef std::vector<contains*> contained_list;
public:
- string const&
+ virtual string const&
type () const {return type_;}
- bool
+ virtual bool
null () const {return null_;}
- void
+ virtual void
null (bool n) {null_ = n;}
- string const&
+ virtual string const&
default_ () const {return default__;}
- void
+ virtual void
default_ (string const& d) {default__ = d;}
- string const&
+ virtual string const&
options () const {return options_;}
- void
+ virtual void
options (string const& o) {options_ = o;}
public:
typedef relational::table table_type;
table_type&
- table () const
- {
- return dynamic_cast<table_type&> (scope ());
- }
+ table () const {return dynamic_cast<table_type&> (scope ());}
// Key containment.
//
@@ -95,12 +92,13 @@ namespace semantics
void
serialize_attributes (xml::serializer&) const;
- private:
+ protected:
string type_;
bool null_;
string default__;
string options_;
+ private:
contained_list contained_;
};
@@ -140,24 +138,34 @@ namespace semantics
serialize (xml::serializer&) const;
};
- class alter_column: public unameable
+ class alter_column: public column
{
public:
+ virtual string const&
+ type () const {return base ().type ();}
+
bool
null_altered () const {return null_altered_;}
- bool
- null () const {return null_;}
+ virtual bool
+ null () const {return null_altered_ ? null_ : base ().null ();}
- void
+ virtual void
null (bool n) {null_ = n; null_altered_ = true;}
+ virtual string const&
+ default_ () const {return base ().default_ ();}
+
+ virtual string const&
+ options () const {return base ().options ();}
+
public:
- alter_column (string const& id)
- : unameable (id), null_altered_ (false)
- {
- }
+ column&
+ base () const {return dynamic_cast<column&> (alters_->base ());}
+ public:
+ alter_column (string const& id)
+ : column (id, "", false), alters_ (0), null_altered_ (false) {}
alter_column (alter_column const&, uscope&, graph&);
alter_column (xml::parser&, uscope&, graph&);
@@ -173,9 +181,17 @@ namespace semantics
virtual void
serialize (xml::serializer&) const;
+ virtual void
+ add_edge_left (alters& a)
+ {
+ assert (alters_ == 0);
+ alters_ = &a;
+ }
+
private:
+ alters* alters_;
+
bool null_altered_;
- bool null_;
};
}
}
diff --git a/odb/semantics/relational/elements.cxx b/odb/semantics/relational/elements.cxx
index e14bc00..d83bff7 100644
--- a/odb/semantics/relational/elements.cxx
+++ b/odb/semantics/relational/elements.cxx
@@ -45,23 +45,36 @@ namespace semantics
{
typename names_list::iterator i;
- // We want the order to be columns first, then the primary key,
- // and then the foreign keys.
+ // We want the order to be add/alter columns first, then the
+ // primary key, then other keys, and finnally drop columns.
//
- if (n.is_a<column> ())
+ if (n.is_a<column> () ||
+ n.is_a<add_column> () ||
+ n.is_a<alter_column> ())
+ {
i = names_.insert (first_key_, &e);
- else
+ }
+ else if (!n.is_a<drop_column> ())
{
if (n.is_a<primary_key> ())
- first_key_ = i = names_.insert (first_key_, &e);
+ first_key_ = i = names_.insert (
+ first_key_ != names_.end () ? first_key_ : first_drop_column_,
+ &e);
else
{
- i = names_.insert (names_.end (), &e);
+ i = names_.insert (first_drop_column_, &e);
if (first_key_ == names_.end ())
first_key_ = i;
}
}
+ else
+ {
+ i = names_.insert (names_.end (), &e);
+
+ if (first_drop_column_ == names_.end ())
+ first_drop_column_ = i;
+ }
names_map_[name] = i;
iterator_map_[&e] = i;
@@ -83,6 +96,11 @@ namespace semantics
if (first_key_ == i->second)
first_key_++;
+ // The same for the first drop column.
+ //
+ if (first_drop_column_ == i->second)
+ first_drop_column_++;
+
names_.erase (i->second);
names_map_.erase (e.name ());
iterator_map_.erase (i);
@@ -106,6 +124,14 @@ namespace semantics
//
insert (type_info (typeid (edge)));
+ // alters
+ //
+ {
+ type_info ti (typeid (alters));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
// names
//
{
diff --git a/odb/semantics/relational/elements.hxx b/odb/semantics/relational/elements.hxx
index 381d7a8..11e7ea8 100644
--- a/odb/semantics/relational/elements.hxx
+++ b/odb/semantics/relational/elements.hxx
@@ -93,9 +93,57 @@ namespace semantics
//
public:
void
- add_edge_right (edge&)
+ add_edge_right (edge&) {}
+
+ void
+ remove_edge_right (edge&) {}
+ };
+
+ //
+ //
+ class alters: public edge
+ {
+ public:
+ node&
+ base () const {return *base_;}
+
+ node&
+ modifier () const {return *modifier_;}
+
+ public:
+ alters () : base_ (0), modifier_ (0) {}
+
+ void
+ set_left_node (node& m)
+ {
+ assert (modifier_ == 0);
+ modifier_ = &m;
+ }
+
+ void
+ set_right_node (node& b)
{
+ assert (base_ == 0);
+ base_ = &b;
}
+
+ void
+ clear_left_node (node& m)
+ {
+ assert (modifier_ == &m);
+ modifier_ = 0;
+ }
+
+ void
+ clear_right_node (node& b)
+ {
+ assert (base_ == &b);
+ base_ = 0;
+ }
+
+ protected:
+ node* base_;
+ node* modifier_;
};
//
@@ -224,6 +272,7 @@ namespace semantics
}
using node::add_edge_right;
+ using node::remove_edge_right;
protected:
nameable (nameable const&, graph& g);
@@ -319,7 +368,7 @@ namespace semantics
return names_.empty ();
}
- // Find.
+ // Find (this scope only).
//
template <typename T>
T*
@@ -337,30 +386,64 @@ namespace semantics
names_const_iterator
find (names_type const&) const;
+ // Lookup in this and all altered scopes until we find what we are
+ // looking for or hit a stop node of type S (e.g., drop_*).
+ //
+ template <typename T, typename S>
+ T*
+ lookup (name_type const&);
+
+ public:
+ scope*
+ base () const
+ {
+ return alters_ != 0 ? &dynamic_cast<scope&> (alters_->base ()) : 0;
+ }
+
public:
- scope (): first_key_ (names_.end ()) {}
+ scope ()
+ : first_key_ (names_.end ()),
+ first_drop_column_ (names_.end ()),
+ alters_ (0) {}
// Virtual because we call it via scope interface (e.g., in copy).
//
virtual void
+ add_edge_left (alters& a)
+ {
+ assert (alters_ == 0);
+ alters_ = &a;
+ }
+
+ virtual void
+ remove_edge_left (alters& a)
+ {
+ assert (alters_ == &a);
+ alters_ = 0;
+ }
+
+ virtual void
add_edge_left (names_type&);
virtual void
remove_edge_left (names_type&);
protected:
- scope (scope const&, graph&);
- scope (xml::parser&, graph&);
+ scope (scope const&, scope* base, graph&);
+ scope (xml::parser&, scope* base, graph&);
void
serialize_content (xml::serializer&) const;
- private:
+ protected:
names_list names_;
names_map names_map_;
names_iterator_map iterator_map_;
typename names_list::iterator first_key_;
+ typename names_list::iterator first_drop_column_;
+
+ alters* alters_;
};
template <>
diff --git a/odb/semantics/relational/elements.txx b/odb/semantics/relational/elements.txx
index e1fd6d5..725fc3f 100644
--- a/odb/semantics/relational/elements.txx
+++ b/odb/semantics/relational/elements.txx
@@ -54,6 +54,23 @@ namespace semantics
//
template <typename N>
+ template <typename T, typename S>
+ T* scope<N>::
+ lookup (name_type const& name)
+ {
+ if (T* r = find<T> (name))
+ return r;
+
+ if (scope* b = base ())
+ {
+ if (find<S> (name) == 0)
+ return b->lookup<T, S> (name);
+ }
+
+ return 0;
+ }
+
+ template <typename N>
template <typename T>
T* scope<N>::
find (name_type const& name)
@@ -106,9 +123,16 @@ namespace semantics
template <typename N>
scope<N>::
- scope (scope const& s, graph& g)
- : first_key_ (names_.end ())
+ scope (scope const& s, scope* base, graph& g)
+ : first_key_ (names_.end ()),
+ first_drop_column_ (names_.end ()),
+ alters_ (0)
{
+ // Set the alters edge for lookup.
+ //
+ if (base != 0)
+ g.new_edge<alters> (*this, *base);
+
for (names_const_iterator i (s.names_begin ());
i != s.names_end (); ++i)
{
@@ -119,9 +143,16 @@ namespace semantics
template <typename N>
scope<N>::
- scope (xml::parser& p, graph& g)
- : first_key_ (names_.end ())
+ scope (xml::parser& p, scope* base, graph& g)
+ : first_key_ (names_.end ()),
+ first_drop_column_ (names_.end ()),
+ alters_ (0)
{
+ // Set the alters edge for lookup.
+ //
+ if (base != 0)
+ g.new_edge<alters> (*this, *base);
+
using namespace xml;
p.content (parser::complex);
diff --git a/odb/semantics/relational/foreign-key.cxx b/odb/semantics/relational/foreign-key.cxx
index 7ef88a6..0407858 100644
--- a/odb/semantics/relational/foreign-key.cxx
+++ b/odb/semantics/relational/foreign-key.cxx
@@ -89,11 +89,9 @@ namespace semantics
return g.new_node<foreign_key> (*this, s, g);
}
-
void foreign_key::
- serialize (xml::serializer& s) const
+ serialize_attributes (xml::serializer& s) const
{
- s.start_element (xmlns, "foreign-key");
key::serialize_attributes (s);
if (deferred ())
@@ -101,7 +99,11 @@ namespace semantics
if (on_delete () != no_action)
s.attribute ("on-delete", on_delete ());
+ }
+ void foreign_key::
+ serialize_content (xml::serializer& s) const
+ {
key::serialize_content (s);
// Referenced columns.
@@ -118,9 +120,57 @@ namespace semantics
}
s.end_element (); // references
+ }
+
+ void foreign_key::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "foreign-key");
+ serialize_attributes (s);
+ serialize_content (s);
s.end_element (); // foreign-key
}
+ // add_foreign_key
+ //
+ add_foreign_key& add_foreign_key::
+ clone (uscope& s, graph& g) const
+ {
+ return g.new_node<add_foreign_key> (*this, s, g);
+ }
+
+ void add_foreign_key::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "add-foreign-key");
+ foreign_key::serialize_attributes (s);
+ foreign_key::serialize_content (s);
+ s.end_element ();
+ }
+
+ // drop_foreign_key
+ //
+ drop_foreign_key::
+ drop_foreign_key (xml::parser& p, uscope&, graph& g)
+ : unameable (p, g)
+ {
+ p.content (xml::parser::empty);
+ }
+
+ drop_foreign_key& drop_foreign_key::
+ clone (uscope& s, graph& g) const
+ {
+ return g.new_node<drop_foreign_key> (*this, s, g);
+ }
+
+ void drop_foreign_key::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "drop-foreign-key");
+ unameable::serialize_attributes (s);
+ s.end_element ();
+ }
+
// type info
//
namespace
@@ -129,16 +179,37 @@ namespace semantics
{
init ()
{
- unameable::parser_map_["foreign-key"] =
- &unameable::parser_impl<foreign_key>;
+ unameable::parser_map& m (unameable::parser_map_);
+
+ m["foreign-key"] = &unameable::parser_impl<foreign_key>;
+ m["add-foreign-key"] = &unameable::parser_impl<add_foreign_key>;
+ m["drop-foreign-key"] = &unameable::parser_impl<drop_foreign_key>;
using compiler::type_info;
+ // foreign_key
+ //
{
type_info ti (typeid (foreign_key));
ti.add_base (typeid (key));
insert (ti);
}
+
+ // add_foreign_key
+ //
+ {
+ type_info ti (typeid (add_foreign_key));
+ ti.add_base (typeid (foreign_key));
+ insert (ti);
+ }
+
+ // drop_foreign_key
+ //
+ {
+ type_info ti (typeid (drop_foreign_key));
+ ti.add_base (typeid (unameable));
+ insert (ti);
+ }
}
} init_;
}
diff --git a/odb/semantics/relational/foreign-key.hxx b/odb/semantics/relational/foreign-key.hxx
index 5d551fe..50a3fae 100644
--- a/odb/semantics/relational/foreign-key.hxx
+++ b/odb/semantics/relational/foreign-key.hxx
@@ -83,6 +83,13 @@ namespace semantics
virtual void
serialize (xml::serializer&) const;
+ protected:
+ void
+ serialize_attributes (xml::serializer&) const;
+
+ void
+ serialize_content (xml::serializer&) const;
+
private:
qname referenced_table_;
columns referenced_columns_;
@@ -95,6 +102,47 @@ namespace semantics
std::istream&
operator>> (std::istream&, foreign_key::action_type&);
+
+ class add_foreign_key: public foreign_key
+ {
+ public:
+ add_foreign_key (string const& id,
+ qname const& rt,
+ bool d,
+ action_type od = no_action)
+ : foreign_key (id, rt, d, od) {}
+ add_foreign_key (foreign_key const& fk, uscope& s, graph& g)
+ : foreign_key (fk, s, g) {}
+ add_foreign_key (xml::parser& p, uscope& s, graph& g)
+ : foreign_key (p, s, g) {}
+
+ virtual add_foreign_key&
+ clone (uscope&, graph&) const;
+
+ virtual string
+ kind () const {return "add foreign key";}
+
+ virtual void
+ serialize (xml::serializer&) const;
+ };
+
+ class drop_foreign_key: public unameable
+ {
+ public:
+ drop_foreign_key (string const& id): unameable (id) {}
+ drop_foreign_key (drop_foreign_key const& dfk, uscope&, graph& g)
+ : unameable (dfk, g) {}
+ drop_foreign_key (xml::parser&, uscope&, graph&);
+
+ virtual drop_foreign_key&
+ clone (uscope&, graph&) const;
+
+ virtual string
+ kind () const {return "drop foreign key";}
+
+ virtual void
+ serialize (xml::serializer&) const;
+ };
}
}
diff --git a/odb/semantics/relational/index.cxx b/odb/semantics/relational/index.cxx
index 5ff1a26..b38c6e4 100644
--- a/odb/semantics/relational/index.cxx
+++ b/odb/semantics/relational/index.cxx
@@ -10,6 +10,8 @@ namespace semantics
{
namespace relational
{
+ // index
+ //
index::
index (index const& i, uscope& s, graph& g)
: key (i, s, g),
@@ -35,9 +37,8 @@ namespace semantics
}
void index::
- serialize (xml::serializer& s) const
+ serialize_attributes (xml::serializer& s) const
{
- s.start_element (xmlns, "index");
key::serialize_attributes (s);
if (!type ().empty ())
@@ -48,11 +49,57 @@ namespace semantics
if (!options ().empty ())
s.attribute ("options", options ());
+ }
+ void index::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "index");
+ serialize_attributes (s);
key::serialize_content (s);
s.end_element ();
}
+ // add_index
+ //
+ add_index& add_index::
+ clone (uscope& s, graph& g) const
+ {
+ return g.new_node<add_index> (*this, s, g);
+ }
+
+ void add_index::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "add-index");
+ index::serialize_attributes (s);
+ index::serialize_content (s);
+ s.end_element ();
+ }
+
+ // drop_index
+ //
+ drop_index::
+ drop_index (xml::parser& p, uscope&, graph& g)
+ : unameable (p, g)
+ {
+ p.content (xml::parser::empty);
+ }
+
+ drop_index& drop_index::
+ clone (uscope& s, graph& g) const
+ {
+ return g.new_node<drop_index> (*this, s, g);
+ }
+
+ void drop_index::
+ serialize (xml::serializer& s) const
+ {
+ s.start_element (xmlns, "drop-index");
+ unameable::serialize_attributes (s);
+ s.end_element ();
+ }
+
// type info
//
namespace
@@ -61,15 +108,37 @@ namespace semantics
{
init ()
{
- unameable::parser_map_["index"] = &unameable::parser_impl<index>;
+ unameable::parser_map& m (unameable::parser_map_);
+
+ m["index"] = &unameable::parser_impl<index>;
+ m["add-index"] = &unameable::parser_impl<add_index>;
+ m["drop-index"] = &unameable::parser_impl<drop_index>;
using compiler::type_info;
+ // index
+ //
{
type_info ti (typeid (index));
ti.add_base (typeid (key));
insert (ti);
}
+
+ // add_index
+ //
+ {
+ type_info ti (typeid (add_index));
+ ti.add_base (typeid (index));
+ insert (ti);
+ }
+
+ // drop_index
+ //
+ {
+ type_info ti (typeid (drop_index));
+ ti.add_base (typeid (unameable));
+ insert (ti);
+ }
}
} init_;
}
diff --git a/odb/semantics/relational/index.hxx b/odb/semantics/relational/index.hxx
index 621f36a..500c341 100644
--- a/odb/semantics/relational/index.hxx
+++ b/odb/semantics/relational/index.hxx
@@ -31,10 +31,7 @@ namespace semantics
string const& t = string (),
string const& m = string (),
string const& o = string ())
- : key (id), type_ (t), method_ (m), options_ (o)
- {
- }
-
+ : key (id), type_ (t), method_ (m), options_ (o) {}
index (index const&, uscope&, graph&);
index (xml::parser&, uscope&, graph&);
@@ -50,11 +47,54 @@ namespace semantics
virtual void
serialize (xml::serializer&) const;
+ protected:
+ void
+ serialize_attributes (xml::serializer&) const;
+
private:
string type_; // E.g., "UNIQUE", etc.
string method_; // E.g., "BTREE", etc.
string options_; // Database-specific index options.
};
+
+ class add_index: public index
+ {
+ public:
+ add_index (string const& id,
+ string const& t = string (),
+ string const& m = string (),
+ string const& o = string ())
+ : index (id, t, m, o) {}
+ add_index (index const& i, uscope& s, graph& g): index (i, s, g) {}
+ add_index (xml::parser& p, uscope& s, graph& g): index (p, s, g) {}
+
+ virtual add_index&
+ clone (uscope&, graph&) const;
+
+ virtual string
+ kind () const {return "add index";}
+
+ virtual void
+ serialize (xml::serializer&) const;
+ };
+
+ class drop_index: public unameable
+ {
+ public:
+ drop_index (string const& id): unameable (id) {}
+ drop_index (drop_index const& di, uscope&, graph& g)
+ : unameable (di, g) {}
+ drop_index (xml::parser&, uscope&, graph&);
+
+ virtual drop_index&
+ clone (uscope&, graph&) const;
+
+ virtual string
+ kind () const {return "drop index";}
+
+ virtual void
+ serialize (xml::serializer&) const;
+ };
}
}
diff --git a/odb/semantics/relational/key.cxx b/odb/semantics/relational/key.cxx
index e27253c..dc0fbe0 100644
--- a/odb/semantics/relational/key.cxx
+++ b/odb/semantics/relational/key.cxx
@@ -18,7 +18,7 @@ namespace semantics
for (contains_iterator i (k.contains_begin ());
i != k.contains_end (); ++i)
{
- column* c (s.find<column> (i->column ().name ()));
+ column* c (s.lookup<column, drop_column> (i->column ().name ()));
assert (c != 0);
g.new_edge<contains> (*this, *c, i->options ());
}
@@ -42,7 +42,7 @@ namespace semantics
p.content (parser::empty);
uname n (p.attribute<uname> ("name"));
- column* c (s.find<column> (n));
+ column* c (s.lookup<column, drop_column> (n));
if (c == 0)
throw parsing (p, "invalid column name in the 'name' attribute");
diff --git a/odb/semantics/relational/key.hxx b/odb/semantics/relational/key.hxx
index 8d64993..184433e 100644
--- a/odb/semantics/relational/key.hxx
+++ b/odb/semantics/relational/key.hxx
@@ -6,6 +6,7 @@
#define ODB_SEMANTICS_RELATIONAL_KEY_HXX
#include <odb/semantics/relational/elements.hxx>
+#include <odb/semantics/relational/table.hxx>
namespace semantics
{
@@ -55,6 +56,8 @@ namespace semantics
typedef std::vector<contains*> contains_list;
public:
+ typedef contains_list::size_type contains_size_type;
+
typedef
pointer_iterator<contains_list::const_iterator>
contains_iterator;
@@ -65,9 +68,18 @@ namespace semantics
contains_iterator
contains_end () const {return contains_.end ();}
- contains_list::size_type
+ contains_size_type
contains_size () const {return contains_.size ();}
+ contains&
+ contains_at (contains_size_type i) const {return *contains_[i];}
+
+ public:
+ typedef relational::table table_type;
+
+ table_type&
+ table () const {return dynamic_cast<table_type&> (scope ());}
+
public:
key (std::string const& id): unameable (id) {}
diff --git a/odb/semantics/relational/model.cxx b/odb/semantics/relational/model.cxx
index 6515591..678debe 100644
--- a/odb/semantics/relational/model.cxx
+++ b/odb/semantics/relational/model.cxx
@@ -12,14 +12,14 @@ namespace semantics
{
model::
model (model const& m, graph& g)
- : qscope (m, g),
+ : qscope (m, 0, g),
version_ (m.version_)
{
}
model::
model (xml::parser& p, graph& g)
- : qscope (p, g),
+ : qscope (p, 0, g),
version_ (p.attribute<version_type> ("version"))
{
}
diff --git a/odb/semantics/relational/name.hxx b/odb/semantics/relational/name.hxx
index 18c7509..06794be 100644
--- a/odb/semantics/relational/name.hxx
+++ b/odb/semantics/relational/name.hxx
@@ -125,6 +125,18 @@ namespace semantics
public:
friend bool
+ operator== (qname const& x, qname const& y)
+ {
+ return x.components_ == y.components_;
+ }
+
+ friend bool
+ operator!= (qname const& x, qname const& y)
+ {
+ return x.components_ != y.components_;
+ }
+
+ friend bool
operator< (qname const& x, qname const& y)
{
return x.components_ < y.components_;
diff --git a/odb/semantics/relational/table.cxx b/odb/semantics/relational/table.cxx
index 682196c..17265bd 100644
--- a/odb/semantics/relational/table.cxx
+++ b/odb/semantics/relational/table.cxx
@@ -13,14 +13,20 @@ namespace semantics
// table
//
table::
- table (table const& t, qscope&, graph& g)
- : qnameable (t, g), uscope (t, g)
+ table (table const& t, qscope& s, graph& g, bool b)
+ : qnameable (t, g),
+ uscope (t, (b ? s.lookup<table, drop_table> (t.name ()) : 0), g)
{
}
table::
- table (xml::parser& p, qscope&, graph& g)
- : qnameable (p, g), uscope (p, g)
+ table (xml::parser& p, qscope& s, graph& g, bool b)
+ : qnameable (p, g),
+ uscope (
+ p,
+ (b ? s.lookup<table, drop_table> (
+ p.attribute<qnameable::name_type> ("name")) : 0),
+ g)
{
}
@@ -81,18 +87,6 @@ namespace semantics
// alter_table
//
- alter_table::
- alter_table (alter_table const& t, qscope&, graph& g)
- : qnameable (t, g), uscope (t, g)
- {
- }
-
- alter_table::
- alter_table (xml::parser& p, qscope&, graph& g)
- : qnameable (p, g), uscope (p, g)
- {
- }
-
alter_table& alter_table::
clone (qscope& s, graph& g) const
{
@@ -103,8 +97,8 @@ namespace semantics
serialize (xml::serializer& s) const
{
s.start_element (xmlns, "alter-table");
- qnameable::serialize_attributes (s);
- uscope::serialize_content (s);
+ table::serialize_attributes (s);
+ table::serialize_content (s);
s.end_element ();
}
@@ -154,8 +148,7 @@ namespace semantics
//
{
type_info ti (typeid (alter_table));
- ti.add_base (typeid (qnameable));
- ti.add_base (typeid (uscope));
+ ti.add_base (typeid (table));
insert (ti);
}
}
diff --git a/odb/semantics/relational/table.hxx b/odb/semantics/relational/table.hxx
index effd552..ae4c96c 100644
--- a/odb/semantics/relational/table.hxx
+++ b/odb/semantics/relational/table.hxx
@@ -15,8 +15,8 @@ namespace semantics
{
public:
table (string const& id): qnameable (id) {}
- table (table const&, qscope&, graph&);
- table (xml::parser&, qscope&, graph&);
+ table (table const&, qscope&, graph&, bool base = false);
+ table (xml::parser&, qscope&, graph&, bool base = false);
virtual table&
clone (qscope&, graph&) const;
@@ -66,12 +66,14 @@ namespace semantics
serialize (xml::serializer&) const;
};
- class alter_table: public qnameable, public uscope
+ class alter_table: public table
{
public:
- alter_table (string const& id): qnameable (id) {}
- alter_table (alter_table const&, qscope&, graph&);
- alter_table (xml::parser&, qscope&, graph&);
+ alter_table (string const& id): table (id) {}
+ alter_table (alter_table const& at, qscope& s, graph& g)
+ : table (at, s, g, true) {}
+ alter_table (xml::parser& p, qscope& s, graph& g)
+ : table (p, s, g, true) {}
virtual alter_table&
clone (qscope&, graph&) const;
@@ -81,10 +83,6 @@ namespace semantics
virtual void
serialize (xml::serializer&) const;
-
- // Resolve ambiguity.
- //
- using qnameable::scope;
};
}
}
diff --git a/odb/traversal/relational/foreign-key.hxx b/odb/traversal/relational/foreign-key.hxx
index d80df26..1dc54e9 100644
--- a/odb/traversal/relational/foreign-key.hxx
+++ b/odb/traversal/relational/foreign-key.hxx
@@ -13,6 +13,9 @@ namespace traversal
namespace relational
{
struct foreign_key: key_template<semantics::relational::foreign_key> {};
+ struct add_foreign_key:
+ key_template<semantics::relational::add_foreign_key> {};
+ struct drop_foreign_key: node<semantics::relational::drop_foreign_key> {};
}
}
diff --git a/odb/traversal/relational/index.hxx b/odb/traversal/relational/index.hxx
index f45dda7..7426ab4 100644
--- a/odb/traversal/relational/index.hxx
+++ b/odb/traversal/relational/index.hxx
@@ -13,6 +13,8 @@ namespace traversal
namespace relational
{
struct index: key_template<semantics::relational::index> {};
+ struct add_index: key_template<semantics::relational::add_index> {};
+ struct drop_index: node<semantics::relational::drop_index> {};
}
}