1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
// Copyright (c) 2020-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_SQLITE_H
#define BITCOIN_WALLET_SQLITE_H
#include <wallet/db.h>
#include <sqlite3.h>
struct bilingual_str;
namespace wallet {
class SQLiteDatabase;
class SQLiteCursor : public DatabaseCursor
{
public:
sqlite3_stmt* m_cursor_stmt{nullptr};
explicit SQLiteCursor() {}
~SQLiteCursor() override;
Status Next(DataStream& key, DataStream& value) override;
};
/** RAII class that provides access to a WalletDatabase */
class SQLiteBatch : public DatabaseBatch
{
private:
SQLiteDatabase& m_database;
sqlite3_stmt* m_read_stmt{nullptr};
sqlite3_stmt* m_insert_stmt{nullptr};
sqlite3_stmt* m_overwrite_stmt{nullptr};
sqlite3_stmt* m_delete_stmt{nullptr};
void SetupSQLStatements();
bool ReadKey(DataStream&& key, DataStream& value) override;
bool WriteKey(DataStream&& key, DataStream&& value, bool overwrite = true) override;
bool EraseKey(DataStream&& key) override;
bool HasKey(DataStream&& key) override;
public:
explicit SQLiteBatch(SQLiteDatabase& database);
~SQLiteBatch() override { Close(); }
/* No-op. See comment on SQLiteDatabase::Flush */
void Flush() override {}
void Close() override;
std::unique_ptr<DatabaseCursor> GetNewCursor() override;
bool TxnBegin() override;
bool TxnCommit() override;
bool TxnAbort() override;
};
/** An instance of this class represents one SQLite3 database.
**/
class SQLiteDatabase : public WalletDatabase
{
private:
const bool m_mock{false};
const std::string m_dir_path;
const std::string m_file_path;
void Cleanup() noexcept;
public:
SQLiteDatabase() = delete;
/** Create DB handle to real database */
SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock = false);
~SQLiteDatabase();
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; }
std::string Format() override { return "sqlite"; }
/** Make a SQLiteBatch connected to this database */
std::unique_ptr<DatabaseBatch> MakeBatch(bool flush_on_close = true) override;
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
|