aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-08-21 10:47:30 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-08-21 10:47:30 +0200
commit6a6095112daabd18d445ecf0d4c05e993e54236c (patch)
tree215997450ae13f63b0102d90daf41e104d1b0fc9
parenta26f4251e67ccaaaa848982946c8867443092ebe (diff)
Add support for multi-pass database schema drop
-rw-r--r--odb/relational/header.hxx2
-rw-r--r--odb/relational/schema.cxx11
-rw-r--r--odb/relational/schema.hxx54
-rw-r--r--odb/relational/source.hxx65
4 files changed, 98 insertions, 34 deletions
diff --git a/odb/relational/header.hxx b/odb/relational/header.hxx
index f25e9fe..ceca095 100644
--- a/odb/relational/header.hxx
+++ b/odb/relational/header.hxx
@@ -1009,7 +1009,7 @@ namespace relational
if (embedded_schema)
{
os << "static bool" << endl
- << "create_schema (database&, unsigned short pass);"
+ << "create_schema (database&, unsigned short pass, bool drop);"
<< endl;
}
diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx
index a347d49..c55837e 100644
--- a/odb/relational/schema.cxx
+++ b/odb/relational/schema.cxx
@@ -182,7 +182,7 @@ namespace relational
schema_emitter emitter;
- // Drop. It is essentially pass 0.
+ // Drop.
//
{
traversal::unit unit;
@@ -197,7 +197,14 @@ namespace relational
ns >> ns_defines >> ns;
ns_defines >> c;
- unit.dispatch (ctx.unit);
+
+ // Pass 1 and 2.
+ //
+ for (unsigned short pass (1); pass < 3; ++pass)
+ {
+ c->pass (pass);
+ unit.dispatch (ctx.unit);
+ }
}
os << endl;
diff --git a/odb/relational/schema.hxx b/odb/relational/schema.hxx
index 371cff9..24f5c54 100644
--- a/odb/relational/schema.hxx
+++ b/odb/relational/schema.hxx
@@ -71,11 +71,17 @@ namespace relational
{
typedef member_drop base;
- member_drop (emitter& e, ostream& os, tables& t)
+ member_drop (emitter& e, ostream& os, std::vector<tables>& t)
: object_members_base (false, true), common (e, os), tables_ (t)
{
}
+ void
+ pass (unsigned short p)
+ {
+ pass_ = p;
+ }
+
virtual void
container (semantics::data_member& m)
{
@@ -86,7 +92,7 @@ namespace relational
string const& name (table_name (m, table_prefix_));
- if (tables_.count (name))
+ if (tables_[pass_].count (name))
return;
// Drop table.
@@ -95,7 +101,7 @@ namespace relational
drop_table (name);
post_statement ();
- tables_.insert (name);
+ tables_[pass_].insert (name);
// Drop indexes.
//
@@ -112,7 +118,8 @@ namespace relational
}
protected:
- tables& tables_;
+ std::vector<tables>& tables_;
+ unsigned short pass_;
};
struct class_drop: traversal::class_, common, virtual drop_common
@@ -122,6 +129,7 @@ namespace relational
class_drop (emitter& e)
: common (e, os_), os_ (e), member_drop_ (e, os_, tables_)
{
+ tables_.push_back (tables ()); // Dummy entry.
}
class_drop (class_drop const& x)
@@ -129,11 +137,33 @@ namespace relational
context (),
common (x.e_, os_), os_ (x.e_), member_drop_ (x.e_, os_, tables_)
{
+ tables_.push_back (tables ()); // Dummy entry.
+ }
+
+ void
+ pass (unsigned short p)
+ {
+ pass_ = p;
+
+ if (tables_.size () == pass_)
+ tables_.push_back (tables ());
+
+ member_drop_->pass (p);
}
virtual void
traverse (type& c)
{
+ // By default we do everything in a single pass. But some
+ // databases may require the second pass.
+ //
+ if (pass_ == 1)
+ drop (c);
+ }
+
+ virtual void
+ drop (type& c)
+ {
if (c.file () != unit.file ())
return;
@@ -142,23 +172,25 @@ namespace relational
string const& name (table_name (c));
- if (tables_.count (name))
+ if (tables_[pass_].count (name))
return;
+ // Drop tables for members. Do it before dropping the primary
+ // table -- some databases may prefer it that way.
+ //
+ member_drop_->traverse (c);
+
pre_statement ();
drop_table (name);
post_statement ();
- tables_.insert (name);
-
- // Drop tables for members.
- //
- member_drop_->traverse (c);
+ tables_[pass_].insert (name);
}
protected:
- tables tables_;
emitter_ostream os_;
+ unsigned short pass_;
+ std::vector<tables> tables_; // Seperate table for each pass.
instance<member_drop> member_drop_;
};
diff --git a/odb/relational/source.hxx b/odb/relational/source.hxx
index d30f605..9289206 100644
--- a/odb/relational/source.hxx
+++ b/odb/relational/source.hxx
@@ -2611,11 +2611,11 @@ namespace relational
new_pass_ = false;
empty_ = false;
- if (pass_ == 0)
+ if (pass_ == 1)
{
os << "switch (pass)"
<< "{"
- << "case 0:" << endl
+ << "case 1:" << endl
<< "{";
}
else
@@ -2658,34 +2658,59 @@ namespace relational
// create_schema ()
//
os << "bool " << traits << "::" << endl
- << "create_schema (database& db, unsigned short pass)"
+ << "create_schema (database& db, unsigned short pass, bool drop)"
<< "{"
<< "ODB_POTENTIALLY_UNUSED (db);"
<< "ODB_POTENTIALLY_UNUSED (pass);"
<< endl;
- bool close (false);
-
- // Pass 0.
+ // Drop.
//
- schema_emitter_.pass (0);
- schema_drop_->traverse (c);
- close = close || !schema_emitter_.empty ();
+ {
+ bool close (false);
+
+ os << "if (drop)"
+ << "{";
+
+ for (unsigned short pass (1); pass < 3; ++pass)
+ {
+ schema_emitter_.pass (pass);
+ schema_drop_->pass (pass);
+ schema_drop_->traverse (c);
+ close = close || !schema_emitter_.empty ();
+ }
+
+ if (close) // Close the last case and the switch block.
+ os << "return false;"
+ << "}" // case
+ << "}"; // switch
+
+ os << "}";
+ }
- // Pass 1 and 2.
+ // Create.
//
- for (unsigned short pass (1); pass < 3; ++pass)
{
- schema_emitter_.pass (pass);
- schema_create_->pass (pass);
- schema_create_->traverse (c);
- close = close || !schema_emitter_.empty ();
- }
+ bool close (false);
+
+ os << "else"
+ << "{";
+
+ for (unsigned short pass (1); pass < 3; ++pass)
+ {
+ schema_emitter_.pass (pass);
+ schema_create_->pass (pass);
+ schema_create_->traverse (c);
+ close = close || !schema_emitter_.empty ();
+ }
+
+ if (close) // Close the last case and the switch block.
+ os << "return false;"
+ << "}" // case
+ << "}"; // switch
- if (close) // Close the last case and the switch block.
- os << "return false;"
- << "}" // case
- << "}"; // switch
+ os << "}";
+ }
os << "return false;"
<< "}";