summaryrefslogtreecommitdiff
path: root/source/fud_sqlite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/fud_sqlite.cpp')
-rw-r--r--source/fud_sqlite.cpp175
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