From 287a41287ed26bcf481f087680cad56ed5ef9865 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 9 Apr 2013 16:17:26 +0200 Subject: Add support for embedded schema migration --- odb/schema-catalog.cxx | 116 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 11 deletions(-) (limited to 'odb/schema-catalog.cxx') diff --git a/odb/schema-catalog.cxx b/odb/schema-catalog.cxx index 07793d8..52b612f 100644 --- a/odb/schema-catalog.cxx +++ b/odb/schema-catalog.cxx @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -14,15 +15,21 @@ using namespace std; namespace odb { - // It is important we use vector to store the list of create - // functions since schema generators for some databases may - // rely on the DDL statements executing in a specific order, - // for example, for foreign key generation. - // typedef bool (*create_function) (database&, unsigned short pass, bool drop); + typedef bool (*migrate_function) (database&, unsigned short pass, bool pre); + typedef pair key; typedef vector create_functions; - struct schema_catalog_impl: map {}; + typedef vector migrate_functions; + typedef map version_map; + + struct schema_functions + { + create_functions create; + version_map migrate; + }; + + struct schema_catalog_impl: map {}; schema_catalog_impl* schema_catalog_init::catalog = 0; size_t schema_catalog_init::count = 0; @@ -43,7 +50,7 @@ namespace odb if (i == c.end ()) throw unknown_schema (name); - const create_functions& fs (i->second); + const create_functions& fs (i->second.create); // Run the passes until we ran them all or all the functions // return false, which means no more passes necessary. Do that @@ -81,6 +88,79 @@ namespace odb } } + void schema_catalog:: + migrate_schema_impl (database& db, + schema_version v, + const string& name, + migrate_mode m) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_catalog_impl::const_iterator i (c.find (key (db.id (), name))); + + if (i == c.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + version_map::const_iterator j (vm.find (v)); + + if (j == vm.end ()) + throw unknown_schema_version (v); + + const migrate_functions& fs (j->second); + + // Run the passes until we ran them all or all the functions + // return false, which means no more passes necessary. + // + for (bool pre (m != migrate_post);; pre = false) + { + for (unsigned short pass (1); pass < 3; ++pass) + { + bool done (true); + + for (migrate_functions::const_iterator i (fs.begin ()), e (fs.end ()); + i != e; ++i) + { + if ((*i) (db, pass, pre)) + done = false; + } + + if (done) + break; + } + + if (!pre || m != migrate_both) + break; + } + } + + schema_version schema_catalog:: + next_version (database_id id, schema_version current, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_catalog_impl::const_iterator i (c.find (key (id, name))); + + if (i == c.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + version_map::const_iterator j (vm.upper_bound (current)); + return j != vm.end () ? j->first : 0; + } + + schema_version schema_catalog:: + latest_version (database_id id, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_catalog_impl::const_iterator i (c.find (key (id, name))); + + if (i == c.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + assert (!vm.empty ()); + return vm.rbegin ()->first; + } + // schema_catalog_init // schema_catalog_init:: @@ -99,12 +179,26 @@ namespace odb delete catalog; } - // schema_catalog_entry + // schema_catalog_create_entry + // + schema_catalog_create_entry:: + schema_catalog_create_entry (database_id id, + const char* name, + create_function cf) + { + schema_catalog_impl& c (*schema_catalog_init::catalog); + c[key(id, name)].create.push_back (cf); + } + + // schema_catalog_migrate_entry // - schema_catalog_entry:: - schema_catalog_entry (database_id id, const char* name, create_function cf) + schema_catalog_migrate_entry:: + schema_catalog_migrate_entry (database_id id, + const char* name, + schema_version v, + migrate_function mf) { schema_catalog_impl& c (*schema_catalog_init::catalog); - c[key(id, name)].push_back (cf); + c[key(id, name)].migrate[v].push_back (mf); } } -- cgit v1.1