/* * libfud * Copyright 2024 Dominick Allen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FUD_SQLITE_HPP #define FUD_SQLITE_HPP #include #include #include #include #include namespace fud { class SqliteStatement; // NOLINTNEXTLINE(performance-enum-size) enum class SqliteOpenMode : int { ReadOnly = SQLITE_OPEN_READONLY, ReadWrite = SQLITE_OPEN_READWRITE, ReadWriteCreate = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE }; class SqliteErrorMsg; class SqliteDb; using SqliteDbResult = Result; class SqliteDb { private: constexpr SqliteDb() = default; public: static SqliteDbResult make(const String& name, SqliteOpenMode mode, int extraFlags = 0); static SqliteDbResult make(StringView name, SqliteOpenMode mode, int extraFlags = 0); static SqliteDbResult make(const char* cStrName, SqliteOpenMode mode, int extraFlags = 0); SqliteDb(const SqliteDb&) = delete; SqliteDb(SqliteDb&& rhs) noexcept; ~SqliteDb(); SqliteDb& operator=(const SqliteDb&) = delete; SqliteDb& operator=(SqliteDb&& rhs) noexcept; [[nodiscard]] bool valid() const; bool revalidate(); FudStatus exec( const String& statement, int (*callback)(void*, int, char**, char**), void* context, std::unique_ptr errorMessage); [[nodiscard]] constexpr int errorCode() const { return m_errorCode; } [[nodiscard]] constexpr sqlite3* handle() const { return m_dbHandle; } private: static SqliteDbResult finishMake(SqliteOpenMode& mode, int& extraFlags, SqliteDb&& sqlDb); // private methods FudStatus initialize(); [[nodiscard]] int open(); Result prepare(const String& sql); // private data members String m_name{}; bool m_nameValid{false}; sqlite3* m_dbHandle{nullptr}; int m_errorCode{0}; SqliteOpenMode m_mode{}; int m_extraFlags{}; }; class SqliteStatement { public: SqliteStatement(const SqliteDb& sqliteDb, const String& input); SqliteStatement(const SqliteStatement&) = delete; SqliteStatement(SqliteStatement&& rhs) noexcept; ~SqliteStatement(); SqliteStatement& operator=(const SqliteStatement&) = delete; SqliteStatement& operator=(SqliteStatement&& rhs) noexcept = delete; [[nodiscard]] bool valid() const; sqlite3_stmt* statement(); int step(); FudStatus reset(); [[nodiscard]] constexpr int errorCode() const { return m_errorCode; } constexpr FudStatus status() { return m_status; } private: String m_input{}; const char* m_tail{nullptr}; FudStatus m_status{FudStatus::ObjectInvalid}; int m_errorCode{0}; sqlite3_stmt* m_preparedStatement{nullptr}; }; class SqliteErrorMsg { public: constexpr SqliteErrorMsg() = default; explicit constexpr SqliteErrorMsg(char* errorMsg) : m_errorMsg{errorMsg} { } SqliteErrorMsg(const SqliteErrorMsg&) = delete; SqliteErrorMsg(SqliteErrorMsg&& rhs) noexcept; ~SqliteErrorMsg(); SqliteErrorMsg& operator=(const SqliteErrorMsg&) = delete; SqliteErrorMsg& operator=(SqliteErrorMsg&& rhs) noexcept; private: char* m_errorMsg{nullptr}; }; } // namespace fud #endif