Repository: bitcoin/bitcoin
File: src/wallet/sqlite.h (C/C++)

Code before:

    /** Create DB handle to real database */
    SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false);

    ~SQLiteDatabase();

    // Batches must acquire this semaphore on writing, and release when done writing.
    // This ensures that only one batch is modifying the database at a time.
    CSemaphore m_write_semaphore;

    bool Verify(bilingual_str& error);

    /** Open the database if it is not already opened */
    void Open() override;

    /** Close the database */
    void Close() override;

    /* These functions are unused */
    void AddRef() override { assert(false); }
    void RemoveRef() override { assert(false); }

    /** Rewrite the entire database on disk */
    bool Rewrite(const char* skip = nullptr) override;

    /** Back up the entire database to a file.
     */
    bool Backup(const std::string& dest) const override;

    /** No-ops
     *
     * SQLite always flushes everything to the database file after each transaction
     * (each Read/Write/Erase that we do is its own transaction unless we called
     * TxnBegin) so there is no need to have Flush or Periodic Flush.
     *
     * There is no DB env to reload, so ReloadDbEnv has nothing to do
     */
    void Flush() override {}
    bool PeriodicFlush() override { return false; }
    void ReloadDbEnv() override {}

    void IncrementUpdateCounter() override { ++nUpdateCounter; }

    std::string Filename() override { return m_file_path; }
    /** Return paths to all database created files */
    std::vector<fs::path> Files() override
    {
        std::vector<fs::path> files;
        files.emplace_back(m_dir_path / fs::PathFromString(m_file_path));
        files.emplace_back(m_dir_path / fs::PathFromString(m_file_path + "-journal"));
        return files;

Review comment (bug):
Should probably be skipped for `BerkeleyDatabase`, but should have a test for `Files()`, e.g.:

<details>

<summary>

#### Maybe something like https://github.com/davidgumberg/bitcoin/commit/db9449b547b07c59f73e3ae0a74eb808325bac48
 
 </summary>

```cpp
#ifdef USE_SQLITE
BOOST_AUTO_TEST_CASE(sqlite_db_files)
{
    DatabaseOptions options;
    DatabaseStatus status;
    bilingual_str error;
    std::unique_ptr<SQLiteDatabase> sqldb = MakeSQLiteDatabase(m_path_root / "sqlite", options, status, error);

    auto sqlite_internal_filename(sqlite3_db_filename(sqldb->m_db, "main"));
    BOOST_CHECK(sqlite_internal_filename != nullptr);

    std::vector<fs::path> sql_paths;
    sql_paths.push_back(fs::PathFromString(sqlite3_filename_database(sqlite_internal_filename)));
    sql_paths.push_back(fs::PathFromString(sqlite3_filename_journal(sqlite_internal_filename)));
    BOOST_TEST(sql_paths == sqldb->Files(), boost::test_tools::per_element());
}
#endif
```

</details>

---

Edit: This test is actually [failing on macOS](https://github.com/davidgumberg/bitcoin/actions/runs/14368257249/job/40286109583#step:7:2487), where sqlite's filepath differs from this, I haven't yet figured out if my test is wrong.

```console
wallet/test/db_tests.cpp:163: error: in "db_tests/sqlite_db_files": check sql_paths == sqldb->Files() has failed
  - mismatch at position 0: ["/private/var/folders/qn/7t0vq3ts721cmgt0tgrtgzl80000gn/T/test_common bitcoin/db_tests/sqlite_db_files/4401d34f82818d7bcb73/sqlite/wallet.dat" == "/var/folders/qn/7t0vq3ts721cmgt0tgrtgzl80000gn/T/test_common bitcoin/db_tests/sqlite_db_files/4401d34f82818d7bcb73/sqlite/wallet.dat"] is false
  - mismatch at position 1: ["/private/var/folders/qn/7t0vq3ts721cmgt0tgrtgzl80000gn/T/test_common bitcoin/db_tests/sqlite_db_files/4401d34f82818d7bcb73/sqlite/wallet.dat-journal" == "/var/folders/qn/7t0vq3ts721cmgt0tgrtgzl80000gn/T/test_common bitcoin/db_tests/sqlite_db_files/4401d34f82818d7bcb73/sqlite/wallet.dat-journal"] is false
```

Code after:
    /** Create DB handle to real database */
    SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false);

    ~SQLiteDatabase();

    // Batches must acquire this semaphore on writing, and release when done writing.
    // This ensures that only one batch is modifying the database at a time.
    std::binary_semaphore m_write_semaphore;

    bool Verify(bilingual_str& error);

    /** Open the database if it is not already opened */
    void Open() override;

    /** Close the database */
    void Close() override;

    /** Rewrite the entire database on disk */
    bool Rewrite(const char* skip = nullptr) override;

    /** Back up the entire database to a file.
     */
    bool Backup(const std::string& dest) const override;

    std::string Filename() override { return m_file_path; }
    /** Return paths to all database created files */
    std::vector<fs::path> Files() override
    {
        std::vector<fs::path> files;
        files.emplace_back(m_dir_path / fs::PathFromString(m_file_path));
        files.emplace_back(m_dir_path / fs::PathFromString(m_file_path + "-journal"));
        return files;
    }
    std::string Format() override { return "sqlite"; }

    /** Make a SQLiteBatch connected to this database */
    std::unique_ptr<DatabaseBatch> MakeBatch() override;

    /** Return true if there is an on-going txn in this connection */
    bool HasActiveTxn();

    sqlite3* m_db{nullptr};
    bool m_use_unsafe_sync;
};

std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);

std::string SQLiteDatabaseVersion();
} // namespace wallet

#endif // BITCOIN_WALLET_SQLITE_H