diff options
Diffstat (limited to 'bpkg/database.cxx')
-rw-r--r-- | bpkg/database.cxx | 297 |
1 files changed, 175 insertions, 122 deletions
diff --git a/bpkg/database.cxx b/bpkg/database.cxx index 451ade3..65e3af8 100644 --- a/bpkg/database.cxx +++ b/bpkg/database.cxx @@ -3,13 +3,13 @@ #include <bpkg/database.hxx> +#include <sqlite3.h> // @@ TMP sqlite3_libversion_number() + #include <map> #include <odb/schema-catalog.hxx> #include <odb/sqlite/exceptions.hxx> -#include <libbutl/sha256.mxx> - #include <bpkg/package.hxx> #include <bpkg/package-odb.hxx> #include <bpkg/diagnostics.hxx> @@ -61,130 +61,95 @@ namespace bpkg template <odb::schema_version v> using migration_entry = odb::data_migration_entry<v, DB_SCHEMA_VERSION_BASE>; - static const migration_entry<8> - migrate_v8 ([] (odb::database& db) - { - for (shared_ptr<repository> r: pointer_result (db.query<repository> ())) - { - if (!r->name.empty ()) // Non-root repository? - { - r->local = r->location.local (); - db.update (r); - } - } - }); - - static const migration_entry<9> - migrate_v9 ([] (odb::database& db) - { - // Add the unnamed self-link of the target type. - // - shared_ptr<configuration> sl ( - make_shared<configuration> (optional<string> (), "target")); - - db.persist (sl); - db.execute (string ("UPDATE \"main\".selected_package_prerequisites ") + - "SET configuration = '" + sl->uuid.string () + "'"); - }); - - static const migration_entry<10> - migrate_v10 ([] (odb::database& db) + // @@ Since there is no proper support for dropping table columns not in + // SQLite prior to 3.35.5 nor in ODB, we will drop the + // available_package_dependency_alternatives.dep_* columns manually. We, + // however, cannot do it here since ODB will try to set the dropped + // column values to NULL at the end of migration. Thus, we will do it + // ad hoc after the below schema_catalog::migrate() call. + // + // NOTE: remove the mentioned ad hoc migration when removing this + // function. + // + static const migration_entry<13> + migrate_v13 ([] (odb::database& db) { - // Create the multi-column index for the configuration and prerequisite - // columns of the selected_package_prerequisites table. + // Note that + // available_package_dependency_alternative_dependencies.alternative_index + // is copied from available_package_dependency_alternatives.index and + // available_package_dependency_alternative_dependencies.index is set to 0. // db.execute ( - "CREATE INDEX " - "\"main\".selected_package_prerequisites_configuration_prerequisite_i " - "ON selected_package_prerequisites (configuration, prerequisite)"); + "INSERT INTO \"main\".\"available_package_dependency_alternative_dependencies\" " + "(\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"alternative_index\", " + "\"index\", " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"dep_min_version_iteration\", " + "\"dep_min_version_upstream\", " + "\"dep_min_version_release\", " + "\"dep_max_version_epoch\", " + "\"dep_max_version_canonical_upstream\", " + "\"dep_max_version_canonical_release\", " + "\"dep_max_version_revision\", " + "\"dep_max_version_iteration\", " + "\"dep_max_version_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\") " + "SELECT " + "\"name\", " + "\"version_epoch\", " + "\"version_canonical_upstream\", " + "\"version_canonical_release\", " + "\"version_revision\", " + "\"version_iteration\", " + "\"dependency_index\", " + "\"index\", " + "0, " + "\"dep_name\", " + "\"dep_min_version_epoch\", " + "\"dep_min_version_canonical_upstream\", " + "\"dep_min_version_canonical_release\", " + "\"dep_min_version_revision\", " + "\"dep_min_version_iteration\", " + "\"dep_min_version_upstream\", " + "\"dep_min_version_release\", " + "\"dep_max_version_epoch\", " + "\"dep_max_version_canonical_upstream\", " + "\"dep_max_version_canonical_release\", " + "\"dep_max_version_revision\", " + "\"dep_max_version_iteration\", " + "\"dep_max_version_upstream\", " + "\"dep_max_version_release\", " + "\"dep_min_open\", " + "\"dep_max_open\" " + "FROM \"main\".\"available_package_dependency_alternatives\""); }); - static const migration_entry<12> - migrate_v12 ([] (odb::database& d) + // @@ Since there is no proper support for dropping table columns not in + // SQLite prior to 3.35.5 nor in ODB, we will drop the + // available_package_dependencies.conditional column manually. We, + // however, cannot do it here since ODB will try to set the dropped + // column values to NULL at the end of migration. Thus, we will do it + // ad hoc after the below schema_catalog::migrate() call. + // + // NOTE: remove the mentioned ad hoc migration when removing this + // function. + // + static const migration_entry<14> + migrate_v14 ([] (odb::database&) { - // Drop foreign key constraint for the prerequisite column of the - // selected_package_prerequisites table. - // - // Note that since SQLite provides no API to drop constraints we will - // rename the selected_package_prerequisites table, create the new table - // without the constraint, and copy the data into the new table. - // - // Also note that we can only perform migration of the main database, - // since dropping index and table in an attached database fails by some - // reason with the SQLITE_LOCKED error. This, however, is probably ok - // since the host and build system module configurations are already - // created without this constraint and its highly unlikely to encounter an - // already migrated (up to version 11) a linked target configuration. - // - database& db (static_cast<database&> (d)); - - if (!db.main ()) - return; - - db.execute ("ALTER TABLE \"main\".\"selected_package_prerequisites\" " - "RENAME TO \"selected_package_prerequisites_old\""); - - db.execute ("CREATE TABLE \"main\".\"selected_package_prerequisites\" (\n" - " \"package\" TEXT NULL COLLATE NOCASE,\n" - " \"configuration\" TEXT NULL,\n" - " \"prerequisite\" TEXT NULL COLLATE NOCASE,\n" - " \"min_version_epoch\" INTEGER NULL,\n" - " \"min_version_canonical_upstream\" TEXT NULL,\n" - " \"min_version_canonical_release\" TEXT NULL,\n" - " \"min_version_revision\" INTEGER NULL,\n" - " \"min_version_iteration\" INTEGER NULL,\n" - " \"min_version_upstream\" TEXT NULL,\n" - " \"min_version_release\" TEXT NULL,\n" - " \"max_version_epoch\" INTEGER NULL,\n" - " \"max_version_canonical_upstream\" TEXT NULL,\n" - " \"max_version_canonical_release\" TEXT NULL,\n" - " \"max_version_revision\" INTEGER NULL,\n" - " \"max_version_iteration\" INTEGER NULL,\n" - " \"max_version_upstream\" TEXT NULL,\n" - " \"max_version_release\" TEXT NULL,\n" - " \"min_open\" INTEGER NULL,\n" - " \"max_open\" INTEGER NULL,\n" - " CONSTRAINT \"package_fk\"\n" - " FOREIGN KEY (\"package\")\n" - " REFERENCES \"selected_package\" (\"name\")\n" - " ON DELETE CASCADE)"); - - db.execute ("INSERT INTO \"main\".\"selected_package_prerequisites\" " - "SELECT " - "\"package\", " - "\"configuration\", " - "\"prerequisite\", " - "\"min_version_epoch\", " - "\"min_version_canonical_upstream\", " - "\"min_version_canonical_release\", " - "\"min_version_revision\", " - "\"min_version_iteration\", " - "\"min_version_upstream\", " - "\"min_version_release\", " - "\"max_version_epoch\", " - "\"max_version_canonical_upstream\", " - "\"max_version_canonical_release\", " - "\"max_version_revision\", " - "\"max_version_iteration\", " - "\"max_version_upstream\", " - "\"max_version_release\", " - "\"min_open\", " - "\"max_open\" " - "FROM \"main\".\"selected_package_prerequisites_old\""); - - db.execute ("DROP TABLE \"main\".\"selected_package_prerequisites_old\""); - - // Create the indexes after dropping the old table to make sure the old - // indexes are also dropped to date. - // - db.execute ("CREATE INDEX " - "\"main\".\"selected_package_prerequisites_package_i\"\n" - " ON \"selected_package_prerequisites\" (\"package\")"); - - db.execute ( - "CREATE INDEX " - "\"main\".selected_package_prerequisites_configuration_prerequisite_i " - "ON selected_package_prerequisites (configuration, prerequisite)"); }); static inline path @@ -384,7 +349,6 @@ namespace bpkg else config_orig = config; - string = '[' + config_orig.representation () + ']'; try @@ -490,6 +454,54 @@ namespace bpkg // schema_catalog::migrate (*this); + // Note that the potential data corruption with `DROP COLUMN` is fixed + // in 3.35.5. + // + // @@ TMP Get rid of manual column dropping when ODB starts supporting + // that properly. Not doing so will result in failure of the below + // queries. + // + if (sqlite3_libversion_number () >= 3035005) + { + auto drop = [this] (const char* table, const char* column) + { + execute (std::string ("ALTER TABLE \"main\".") + table + + " DROP COLUMN \"" + column + '"'); + }; + + // @@ TMP See migrate_v13() for details. + // + if (sv < 13) + { + const char* cs[] = {"dep_name", + "dep_min_version_epoch", + "dep_min_version_canonical_upstream", + "dep_min_version_canonical_release", + "dep_min_version_revision", + "dep_min_version_iteration", + "dep_min_version_upstream", + "dep_min_version_release", + "dep_max_version_epoch", + "dep_max_version_canonical_upstream", + "dep_max_version_canonical_release", + "dep_max_version_revision", + "dep_max_version_iteration", + "dep_max_version_upstream", + "dep_max_version_release", + "dep_min_open", + "dep_max_open", + nullptr}; + + for (const char** c (cs); *c != nullptr; ++c) + drop ("available_package_dependency_alternatives", *c); + } + + // @@ TMP See migrate_v14() for details. + // + if (sv < 14) + drop ("available_package_dependencies", "conditional"); + } + for (auto& c: query<configuration> (odb::query<configuration>::id != 0)) { dir_path d (c.effective_path (config)); @@ -565,7 +577,7 @@ namespace bpkg // std::string schema; { - butl::sha256 h (d.string ()); + sha256 h (d.string ()); for (size_t n (4);; ++n) { @@ -936,6 +948,39 @@ namespace bpkg empty_string /* type */); } + linked_databases database:: + cluster_configs (bool sys_rep) + { + linked_databases r; + + // If the database is not in the resulting list, then add it and its + // dependent and dependency configurations, recursively. + // + auto add = [&r, sys_rep] (database& db, const auto& add) + { + if (std::find (r.begin (), r.end (), db) != r.end ()) + return; + + r.push_back (db); + + { + linked_databases cs (db.dependency_configs ()); + for (auto i (cs.begin_linked ()); i != cs.end (); ++i) + add (*i, add); + } + + { + linked_databases cs (db.dependent_configs (sys_rep)); + for (auto i (cs.begin_linked ()); i != cs.end (); ++i) + add (*i, add); + } + }; + + add (*this, add); + + return r; + } + database& database:: find_attached (uint64_t id, bool s) { @@ -1074,4 +1119,12 @@ namespace bpkg { return *this == main_database (); } + + // compare_lazy_ptr + // + bool compare_lazy_ptr:: + less (const odb::database& x, const odb::database& y) const + { + return static_cast<const database&> (x) < static_cast<const database&> (y); + } } |