summaryrefslogtreecommitdiff
path: root/platform/default/sqlite3.cpp
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2018-05-08 10:40:35 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2018-05-09 07:32:16 -0700
commita1195f6a9dc57910f7c3e6c9217e3041929a01fb (patch)
tree850834874e2d77a4cd89b92853d441020b2d8b43 /platform/default/sqlite3.cpp
parentd1dff1d6e782bc6e9d7a7df27e566bf1f1cf862b (diff)
downloadqtlocation-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.cpp37
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)) {}