diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2018-05-08 10:40:35 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2018-05-09 07:32:16 -0700 |
commit | a1195f6a9dc57910f7c3e6c9217e3041929a01fb (patch) | |
tree | 850834874e2d77a4cd89b92853d441020b2d8b43 /platform/default/sqlite3.cpp | |
parent | d1dff1d6e782bc6e9d7a7df27e566bf1f1cf862b (diff) | |
download | qtlocation-mapboxgl-a1195f6a9dc57910f7c3e6c9217e3041929a01fb.tar.gz |
Avoid exceptions for flow control during database creation
Unfortuntely, it's difficult to avoid all exceptions, because sqlite3_open_v2 does not reliably return SQLITE_NOTADB if the file is not a database. However, this should avoid cases where developers misinterpret the SQLITE_CANTOPEN exception as a crash, which is the common case.
Diffstat (limited to 'platform/default/sqlite3.cpp')
-rw-r--r-- | platform/default/sqlite3.cpp | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/platform/default/sqlite3.cpp b/platform/default/sqlite3.cpp index 8f9c34191f..776adc8f3a 100644 --- a/platform/default/sqlite3.cpp +++ b/platform/default/sqlite3.cpp @@ -14,27 +14,20 @@ namespace sqlite { class DatabaseImpl { public: - DatabaseImpl(const char* filename, int flags) + DatabaseImpl(sqlite3* db_) + : db(db_) { - const int error = sqlite3_open_v2(filename, &db, flags, nullptr); - if (error != SQLITE_OK) { - const auto message = sqlite3_errmsg(db); - db = nullptr; - throw Exception { error, message }; - } } ~DatabaseImpl() { - if (!db) return; - const int error = sqlite3_close(db); if (error != SQLITE_OK) { mbgl::Log::Error(mbgl::Event::Database, "%s (Code %i)", sqlite3_errmsg(db), error); } } - sqlite3* db = nullptr; + sqlite3* db; }; class StatementImpl { @@ -164,11 +157,29 @@ const static bool sqliteVersionCheck __attribute__((unused)) = []() { return true; }(); -Database::Database(const std::string &filename, int flags) - : impl(std::make_unique<DatabaseImpl>(filename.c_str(), flags)) -{ +mapbox::util::variant<Database, Exception> Database::tryOpen(const std::string &filename, int flags) { + sqlite3* db = nullptr; + const int error = sqlite3_open_v2(filename.c_str(), &db, flags, nullptr); + if (error != SQLITE_OK) { + const auto message = sqlite3_errmsg(db); + return Exception { error, message }; + } + return Database(std::make_unique<DatabaseImpl>(db)); } +Database Database::open(const std::string &filename, int flags) { + auto result = tryOpen(filename, flags); + if (result.is<Exception>()) { + throw result.get<Exception>(); + } else { + return std::move(result.get<Database>()); + } +} + +Database::Database(std::unique_ptr<DatabaseImpl> impl_) + : impl(std::move(impl_)) +{} + Database::Database(Database &&other) : impl(std::move(other.impl)) {} |