LCOV - code coverage report
Current view: top level - src/wallet - sqlite.h (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 0.0 % 11 0
Test Date: 2025-06-01 05:27:21 Functions: 0.0 % 8 0

            Line data    Source code
       1              : // Copyright (c) 2020-present The Bitcoin Core developers
       2              : // Distributed under the MIT software license, see the accompanying
       3              : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4              : 
       5              : #ifndef BITCOIN_WALLET_SQLITE_H
       6              : #define BITCOIN_WALLET_SQLITE_H
       7              : 
       8              : #include <sync.h>
       9              : #include <wallet/db.h>
      10              : 
      11              : #include <semaphore>
      12              : 
      13              : struct bilingual_str;
      14              : 
      15              : struct sqlite3_stmt;
      16              : struct sqlite3;
      17              : 
      18              : namespace wallet {
      19              : class SQLiteDatabase;
      20              : 
      21              : /** RAII class that provides a database cursor */
      22              : class SQLiteCursor : public DatabaseCursor
      23              : {
      24              : public:
      25              :     sqlite3_stmt* m_cursor_stmt{nullptr};
      26              :     // Copies of the prefix things for the prefix cursor.
      27              :     // Prevents SQLite from accessing temp variables for the prefix things.
      28              :     std::vector<std::byte> m_prefix_range_start;
      29              :     std::vector<std::byte> m_prefix_range_end;
      30              : 
      31            0 :     explicit SQLiteCursor() = default;
      32            0 :     explicit SQLiteCursor(std::vector<std::byte> start_range, std::vector<std::byte> end_range)
      33            0 :         : m_prefix_range_start(std::move(start_range)),
      34            0 :         m_prefix_range_end(std::move(end_range))
      35            0 :     {}
      36              :     ~SQLiteCursor() override;
      37              : 
      38              :     Status Next(DataStream& key, DataStream& value) override;
      39              : };
      40              : 
      41              : /** Class responsible for executing SQL statements in SQLite databases.
      42              :  *  Methods are virtual so they can be overridden by unit tests testing unusual database conditions. */
      43            0 : class SQliteExecHandler
      44              : {
      45              : public:
      46            0 :     virtual ~SQliteExecHandler() = default;
      47              :     virtual int Exec(SQLiteDatabase& database, const std::string& statement);
      48              : };
      49              : 
      50              : /** RAII class that provides access to a WalletDatabase */
      51              : class SQLiteBatch : public DatabaseBatch
      52              : {
      53              : private:
      54              :     SQLiteDatabase& m_database;
      55              :     std::unique_ptr<SQliteExecHandler> m_exec_handler{std::make_unique<SQliteExecHandler>()};
      56              : 
      57              :     sqlite3_stmt* m_read_stmt{nullptr};
      58              :     sqlite3_stmt* m_insert_stmt{nullptr};
      59              :     sqlite3_stmt* m_overwrite_stmt{nullptr};
      60              :     sqlite3_stmt* m_delete_stmt{nullptr};
      61              :     sqlite3_stmt* m_delete_prefix_stmt{nullptr};
      62              : 
      63              :     /** Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_semaphore.
      64              :      * If the batch starts a db tx, it acquires the semaphore and sets this to true, keeping the semaphore
      65              :      * until the transaction ends to prevent other batch objects from writing to the database.
      66              :      *
      67              :      * If this batch did not start a transaction, the semaphore is acquired transiently when writing and m_txn
      68              :      * is not set.
      69              :      *
      70              :      * m_txn is different from HasActiveTxn() as it is only true when this batch has started the transaction,
      71              :      * not just when any batch has started a transaction.
      72              :      */
      73              :     bool m_txn{false};
      74              : 
      75              :     void SetupSQLStatements();
      76              :     bool ExecStatement(sqlite3_stmt* stmt, std::span<const std::byte> blob);
      77              : 
      78              :     bool ReadKey(DataStream&& key, DataStream& value) override;
      79              :     bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
      80              :     bool EraseKey(DataStream&& key) override;
      81              :     bool HasKey(DataStream&& key) override;
      82              :     bool ErasePrefix(std::span<const std::byte> prefix) override;
      83              : 
      84              : public:
      85              :     explicit SQLiteBatch(SQLiteDatabase& database);
      86            0 :     ~SQLiteBatch() override { Close(); }
      87              : 
      88              :     void SetExecHandler(std::unique_ptr<SQliteExecHandler>&& handler) { m_exec_handler = std::move(handler); }
      89              : 
      90              :     void Close() override;
      91              : 
      92              :     std::unique_ptr<DatabaseCursor> GetNewCursor() override;
      93              :     std::unique_ptr<DatabaseCursor> GetNewPrefixCursor(std::span<const std::byte> prefix) override;
      94              :     bool TxnBegin() override;
      95              :     bool TxnCommit() override;
      96              :     bool TxnAbort() override;
      97            0 :     bool HasActiveTxn() override { return m_txn; }
      98              : };
      99              : 
     100              : /** An instance of this class represents one SQLite3 database.
     101              :  **/
     102              : class SQLiteDatabase : public WalletDatabase
     103              : {
     104              : private:
     105              :     const bool m_mock{false};
     106              : 
     107              :     const std::string m_dir_path;
     108              : 
     109              :     const std::string m_file_path;
     110              : 
     111              :     /**
     112              :      * This mutex protects SQLite initialization and shutdown.
     113              :      * sqlite3_config() and sqlite3_shutdown() are not thread-safe (sqlite3_initialize() is).
     114              :      * Concurrent threads that execute SQLiteDatabase::SQLiteDatabase() should have just one
     115              :      * of them do the init and the rest wait for it to complete before all can proceed.
     116              :      */
     117              :     static Mutex g_sqlite_mutex;
     118              :     static int g_sqlite_count GUARDED_BY(g_sqlite_mutex);
     119              : 
     120              :     void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex);
     121              : 
     122              : public:
     123              :     SQLiteDatabase() = delete;
     124              : 
     125              :     /** Create DB handle to real database */
     126              :     SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false);
     127              : 
     128              :     ~SQLiteDatabase();
     129              : 
     130              :     // Batches must acquire this semaphore on writing, and release when done writing.
     131              :     // This ensures that only one batch is modifying the database at a time.
     132              :     std::binary_semaphore m_write_semaphore;
     133              : 
     134              :     bool Verify(bilingual_str& error);
     135              : 
     136              :     /** Open the database if it is not already opened */
     137              :     void Open() override;
     138              : 
     139              :     /** Close the database */
     140              :     void Close() override;
     141              : 
     142              :     /** Rewrite the entire database on disk */
     143              :     bool Rewrite(const char* skip = nullptr) override;
     144              : 
     145              :     /** Back up the entire database to a file.
     146              :      */
     147              :     bool Backup(const std::string& dest) const override;
     148              : 
     149            0 :     std::string Filename() override { return m_file_path; }
     150            0 :     std::string Format() override { return "sqlite"; }
     151              : 
     152              :     /** Make a SQLiteBatch connected to this database */
     153              :     std::unique_ptr<DatabaseBatch> MakeBatch() override;
     154              : 
     155              :     /** Return true if there is an on-going txn in this connection */
     156              :     bool HasActiveTxn();
     157              : 
     158              :     sqlite3* m_db{nullptr};
     159              :     bool m_use_unsafe_sync;
     160              : };
     161              : 
     162              : std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
     163              : 
     164              : std::string SQLiteDatabaseVersion();
     165              : } // namespace wallet
     166              : 
     167              : #endif // BITCOIN_WALLET_SQLITE_H
        

Generated by: LCOV version 2.0-1