From cb9fa588ba8144fcdd52ba4b83d69d93fb18066f Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Sun, 30 Mar 2025 23:08:43 -0500 Subject: Add hash map. --- source/fud_sqlite.cpp | 175 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 139 insertions(+), 36 deletions(-) (limited to 'source/fud_sqlite.cpp') diff --git a/source/fud_sqlite.cpp b/source/fud_sqlite.cpp index 4a7187f..fccbc1e 100644 --- a/source/fud_sqlite.cpp +++ b/source/fud_sqlite.cpp @@ -37,7 +37,7 @@ SqliteDbResult SqliteDb::make(StringView name, SqliteOpenMode mode, int extraFla return SqliteDbResult::error(nameResult.takeError()); } sqlDb.m_name = nameResult.takeOkay(); - return finishMake(mode, extraFlags, std::move(sqlDb)); + return finishMake(mode, extraFlags, std::move(sqlDb)); } SqliteDbResult SqliteDb::make(const char* cStrName, SqliteOpenMode mode, int extraFlags) @@ -48,7 +48,7 @@ SqliteDbResult SqliteDb::make(const char* cStrName, SqliteOpenMode mode, int ext return SqliteDbResult::error(nameResult); } sqlDb.m_name = nameResult.takeOkay(); - return finishMake(mode, extraFlags, std::move(sqlDb)); + return finishMake(mode, extraFlags, std::move(sqlDb)); } SqliteDbResult SqliteDb::finishMake(SqliteOpenMode& mode, int& extraFlags, SqliteDb&& sqlDb) @@ -104,7 +104,7 @@ SqliteDb& SqliteDb::operator=(SqliteDb&& rhs) noexcept bool SqliteDb::valid() const { - return m_nameValid && m_dbHandle != nullptr && m_errorCode == SQLITE_OK; + return m_nameValid && m_dbHandle != nullptr && (m_errorCode == SQLITE_OK || m_errorCode == SQLITE_DONE); } bool SqliteDb::revalidate() @@ -116,11 +116,34 @@ bool SqliteDb::revalidate() return false; } +FudStatus SqliteDb::initialize() +{ + m_nameValid = m_name.utf8Valid(); + + if (!m_nameValid) { + return FudStatus::ArgumentInvalid; + } + + m_errorCode = open(); + if (m_errorCode != SQLITE_OK) { + return FudStatus::Failure; + } + + return FudStatus::Success; +} + +int SqliteDb::open() +{ + // use default vfs + return sqlite3_open_v2(m_name.c_str(), &m_dbHandle, static_cast(m_mode) | m_extraFlags, nullptr); +} + FudStatus SqliteDb::exec( const String& statement, int (*callback)(void*, int, char**, char**), void* context, - std::unique_ptr errorMessage) + // NOLINTNEXTLINE(performance-copy-param-value) + Option& errorMessage) { if (!valid()) { return FudStatus::ObjectInvalid; @@ -131,53 +154,135 @@ FudStatus SqliteDb::exec( } char* errorMsgPtr = nullptr; - char** errorMsgPtrAddress = nullptr; - if (errorMessage != nullptr) { - errorMsgPtrAddress = &errorMsgPtr; - } + char** errorMsgPtrAddress = errorMessage.isNone() ? nullptr : &errorMsgPtr; m_errorCode = sqlite3_exec(m_dbHandle, statement.c_str(), callback, context, errorMsgPtrAddress); - if (errorMessage != nullptr) { - errorMessage = std::make_unique(errorMsgPtr); + if (errorMessage.hasValue()) { + errorMessage.value().setMessage(errorMsgPtr); } return m_errorCode == SQLITE_OK ? FudStatus::Success : FudStatus::Failure; } -FudStatus SqliteDb::initialize() +FudStatus SqliteDb::step(SqliteStatement& statement) { - m_nameValid = m_name.utf8Valid(); - - if (!m_nameValid) { - return FudStatus::ArgumentInvalid; + if (!statement.valid()) { + m_errorCode = SQLITE_MISUSE; + } else { + m_errorCode = sqlite3_step(statement.statement()); } - m_errorCode = open(); - if (m_errorCode != SQLITE_OK) { + switch (m_errorCode) { + case SQLITE_OK: + case SQLITE_ROW: + return FudStatus::Success; + case SQLITE_DONE: + return FudStatus::NotFound; + default: return FudStatus::Failure; } +} - return FudStatus::Success; +Result SqliteDb::columnInt32(SqliteStatement& statement, int index) +{ + if (!statement.valid() || statement.status() != FudStatus::Success) { + m_errorCode = statement.errorCode(); + return Error{statement.status()}; + } + + if (index < 0) { + return Error{FudStatus::ArgumentInvalid}; + } + if (sqlite3_column_type(statement.statement(), index) != SQLITE_INTEGER) { + return Error{FudStatus::ArgumentInvalid}; + } + + auto output = sqlite3_column_int(statement.statement(), index); + + return Okay{output}; } -int SqliteDb::open() +Result SqliteDb::columnInt64(SqliteStatement& statement, int index) { - // use default vfs - return sqlite3_open_v2(m_name.c_str(), &m_dbHandle, static_cast(m_mode) | m_extraFlags, nullptr); + if (!statement.valid() || statement.status() != FudStatus::Success) { + m_errorCode = statement.errorCode(); + return Error{statement.status()}; + } + + if (index < 0) { + return Error{FudStatus::ArgumentInvalid}; + } + if (sqlite3_column_type(statement.statement(), index) != SQLITE_INTEGER) { + return Error{FudStatus::ArgumentInvalid}; + } + + auto output = sqlite3_column_int64(statement.statement(), index); + static_assert(std::is_convertible_v); + + return Okay{static_cast(output)}; +} + +Result SqliteDb::columnDouble(SqliteStatement& statement, int index) +{ + if (!statement.valid() || statement.status() != FudStatus::Success) { + m_errorCode = statement.errorCode(); + return Error{statement.status()}; + } + + if (index < 0) { + return Error{FudStatus::ArgumentInvalid}; + } + if (sqlite3_column_type(statement.statement(), index) != SQLITE_FLOAT) { + return Error{FudStatus::ArgumentInvalid}; + } + + auto output = sqlite3_column_double(statement.statement(), index); + + return Okay{output}; +} + +Result SqliteDb::columnText(SqliteStatement& statement, int index) +{ + if (!statement.valid() || statement.status() != FudStatus::Success) { + m_errorCode = statement.errorCode(); + return Error{statement.status()}; + } + + if (index < 0) { + return Error{FudStatus::ArgumentInvalid}; + } + + StringView output{}; + if (sqlite3_column_type(statement.statement(), index) != SQLITE_TEXT) { + return Error{FudStatus::ArgumentInvalid}; + } + + auto outputLength = sqlite3_column_bytes(statement.statement(), index); + if (outputLength < 0) { + return Error{FudStatus::Failure}; + } + output.m_length = static_cast(outputLength); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + output.m_data = reinterpret_cast(sqlite3_column_text(statement.statement(), index)); + if (output.m_data == nullptr && output.m_length != 0) { + return Error{FudStatus::Failure}; + } + + return Okay{output}; } Result SqliteDb::prepare(const String& sql) { - using RetType = Result; SqliteStatement preparedStatement{*this, sql}; if (!preparedStatement.valid() || preparedStatement.status() != FudStatus::Success) { m_errorCode = preparedStatement.errorCode(); - return RetType::error(preparedStatement.status()); + return Error{preparedStatement.status()}; } - return RetType::okay(std::move(preparedStatement)); + return Okay{std::move(preparedStatement)}; } SqliteStatement::SqliteStatement(const SqliteDb& sqliteDb, const String& input) @@ -200,7 +305,6 @@ SqliteStatement::SqliteStatement(const SqliteDb& sqliteDb, const String& input) } SqliteStatement::SqliteStatement(SqliteStatement&& rhs) noexcept : - m_input{std::move(rhs.m_input)}, m_tail{rhs.m_tail}, m_status{rhs.m_status}, m_errorCode{rhs.m_errorCode}, @@ -229,16 +333,6 @@ sqlite3_stmt* SqliteStatement::statement() return m_preparedStatement; } -int SqliteStatement::step() -{ - if (!valid()) { - m_errorCode = SQLITE_MISUSE; - } else { - m_errorCode = sqlite3_step(m_preparedStatement); - } - return m_errorCode; -} - FudStatus SqliteStatement::reset() { if (!valid()) { @@ -256,7 +350,8 @@ SqliteErrorMsg::SqliteErrorMsg(SqliteErrorMsg&& rhs) noexcept : m_errorMsg{rhs.m rhs.m_errorMsg = nullptr; } -SqliteErrorMsg& SqliteErrorMsg::operator=(SqliteErrorMsg&& rhs) noexcept { +SqliteErrorMsg& SqliteErrorMsg::operator=(SqliteErrorMsg&& rhs) noexcept +{ if (m_errorMsg != nullptr) { sqlite3_free(m_errorMsg); m_errorMsg = nullptr; @@ -275,4 +370,12 @@ SqliteErrorMsg::~SqliteErrorMsg() } } +void SqliteErrorMsg::setMessage(char* newMessage) +{ + if (m_errorMsg != nullptr) { + sqlite3_free(m_errorMsg); + } + m_errorMsg = newMessage; +} + } // namespace fud -- cgit v1.2.3