diff options
Diffstat (limited to 'platform/default/mbgl')
-rw-r--r-- | platform/default/mbgl/storage/offline_database.cpp | 53 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_database.hpp | 3 |
2 files changed, 56 insertions, 0 deletions
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 79bc3c8f27..30b76d1666 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -7,6 +7,7 @@ #include <mbgl/util/logging.hpp> #include "offline_schema.hpp" +#include "merge_sideloaded.hpp" #include "sqlite3.hpp" @@ -637,6 +638,58 @@ OfflineDatabase::createRegion(const OfflineRegionDefinition& definition, return unexpected<std::exception_ptr>(std::current_exception()); } +expected<OfflineRegions, std::exception_ptr> +OfflineDatabase::mergeDatabase(const std::string& sideDatabasePath) { + try { + // clang-format off + mapbox::sqlite::Query query{ getStatement("ATTACH DATABASE ?1 AS side") }; + // clang-format on + + query.bind(1, sideDatabasePath); + query.run(); + } catch (const mapbox::sqlite::Exception& ex) { + handleError(ex, "merge databse attach"); + return unexpected<std::exception_ptr>(std::current_exception()); + } + try { + // Attaching an accessible path without a db file creates a new temporary + //database and attaches it. Check for matching schema version. + auto sideUserVersion = static_cast<int>(getPragma<int64_t>("PRAGMA side.user_version")); + if (sideUserVersion != 6) { + Log::Warning(Event::Database, "Merge database does not match user_version of main database"); + throw std::runtime_error("merge database does not match schema or has incorrect user_version"); + } + + mapbox::sqlite::Transaction transaction(*db); + db->exec(mergeSideloadedDatabaseSQL); + transaction.commit(); + + // clang-format off + mapbox::sqlite::Query query{ getStatement( + "SELECT r.id, r.definition, r.description " + "FROM side.regions sr " + "JOIN regions r ON sr.definition = r.definition") }; + // clang-format on + + OfflineRegions result; + while (query.run()) { + // Construct, then move because this constructor is private. + OfflineRegion region(query.get<int64_t>(0), + decodeOfflineRegionDefinition(query.get<std::string>(1)), + query.get<std::vector<uint8_t>>(2)); + result.emplace_back(std::move(region)); + } + db->exec("DETACH DATABASE side"); + // Explicit move to avoid triggering the copy constructor. + return { std::move(result) }; + } catch (const mapbox::sqlite::Exception& ex) { + db->exec("DETACH DATABASE side"); + handleError(ex, "merge databse post merge sql"); + return unexpected<std::exception_ptr>(std::current_exception()); + } + return {}; +} + expected<OfflineRegionMetadata, std::exception_ptr> OfflineDatabase::updateMetadata(const int64_t regionID, const OfflineRegionMetadata& metadata) try { // clang-format off diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index fbe6c707e1..993f36a606 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -53,6 +53,9 @@ public: expected<OfflineRegion, std::exception_ptr> createRegion(const OfflineRegionDefinition&, const OfflineRegionMetadata&); + expected<OfflineRegions, std::exception_ptr> + mergeDatabase(const std::string& sideDatabasePath); + expected<OfflineRegionMetadata, std::exception_ptr> updateMetadata(const int64_t regionID, const OfflineRegionMetadata&); |