aboutsummaryrefslogtreecommitdiff
path: root/odb/schema-catalog.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/schema-catalog.cxx')
-rw-r--r--odb/schema-catalog.cxx116
1 files changed, 105 insertions, 11 deletions
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 <map>
#include <vector>
+#include <cassert>
#include <odb/database.hxx>
#include <odb/exceptions.hxx>
@@ -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<database_id, string> key;
typedef vector<create_function> create_functions;
- struct schema_catalog_impl: map<key, create_functions> {};
+ typedef vector<migrate_function> migrate_functions;
+ typedef map<schema_version, migrate_functions> version_map;
+
+ struct schema_functions
+ {
+ create_functions create;
+ version_map migrate;
+ };
+
+ struct schema_catalog_impl: map<key, schema_functions> {};
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);
}
}