summaryrefslogtreecommitdiff
path: root/odb/semantics/relational/changelog.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/semantics/relational/changelog.cxx')
-rw-r--r--odb/semantics/relational/changelog.cxx84
1 files changed, 73 insertions, 11 deletions
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);
}