diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2025-03-30 23:08:43 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2025-03-30 23:08:43 -0500 |
commit | cb9fa588ba8144fcdd52ba4b83d69d93fb18066f (patch) | |
tree | 214574ca68c1551ec76e7fbb9e0263793180231d /source/fud_sqlite.cpp | |
parent | 1d357adfa19725ee69fb267a363f1fd217b1272f (diff) |
Add hash map.
Diffstat (limited to 'source/fud_sqlite.cpp')
-rw-r--r-- | source/fud_sqlite.cpp | 175 |
1 files changed, 139 insertions, 36 deletions
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<int>(m_mode) | m_extraFlags, nullptr); +} + FudStatus SqliteDb::exec( const String& statement, int (*callback)(void*, int, char**, char**), void* context, - std::unique_ptr<SqliteErrorMsg> errorMessage) + // NOLINTNEXTLINE(performance-copy-param-value) + Option<SqliteErrorMsg&>& 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<SqliteErrorMsg>(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<int32_t, FudStatus> 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<int64_t, FudStatus> SqliteDb::columnInt64(SqliteStatement& statement, int index) { - // use default vfs - return sqlite3_open_v2(m_name.c_str(), &m_dbHandle, static_cast<int>(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<decltype(output), int64_t>); + + return Okay{static_cast<int64_t>(output)}; +} + +Result<double, FudStatus> 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<StringView, FudStatus> 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<size_t>(outputLength); + + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + output.m_data = reinterpret_cast<const utf8*>(sqlite3_column_text(statement.statement(), index)); + if (output.m_data == nullptr && output.m_length != 0) { + return Error{FudStatus::Failure}; + } + + return Okay{output}; } Result<SqliteStatement, FudStatus> SqliteDb::prepare(const String& sql) { - using RetType = Result<SqliteStatement, FudStatus>; 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 |