diff options
Diffstat (limited to 'platform')
-rw-r--r-- | platform/default/mbgl/storage/offline_database.cpp | 116 | ||||
-rw-r--r-- | platform/default/mbgl/storage/offline_database.hpp | 1 | ||||
-rw-r--r-- | platform/default/sqlite3.hpp | 5 |
3 files changed, 65 insertions, 57 deletions
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 2c4ee2da31..24fc0f2335 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -28,67 +28,70 @@ OfflineDatabase::~OfflineDatabase() { } void OfflineDatabase::ensureSchema() { - if (path != ":memory:") { - auto result = mapbox::sqlite::Database::tryOpen(path, mapbox::sqlite::ReadWrite); - if (result.is<mapbox::sqlite::Exception>()) { - const auto& ex = result.get<mapbox::sqlite::Exception>(); - if (ex.code == mapbox::sqlite::ResultCode::NotADB) { - // Corrupted; blow it away. - removeExisting(); - } else if (ex.code == mapbox::sqlite::ResultCode::CantOpen) { - // Doesn't exist yet. - } else { - Log::Error(Event::Database, "Unexpected error connecting to database: %s", ex.what()); - throw ex; - } + auto result = mapbox::sqlite::Database::tryOpen(path, mapbox::sqlite::ReadWriteCreate); + if (result.is<mapbox::sqlite::Exception>()) { + const auto& ex = result.get<mapbox::sqlite::Exception>(); + if (ex.code == mapbox::sqlite::ResultCode::NotADB) { + // Corrupted; blow it away. + removeExisting(); + result = mapbox::sqlite::Database::open(path, mapbox::sqlite::ReadWriteCreate); } else { - try { - db = std::make_unique<mapbox::sqlite::Database>(std::move(result.get<mapbox::sqlite::Database>())); - db->setBusyTimeout(Milliseconds::max()); - db->exec("PRAGMA foreign_keys = ON"); - - switch (userVersion()) { - case 0: - case 1: - // cache-only database; ok to delete - removeExisting(); - break; - case 2: - migrateToVersion3(); - // fall through - case 3: - case 4: - migrateToVersion5(); - // fall through - case 5: - migrateToVersion6(); - // fall through - case 6: - // happy path; we're done - return; - default: - // downgrade, delete the database - removeExisting(); - break; - } - } catch (const mapbox::sqlite::Exception& ex) { - // Unfortunately, SQLITE_NOTADB is not always reported upon opening the database. - // Apparently sometimes it is delayed until the first read operation. - if (ex.code == mapbox::sqlite::ResultCode::NotADB) { - removeExisting(); - } else { - throw; - } - } + Log::Error(Event::Database, "Unexpected error connecting to database: %s", ex.what()); + throw ex; } } try { - #include "offline_schema.cpp.include" - - db = std::make_unique<mapbox::sqlite::Database>(mapbox::sqlite::Database::open(path, mapbox::sqlite::ReadWrite | mapbox::sqlite::Create)); + assert(result.is<mapbox::sqlite::Database>()); + db = std::make_unique<mapbox::sqlite::Database>(std::move(result.get<mapbox::sqlite::Database>())); db->setBusyTimeout(Milliseconds::max()); db->exec("PRAGMA foreign_keys = ON"); + + switch (userVersion()) { + case 0: + case 1: + // Newly created database, or old cache-only database; remove old table if it exists. + removeOldCacheTable(); + break; + case 2: + migrateToVersion3(); + // fall through + case 3: + case 4: + migrateToVersion5(); + // fall through + case 5: + migrateToVersion6(); + // fall through + case 6: + // happy path; we're done + return; + default: + // downgrade, delete the database + removeExisting(); + break; + } + } catch (const mapbox::sqlite::Exception& ex) { + // Unfortunately, SQLITE_NOTADB is not always reported upon opening the database. + // Apparently sometimes it is delayed until the first read operation. + if (ex.code == mapbox::sqlite::ResultCode::NotADB) { + removeExisting(); + } else { + throw; + } + } + + try { + #include "offline_schema.cpp.include" + + // When downgrading the database, or when the database is corrupt, we've deleted the old database handle, + // so we need to reopen it. + if (!db) { + db = std::make_unique<mapbox::sqlite::Database>(mapbox::sqlite::Database::open(path, mapbox::sqlite::ReadWriteCreate)); + db->setBusyTimeout(Milliseconds::max()); + db->exec("PRAGMA foreign_keys = ON"); + } + db->exec("PRAGMA auto_vacuum = INCREMENTAL"); db->exec("PRAGMA journal_mode = DELETE"); db->exec("PRAGMA synchronous = FULL"); @@ -117,6 +120,11 @@ void OfflineDatabase::removeExisting() { } } +void OfflineDatabase::removeOldCacheTable() { + db->exec("DROP TABLE IF EXISTS http_cache"); + db->exec("VACUUM"); +} + void OfflineDatabase::migrateToVersion3() { db->exec("PRAGMA auto_vacuum = INCREMENTAL"); db->exec("VACUUM"); diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index 639bd42e2d..38eb3783ba 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -70,6 +70,7 @@ private: int userVersion(); void ensureSchema(); void removeExisting(); + void removeOldCacheTable(); void migrateToVersion3(); void migrateToVersion5(); void migrateToVersion6(); diff --git a/platform/default/sqlite3.hpp b/platform/default/sqlite3.hpp index 8686c55666..612e92acc6 100644 --- a/platform/default/sqlite3.hpp +++ b/platform/default/sqlite3.hpp @@ -11,9 +11,8 @@ namespace mapbox { namespace sqlite { enum OpenFlag : int { - ReadOnly = 0x00000001, - ReadWrite = 0x00000002, - Create = 0x00000004, + ReadOnly = 0b001, + ReadWriteCreate = 0b110, }; enum class ResultCode : int { |