1 // Copyright (c) 2020 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 <wallet/db.h>
9 
10 #include <sqlite3.h>
11 
12 struct bilingual_str;
13 class SQLiteDatabase;
14 
15 /** RAII class that provides access to a WalletDatabase */
16 class SQLiteBatch : public DatabaseBatch
17 {
18 private:
19     SQLiteDatabase& m_database;
20 
21     bool m_cursor_init = false;
22 
23     sqlite3_stmt* m_read_stmt{nullptr};
24     sqlite3_stmt* m_insert_stmt{nullptr};
25     sqlite3_stmt* m_overwrite_stmt{nullptr};
26     sqlite3_stmt* m_delete_stmt{nullptr};
27     sqlite3_stmt* m_cursor_stmt{nullptr};
28 
29     void SetupSQLStatements();
30 
31     bool ReadKey(CDataStream&& key, CDataStream& value) override;
32     bool WriteKey(CDataStream&& key, CDataStream&& value, bool overwrite = true) override;
33     bool EraseKey(CDataStream&& key) override;
34     bool HasKey(CDataStream&& key) override;
35 
36 public:
37     explicit SQLiteBatch(SQLiteDatabase& database);
~SQLiteBatch()38     ~SQLiteBatch() override { Close(); }
39 
40     /* No-op. See comment on SQLiteDatabase::Flush */
Flush()41     void Flush() override {}
42 
43     void Close() override;
44 
45     bool StartCursor() override;
46     bool ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete) override;
47     void CloseCursor() override;
48     bool TxnBegin() override;
49     bool TxnCommit() override;
50     bool TxnAbort() override;
51 };
52 
53 /** An instance of this class represents one SQLite3 database.
54  **/
55 class SQLiteDatabase : public WalletDatabase
56 {
57 private:
58     const bool m_mock{false};
59 
60     const std::string m_dir_path;
61 
62     const std::string m_file_path;
63 
64     void Cleanup() noexcept;
65 
66 public:
67     SQLiteDatabase() = delete;
68 
69     /** Create DB handle to real database */
70     SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, bool mock = false);
71 
72     ~SQLiteDatabase();
73 
74     bool Verify(bilingual_str& error);
75 
76     /** Open the database if it is not already opened */
77     void Open() override;
78 
79     /** Close the database */
80     void Close() override;
81 
82     /* These functions are unused */
AddRef()83     void AddRef() override { assert(false); }
RemoveRef()84     void RemoveRef() override { assert(false); }
85 
86     /** Rewrite the entire database on disk */
87     bool Rewrite(const char* skip = nullptr) override;
88 
89     /** Back up the entire database to a file.
90      */
91     bool Backup(const std::string& dest) const override;
92 
93     /** No-ops
94      *
95      * SQLite always flushes everything to the database file after each transaction
96      * (each Read/Write/Erase that we do is its own transaction unless we called
97      * TxnBegin) so there is no need to have Flush or Periodic Flush.
98      *
99      * There is no DB env to reload, so ReloadDbEnv has nothing to do
100      */
Flush()101     void Flush() override {}
PeriodicFlush()102     bool PeriodicFlush() override { return false; }
ReloadDbEnv()103     void ReloadDbEnv() override {}
104 
IncrementUpdateCounter()105     void IncrementUpdateCounter() override { ++nUpdateCounter; }
106 
Filename()107     std::string Filename() override { return m_file_path; }
Format()108     std::string Format() override { return "sqlite"; }
109 
110     /** Make a SQLiteBatch connected to this database */
111     std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
112 
113     sqlite3* m_db{nullptr};
114 };
115 
116 std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);
117 
118 std::string SQLiteDatabaseVersion();
119 
120 #endif // BITCOIN_WALLET_SQLITE_H
121