diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2018-02-06 17:55:50 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2018-03-02 14:26:25 +0100 |
commit | 136e536159a1e22aa4a92c4e6463893600b809d0 (patch) | |
tree | 954be65c8f98b85bb8748d204878daa503c6e71a /platform/default/sqlite3.cpp | |
parent | 5ca38bbde93d273a2a4febb42ff5de53b90e1350 (diff) | |
download | qtlocation-mapboxgl-136e536159a1e22aa4a92c4e6463893600b809d0.tar.gz |
[core, qt] move self-resetting Statement/Query object to shared header
Diffstat (limited to 'platform/default/sqlite3.cpp')
-rw-r--r-- | platform/default/sqlite3.cpp | 238 |
1 files changed, 123 insertions, 115 deletions
diff --git a/platform/default/sqlite3.cpp b/platform/default/sqlite3.cpp index ba7a1f6446..8a567d602e 100644 --- a/platform/default/sqlite3.cpp +++ b/platform/default/sqlite3.cpp @@ -201,85 +201,93 @@ void Database::exec(const std::string &sql) { } } -Statement Database::prepare(const char *query) { - assert(impl); - return Statement(this, query); +Statement::Statement(Database& db, const char* sql) + : impl(std::make_unique<StatementImpl>(db.impl->db, sql)) { } -Statement::Statement(Database *db, const char *sql) - : impl(std::make_unique<StatementImpl>(db->impl->db, sql)) -{ +Statement::~Statement() { +#ifndef NDEBUG + // Crash if we're destructing this object while we know a Query object references this. + assert(!used); +#endif } -Statement::Statement(Statement &&other) { - *this = std::move(other); -} +Query::Query(Statement& stmt_) : stmt(stmt_) { + assert(stmt.impl); -Statement &Statement::operator=(Statement &&other) { - std::swap(impl, other.impl); - return *this; +#ifndef NDEBUG + assert(!stmt.used); + stmt.used = true; +#endif } -Statement::~Statement() = default; +Query::~Query() { + reset(); + clearBindings(); -template <> void Statement::bind(int offset, std::nullptr_t) { - assert(impl); - impl->check(sqlite3_bind_null(impl->stmt, offset)); +#ifndef NDEBUG + stmt.used = false; +#endif } -template <> void Statement::bind(int offset, int8_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, std::nullptr_t) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_null(stmt.impl->stmt, offset)); } -template <> void Statement::bind(int offset, int16_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, int8_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, int32_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, int16_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, int64_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, int32_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, uint8_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, int64_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, uint16_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, uint8_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, uint32_t value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, value)); +template <> void Query::bind(int offset, uint16_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, float value) { - assert(impl); - impl->check(sqlite3_bind_double(impl->stmt, offset, value)); +template <> void Query::bind(int offset, uint32_t value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, double value) { - assert(impl); - impl->check(sqlite3_bind_double(impl->stmt, offset, value)); +template <> void Query::bind(int offset, float value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_double(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, bool value) { - assert(impl); - impl->check(sqlite3_bind_int(impl->stmt, offset, value)); +template <> void Query::bind(int offset, double value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_double(stmt.impl->stmt, offset, value)); } -template <> void Statement::bind(int offset, const char *value) { - assert(impl); - impl->check(sqlite3_bind_text(impl->stmt, offset, value, -1, SQLITE_STATIC)); +template <> void Query::bind(int offset, bool value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int(stmt.impl->stmt, offset, value)); +} + +template <> void Query::bind(int offset, const char *value) { + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_text(stmt.impl->stmt, offset, value, -1, SQLITE_STATIC)); } // We currently cannot use sqlite3_bind_blob64 / sqlite3_bind_text64 because they @@ -289,40 +297,40 @@ template <> void Statement::bind(int offset, const char *value) { // According to http://stackoverflow.com/questions/14288128/what-version-of-sqlite-does-ios-provide, // the first iOS version with 3.8.7+ was 9.0, with 3.8.8. -void Statement::bind(int offset, const char * value, std::size_t length, bool retain) { - assert(impl); +void Query::bind(int offset, const char * value, std::size_t length, bool retain) { + assert(stmt.impl); if (length > std::numeric_limits<int>::max()) { throw std::range_error("value too long for sqlite3_bind_text"); } - impl->check(sqlite3_bind_text(impl->stmt, offset, value, int(length), + stmt.impl->check(sqlite3_bind_text(stmt.impl->stmt, offset, value, int(length), retain ? SQLITE_TRANSIENT : SQLITE_STATIC)); } -void Statement::bind(int offset, const std::string& value, bool retain) { +void Query::bind(int offset, const std::string& value, bool retain) { bind(offset, value.data(), value.size(), retain); } -void Statement::bindBlob(int offset, const void * value, std::size_t length, bool retain) { - assert(impl); +void Query::bindBlob(int offset, const void * value, std::size_t length, bool retain) { + assert(stmt.impl); if (length > std::numeric_limits<int>::max()) { throw std::range_error("value too long for sqlite3_bind_text"); } - impl->check(sqlite3_bind_blob(impl->stmt, offset, value, int(length), + stmt.impl->check(sqlite3_bind_blob(stmt.impl->stmt, offset, value, int(length), retain ? SQLITE_TRANSIENT : SQLITE_STATIC)); } -void Statement::bindBlob(int offset, const std::vector<uint8_t>& value, bool retain) { +void Query::bindBlob(int offset, const std::vector<uint8_t>& value, bool retain) { bindBlob(offset, value.data(), value.size(), retain); } template <> -void Statement::bind( +void Query::bind( int offset, std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> value) { - assert(impl); - impl->check(sqlite3_bind_int64(impl->stmt, offset, std::chrono::system_clock::to_time_t(value))); + assert(stmt.impl); + stmt.impl->check(sqlite3_bind_int64(stmt.impl->stmt, offset, std::chrono::system_clock::to_time_t(value))); } -template <> void Statement::bind(int offset, optional<std::string> value) { +template <> void Query::bind(int offset, optional<std::string> value) { if (!value) { bind(offset, nullptr); } else { @@ -331,7 +339,7 @@ template <> void Statement::bind(int offset, optional<std::string> value) { } template <> -void Statement::bind( +void Query::bind( int offset, optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>> value) { if (!value) { @@ -341,86 +349,86 @@ void Statement::bind( } } -bool Statement::run() { - assert(impl); - const int err = sqlite3_step(impl->stmt); - impl->lastInsertRowId = sqlite3_last_insert_rowid(sqlite3_db_handle(impl->stmt)); - impl->changes = sqlite3_changes(sqlite3_db_handle(impl->stmt)); +bool Query::run() { + assert(stmt.impl); + const int err = sqlite3_step(stmt.impl->stmt); + stmt.impl->lastInsertRowId = sqlite3_last_insert_rowid(sqlite3_db_handle(stmt.impl->stmt)); + stmt.impl->changes = sqlite3_changes(sqlite3_db_handle(stmt.impl->stmt)); if (err == SQLITE_DONE) { return false; } else if (err == SQLITE_ROW) { return true; } else if (err != SQLITE_OK) { - throw Exception { err, sqlite3_errmsg(sqlite3_db_handle(impl->stmt)) }; + throw Exception { err, sqlite3_errmsg(sqlite3_db_handle(stmt.impl->stmt)) }; } else { return false; } } -template <> bool Statement::get(int offset) { - assert(impl); - return sqlite3_column_int(impl->stmt, offset); +template <> bool Query::get(int offset) { + assert(stmt.impl); + return sqlite3_column_int(stmt.impl->stmt, offset); } -template <> int Statement::get(int offset) { - assert(impl); - return sqlite3_column_int(impl->stmt, offset); +template <> int Query::get(int offset) { + assert(stmt.impl); + return sqlite3_column_int(stmt.impl->stmt, offset); } -template <> int64_t Statement::get(int offset) { - assert(impl); - return sqlite3_column_int64(impl->stmt, offset); +template <> int64_t Query::get(int offset) { + assert(stmt.impl); + return sqlite3_column_int64(stmt.impl->stmt, offset); } -template <> double Statement::get(int offset) { - assert(impl); - return sqlite3_column_double(impl->stmt, offset); +template <> double Query::get(int offset) { + assert(stmt.impl); + return sqlite3_column_double(stmt.impl->stmt, offset); } -template <> std::string Statement::get(int offset) { - assert(impl); +template <> std::string Query::get(int offset) { + assert(stmt.impl); return { - reinterpret_cast<const char *>(sqlite3_column_blob(impl->stmt, offset)), - size_t(sqlite3_column_bytes(impl->stmt, offset)) + reinterpret_cast<const char *>(sqlite3_column_blob(stmt.impl->stmt, offset)), + size_t(sqlite3_column_bytes(stmt.impl->stmt, offset)) }; } -template <> std::vector<uint8_t> Statement::get(int offset) { - assert(impl); - const auto* begin = reinterpret_cast<const uint8_t*>(sqlite3_column_blob(impl->stmt, offset)); - const uint8_t* end = begin + sqlite3_column_bytes(impl->stmt, offset); +template <> std::vector<uint8_t> Query::get(int offset) { + assert(stmt.impl); + const auto* begin = reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt.impl->stmt, offset)); + const uint8_t* end = begin + sqlite3_column_bytes(stmt.impl->stmt, offset); return { begin, end }; } template <> std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds> -Statement::get(int offset) { - assert(impl); +Query::get(int offset) { + assert(stmt.impl); return std::chrono::time_point_cast<std::chrono::seconds>( - std::chrono::system_clock::from_time_t(sqlite3_column_int64(impl->stmt, offset))); + std::chrono::system_clock::from_time_t(sqlite3_column_int64(stmt.impl->stmt, offset))); } -template <> optional<int64_t> Statement::get(int offset) { - assert(impl); - if (sqlite3_column_type(impl->stmt, offset) == SQLITE_NULL) { +template <> optional<int64_t> Query::get(int offset) { + assert(stmt.impl); + if (sqlite3_column_type(stmt.impl->stmt, offset) == SQLITE_NULL) { return optional<int64_t>(); } else { return get<int64_t>(offset); } } -template <> optional<double> Statement::get(int offset) { - assert(impl); - if (sqlite3_column_type(impl->stmt, offset) == SQLITE_NULL) { +template <> optional<double> Query::get(int offset) { + assert(stmt.impl); + if (sqlite3_column_type(stmt.impl->stmt, offset) == SQLITE_NULL) { return optional<double>(); } else { return get<double>(offset); } } -template <> optional<std::string> Statement::get(int offset) { - assert(impl); - if (sqlite3_column_type(impl->stmt, offset) == SQLITE_NULL) { +template <> optional<std::string> Query::get(int offset) { + assert(stmt.impl); + if (sqlite3_column_type(stmt.impl->stmt, offset) == SQLITE_NULL) { return optional<std::string>(); } else { return get<std::string>(offset); @@ -429,9 +437,9 @@ template <> optional<std::string> Statement::get(int offset) { template <> optional<std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>> -Statement::get(int offset) { - assert(impl); - if (sqlite3_column_type(impl->stmt, offset) == SQLITE_NULL) { +Query::get(int offset) { + assert(stmt.impl); + if (sqlite3_column_type(stmt.impl->stmt, offset) == SQLITE_NULL) { return {}; } else { return get<std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>>( @@ -439,24 +447,24 @@ Statement::get(int offset) { } } -void Statement::reset() { - assert(impl); - sqlite3_reset(impl->stmt); +void Query::reset() { + assert(stmt.impl); + sqlite3_reset(stmt.impl->stmt); } -void Statement::clearBindings() { - assert(impl); - sqlite3_clear_bindings(impl->stmt); +void Query::clearBindings() { + assert(stmt.impl); + sqlite3_clear_bindings(stmt.impl->stmt); } -int64_t Statement::lastInsertRowId() const { - assert(impl); - return impl->lastInsertRowId; +int64_t Query::lastInsertRowId() const { + assert(stmt.impl); + return stmt.impl->lastInsertRowId; } -uint64_t Statement::changes() const { - assert(impl); - auto changes_ = impl->changes; +uint64_t Query::changes() const { + assert(stmt.impl); + auto changes_ = stmt.impl->changes; return (changes_ < 0 ? 0 : changes_); } |