/* * SQLiteConnection.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #include "StdInc.h" #include "SQLiteConnection.h" #include [[noreturn]] static void handleSQLiteError(sqlite3 * connection) { const char * message = sqlite3_errmsg(connection); throw std::runtime_error(std::string("SQLite error: ") + message); } static void checkSQLiteError(sqlite3 * connection, int result) { if(result != SQLITE_OK) handleSQLiteError(connection); } SQLiteStatement::SQLiteStatement(SQLiteInstance & instance, sqlite3_stmt * statement) : m_instance(instance) , m_statement(statement) { } SQLiteStatement::~SQLiteStatement() { sqlite3_finalize(m_statement); } bool SQLiteStatement::execute() { int result = sqlite3_step(m_statement); switch(result) { case SQLITE_DONE: return false; case SQLITE_ROW: return true; default: checkSQLiteError(m_instance.m_connection, result); return false; } } void SQLiteStatement::reset() { int result = sqlite3_reset(m_statement); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::clear() { int result = sqlite3_clear_bindings(m_statement); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const double & value) { int result = sqlite3_bind_double(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const bool & value) { int result = sqlite3_bind_int(m_statement, static_cast(value), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const uint8_t & value) { int result = sqlite3_bind_int(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const uint16_t & value) { int result = sqlite3_bind_int(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const uint32_t & value) { int result = sqlite3_bind_int(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const int32_t & value) { int result = sqlite3_bind_int(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const int64_t & value) { int result = sqlite3_bind_int64(m_statement, static_cast(index), value); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const std::string & value) { int result = sqlite3_bind_text(m_statement, static_cast(index), value.data(), static_cast(value.size()), SQLITE_STATIC); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::setBindSingle(size_t index, const char * value) { int result = sqlite3_bind_text(m_statement, static_cast(index), value, -1, SQLITE_STATIC); checkSQLiteError(m_instance.m_connection, result); } void SQLiteStatement::getColumnSingle(size_t index, double & value) { value = sqlite3_column_double(m_statement, static_cast(index)); } void SQLiteStatement::getColumnSingle(size_t index, bool & value) { value = sqlite3_column_int(m_statement, static_cast(index)) != 0; } void SQLiteStatement::getColumnSingle(size_t index, uint8_t & value) { value = static_cast(sqlite3_column_int(m_statement, static_cast(index))); } void SQLiteStatement::getColumnSingle(size_t index, uint16_t & value) { value = static_cast(sqlite3_column_int(m_statement, static_cast(index))); } void SQLiteStatement::getColumnSingle(size_t index, int32_t & value) { value = sqlite3_column_int(m_statement, static_cast(index)); } void SQLiteStatement::getColumnSingle(size_t index, uint32_t & value) { value = sqlite3_column_int(m_statement, static_cast(index)); } void SQLiteStatement::getColumnSingle(size_t index, int64_t & value) { value = sqlite3_column_int64(m_statement, static_cast(index)); } void SQLiteStatement::getColumnSingle(size_t index, std::string & value) { const auto * value_raw = sqlite3_column_text(m_statement, static_cast(index)); value = reinterpret_cast(value_raw); } SQLiteInstancePtr SQLiteInstance::open(const boost::filesystem::path & db_path, bool allow_write) { int flags = allow_write ? (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE) : SQLITE_OPEN_READONLY; sqlite3 * connection; int result = sqlite3_open_v2(db_path.c_str(), &connection, flags, nullptr); if(result == SQLITE_OK) return SQLiteInstancePtr(new SQLiteInstance(connection)); sqlite3_close(connection); handleSQLiteError(connection); } SQLiteInstance::SQLiteInstance(sqlite3 * connection) : m_connection(connection) { } SQLiteInstance::~SQLiteInstance() { sqlite3_close(m_connection); } SQLiteStatementPtr SQLiteInstance::prepare(const std::string & sql_text) { sqlite3_stmt * statement; int result = sqlite3_prepare_v2(m_connection, sql_text.data(), static_cast(sql_text.size()), &statement, nullptr); if(result == SQLITE_OK) return SQLiteStatementPtr(new SQLiteStatement(*this, statement)); sqlite3_finalize(statement); handleSQLiteError(m_connection); }