summaryrefslogtreecommitdiff
path: root/libodb/odb/schema-catalog.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libodb/odb/schema-catalog.hxx')
-rw-r--r--libodb/odb/schema-catalog.hxx392
1 files changed, 392 insertions, 0 deletions
diff --git a/libodb/odb/schema-catalog.hxx b/libodb/odb/schema-catalog.hxx
new file mode 100644
index 0000000..c38cd4f
--- /dev/null
+++ b/libodb/odb/schema-catalog.hxx
@@ -0,0 +1,392 @@
+// file : odb/schema-catalog.hxx
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#ifndef ODB_SCHEMA_CATALOG_HXX
+#define ODB_SCHEMA_CATALOG_HXX
+
+#include <odb/pre.hxx>
+
+#include <odb/details/config.hxx> // ODB_CXX11
+
+#include <string>
+#include <cstddef> // std::size_t
+
+#ifdef ODB_CXX11
+# include <utility> // std::move
+# include <functional> // std::function
+# include <type_traits> // std::enable_if, std::is_convertible
+#endif
+
+#include <odb/forward.hxx> // schema_version, odb::core
+#include <odb/database.hxx>
+
+#include <odb/details/export.hxx>
+#include <odb/details/unused.hxx>
+#include <odb/details/meta/static-assert.hxx>
+
+namespace odb
+{
+ class LIBODB_EXPORT schema_catalog
+ {
+ public:
+ // Schema creation.
+ //
+ static void
+ create_schema (database&, const std::string& name = "", bool drop = true);
+
+ static void
+ drop_schema (database&, const std::string& name = "");
+
+ // Schema migration.
+ //
+ public:
+ static void
+ migrate_schema_pre (database& db,
+ schema_version v,
+ const std::string& name = "")
+ {
+ migrate_schema_impl (db, v, name, migrate_pre);
+ }
+
+ static void
+ migrate_schema_post (database& db,
+ schema_version v,
+ const std::string& name = "")
+ {
+ migrate_schema_impl (db, v, name, migrate_post);
+ }
+
+ static void
+ migrate_schema (database& db,
+ schema_version v,
+ const std::string& name = "")
+ {
+ migrate_schema_impl (db, v, name, migrate_both);
+ }
+
+ // Data migration.
+ //
+ public:
+ // If version is 0, then use the current database version and also
+ // check whether we are in migration. Returns the number of calls made.
+ //
+ static std::size_t
+ migrate_data (database&,
+ schema_version = 0,
+ const std::string& name = "");
+
+ typedef void data_migration_function_type (database&);
+ typedef data_migration_function_type* data_migration_function_ptr;
+
+ typedef details::function_wrapper<data_migration_function_type>
+ data_migration_function_wrapper;
+
+ // The following three variants of the registration functions make
+ // sure that the version is greater that the base model version.
+ // This helps with identifying and removing data migration function
+ // that are no longer required.
+ //
+ // Data migration functions are called in the order of registration.
+ //
+#ifndef ODB_CXX11
+ template <schema_version v, schema_version base>
+ static void
+ data_migration_function (data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ data_migration_function<v, base> (id_common, f, name);
+ }
+
+#else
+ template <schema_version v, schema_version base, typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (F f, const std::string& name = "")
+ {
+ data_migration_function<v, base> (id_common, std::move (f), name);
+ }
+#endif
+
+ // Database-specific data migration.
+ //
+#ifndef ODB_CXX11
+ template <schema_version v, schema_version base>
+ static void
+ data_migration_function (database& db,
+ data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ data_migration_function<v, base> (db.id (), f, name);
+ }
+#else
+ template <schema_version v, schema_version base, typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (database& db, F f, const std::string& name = "")
+ {
+ data_migration_function<v, base> (db.id (), std::move (f), name);
+ }
+#endif
+
+#ifndef ODB_CXX11
+ template <schema_version v, schema_version base>
+ static void
+ data_migration_function (database_id id,
+ data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ // If the data migration version is below the base model version
+ // then it will never be called.
+ //
+
+ // Poor man's static_assert.
+ //
+ typedef details::meta::static_assert_test<(v > base || base == 0)>
+ data_migration_function_is_no_longer_necessary;
+
+ char sa [sizeof (data_migration_function_is_no_longer_necessary)];
+ ODB_POTENTIALLY_UNUSED (sa);
+
+ data_migration_function (id, v, f, name);
+ }
+#else
+ template <schema_version v, schema_version base, typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (database_id id, F f, const std::string& name = "")
+ {
+ // If the data migration version is below the base model version
+ // then it will never be called.
+ //
+ static_assert (v > base || base == 0,
+ "data migration function is no longer necessary");
+
+ data_migration_function (id, v, std::move (f), name);
+ }
+#endif
+
+ // The same as above but take the version as an argument and do
+ // not check whether it is greater than the base model version.
+ //
+#ifndef ODB_CXX11
+ static void
+ data_migration_function (schema_version v,
+ data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ data_migration_function (id_common, v, f, name);
+ }
+#else
+ template <typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (schema_version v,
+ F f,
+ const std::string& name = "")
+ {
+ data_migration_function (id_common, v, std::move (f), name);
+ }
+#endif
+
+#ifndef ODB_CXX11
+ static void
+ data_migration_function (database& db,
+ schema_version v,
+ data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ data_migration_function (db.id (), v, f, name);
+ }
+#else
+ template <typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (database& db,
+ schema_version v,
+ F f,
+ const std::string& name = "")
+ {
+ data_migration_function (db.id (), v, std::move (f), name);
+ }
+#endif
+
+#ifndef ODB_CXX11
+ static void
+ data_migration_function (database_id i,
+ schema_version v,
+ data_migration_function_ptr f,
+ const std::string& name = "")
+ {
+ data_migration_function (i,
+ v,
+ data_migration_function_wrapper (f),
+ name);
+ }
+#else
+ template <typename F>
+ static typename std::enable_if<
+ std::is_convertible<
+ F, std::function<data_migration_function_type>>::value, void>::type
+ data_migration_function (database_id i,
+ schema_version v,
+ F f,
+ const std::string& name = "")
+ {
+ data_migration_function (
+ i,
+ v,
+ data_migration_function_wrapper (std::move (f)),
+ name);
+ }
+#endif
+
+ private:
+ static void
+ data_migration_function (database_id,
+ schema_version,
+ data_migration_function_wrapper,
+ const std::string& name);
+
+ // Combined schema and data migration.
+ //
+ public:
+ // Migrate both schema and data to the specified version. If version
+ // is not specified, then migrate to the current model version.
+ //
+ static void
+ migrate (database&, schema_version = 0, const std::string& name = "");
+
+ // Schema version information.
+ //
+ public:
+ // Return the base model version.
+ //
+ static schema_version
+ base_version (const database& db, const std::string& name = "")
+ {
+ return base_version (db.id (), name);
+ }
+
+ static schema_version
+ base_version (database_id, const std::string& name = "");
+
+ // Return the current model version.
+ //
+ static schema_version
+ current_version (const database& db, const std::string& name = "")
+ {
+ return current_version (db.id (), name);
+ }
+
+ static schema_version
+ current_version (database_id, const std::string& name = "");
+
+ // Return current model version + 1 (that is, one past current) if
+ // the passed version is equal to or greater than current. If the
+ // version is not specified, then use the current database version.
+ //
+ static schema_version
+ next_version (const database& db,
+ schema_version v = 0,
+ const std::string& name = "")
+ {
+ return next_version (db.id (), v == 0 ? db.schema_version () : v, name);
+ }
+
+ static schema_version
+ next_version (database_id,
+ schema_version,
+ const std::string& name = "");
+
+ // Schema existence.
+ //
+ public:
+ // Test for presence of a schema with a specific name.
+ //
+ static bool
+ exists (const database& db, const std::string& name = "")
+ {
+ return exists (db.id (), name);
+ }
+
+ static bool
+ exists (database_id, const std::string& name = "");
+
+ private:
+ enum migrate_mode
+ {
+ migrate_pre,
+ migrate_post,
+ migrate_both
+ };
+
+ static void
+ migrate_schema_impl (database&,
+ schema_version,
+ const std::string& name,
+ migrate_mode);
+ };
+
+ // Static data migration function registration.
+ //
+ template <schema_version v, schema_version base>
+ struct data_migration_entry
+ {
+ typedef schema_catalog::data_migration_function_type function_type;
+
+#ifndef ODB_CXX11
+ data_migration_entry (function_type* f, const std::string& name = "")
+ {
+ schema_catalog::data_migration_function<v, base> (f, name);
+ }
+#else
+ template <typename F>
+ data_migration_entry (F f,
+ const std::string& name = "",
+ typename std::enable_if<std::is_convertible<
+ F, std::function<function_type>>::value>
+ ::type* = 0)
+ {
+ schema_catalog::data_migration_function<v, base> (std::move (f), name);
+ }
+#endif
+
+#ifndef ODB_CXX11
+ data_migration_entry (database_id id,
+ function_type *f,
+ const std::string& name = "")
+ {
+ schema_catalog::data_migration_function<v, base> (id, v, f, name);
+ }
+#else
+ template <typename F>
+ data_migration_entry (database_id id,
+ F f,
+ const std::string& name = "",
+ typename std::enable_if<std::is_convertible<
+ F, std::function<function_type>>::value>
+ ::type* = 0)
+ {
+ schema_catalog::data_migration_function<v, base> (id,
+ v,
+ std::move (f),
+ name);
+ }
+#endif
+ };
+
+ namespace common
+ {
+ using odb::schema_catalog;
+ using odb::data_migration_entry;
+ }
+}
+
+#include <odb/post.hxx>
+
+#endif // ODB_SCHEMA_CATALOG_HXX