From 2aa3cabf1b737e225178230882ee9aadfd817ce0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 28 Mar 2013 16:04:48 +0200 Subject: Add changelog support for add/drop index/foreign key Also diagnose changes to primary keys and establish the 'alters' association. --- odb/semantics/relational/changelog.cxx | 84 +++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) (limited to 'odb/semantics/relational/changelog.cxx') 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 +#include #include @@ -10,6 +11,8 @@ #include #include +using namespace std; + namespace semantics { namespace relational @@ -26,10 +29,12 @@ namespace semantics if (p.attribute ("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 changesets; + typedef vector 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 (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 (*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 (p, *this)); new_edge (*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 (ip, *base, *this)); + new_edge (*this, c); + base = &c; + + ip.next_expect (parser::end_element); + } + p.next_expect (parser::end_element); } -- cgit v1.1