From 6a6095112daabd18d445ecf0d4c05e993e54236c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 21 Aug 2011 10:47:30 +0200 Subject: Add support for multi-pass database schema drop --- odb/relational/header.hxx | 2 +- odb/relational/schema.cxx | 11 ++++++-- odb/relational/schema.hxx | 54 +++++++++++++++++++++++++++++++-------- odb/relational/source.hxx | 65 ++++++++++++++++++++++++++++++++--------------- 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& 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_; + 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_; // Seperate table for each pass. instance 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;" << "}"; -- cgit v1.1