5#include <bitcoin-build-config.h>
9#include <chainparams.h>
29static std::span<const std::byte>
SpanFromBlob(sqlite3_stmt* stmt,
int col)
31 return {
reinterpret_cast<const std::byte*
>(sqlite3_column_blob(stmt, col)),
32 static_cast<size_t>(sqlite3_column_bytes(stmt, col))};
43 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code,
msg);
49 if (code == SQLITE_TRACE_STMT) {
50 auto* stmt =
static_cast<sqlite3_stmt*
>(param1);
54 char* expanded{sqlite3_stmt_readonly(stmt) ? sqlite3_expanded_sql(stmt) :
nullptr};
55 LogTrace(
BCLog::WALLETDB,
"[%s] SQLite Statement: %s\n", db->Filename(), expanded ? expanded : sqlite3_sql(stmt));
56 if (expanded) sqlite3_free(expanded);
63 std::span<const std::byte> blob,
64 const std::string& description)
70 int res = sqlite3_bind_blob(stmt, index, blob.data() ?
static_cast<const void*
>(blob.data()) :
"", blob.size(), SQLITE_STATIC);
71 if (res != SQLITE_OK) {
72 LogPrintf(
"Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
73 sqlite3_clear_bindings(stmt);
83 std::string stmt_text =
strprintf(
"PRAGMA %s", key);
84 sqlite3_stmt* pragma_read_stmt{
nullptr};
85 int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt,
nullptr);
86 if (
ret != SQLITE_OK) {
87 sqlite3_finalize(pragma_read_stmt);
88 error =
Untranslated(
strprintf(
"SQLiteDatabase: Failed to prepare the statement to fetch %s: %s", description, sqlite3_errstr(
ret)));
91 ret = sqlite3_step(pragma_read_stmt);
92 if (
ret != SQLITE_ROW) {
93 sqlite3_finalize(pragma_read_stmt);
97 int result = sqlite3_column_int(pragma_read_stmt, 0);
98 sqlite3_finalize(pragma_read_stmt);
102static void SetPragma(sqlite3* db,
const std::string& key,
const std::string& value,
const std::string& err_msg)
104 std::string stmt_text =
strprintf(
"PRAGMA %s = %s", key, value);
105 int ret = sqlite3_exec(db, stmt_text.c_str(),
nullptr,
nullptr,
nullptr);
106 if (
ret != SQLITE_OK) {
107 throw std::runtime_error(
strprintf(
"SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(
ret)));
112int SQLiteDatabase::g_sqlite_count = 0;
115 :
WalletDatabase(), m_mock(mock), m_dir_path(dir_path), m_file_path(fs::PathToString(file_path)), m_write_semaphore(1), m_use_unsafe_sync(options.use_unsafe_sync)
119 if (++g_sqlite_count == 1) {
122 if (
ret != SQLITE_OK) {
123 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(
ret)));
126 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
127 if (
ret != SQLITE_OK) {
128 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(
ret)));
131 int ret = sqlite3_initialize();
132 if (
ret != SQLITE_OK) {
133 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(
ret)));
139 }
catch (
const std::runtime_error&) {
148 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
149 {&
m_read_stmt,
"SELECT value FROM main WHERE key = ?"},
156 for (
const auto& [stmt_prepared, stmt_text] : statements) {
157 if (*stmt_prepared ==
nullptr) {
158 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, stmt_prepared,
nullptr);
159 if (res != SQLITE_OK) {
161 "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
179 if (--g_sqlite_count == 0) {
180 int ret = sqlite3_shutdown();
181 if (
ret != SQLITE_OK) {
182 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(
ret));
193 if (!read_result.has_value())
return false;
194 uint32_t app_id =
static_cast<uint32_t
>(read_result.value());
196 if (app_id != net_magic) {
197 error =
strprintf(
_(
"SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
203 if (!read_result.has_value())
return false;
204 int32_t user_ver = read_result.value();
210 sqlite3_stmt* stmt{
nullptr};
211 int ret = sqlite3_prepare_v2(
m_db,
"PRAGMA integrity_check", -1, &stmt,
nullptr);
212 if (
ret != SQLITE_OK) {
213 sqlite3_finalize(stmt);
214 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(
ret));
218 ret = sqlite3_step(stmt);
219 if (
ret == SQLITE_DONE) {
222 if (
ret != SQLITE_ROW) {
223 error =
strprintf(
_(
"SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(
ret));
226 const char*
msg = (
const char*)sqlite3_column_text(stmt, 0);
228 error =
strprintf(
_(
"SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(
ret));
231 std::string str_msg(
msg);
232 if (str_msg ==
"ok") {
240 sqlite3_finalize(stmt);
241 return error.
empty();
246 int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
248 flags |= SQLITE_OPEN_MEMORY;
251 if (
m_db ==
nullptr) {
256 if (
ret != SQLITE_OK) {
257 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(
ret)));
259 ret = sqlite3_extended_result_codes(
m_db, 1);
260 if (
ret != SQLITE_OK) {
261 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(
ret)));
266 if (
ret != SQLITE_OK) {
272 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
273 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
278 SetPragma(
m_db,
"locking_mode",
"exclusive",
"Unable to change database locking mode to exclusive");
280 int ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
nullptr);
281 if (
ret != SQLITE_OK) {
282 throw std::runtime_error(
"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of " CLIENT_NAME
"?\n");
284 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
285 if (
ret != SQLITE_OK) {
286 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(
ret)));
290 SetPragma(
m_db,
"fullfsync",
"true",
"Failed to enable fullfsync");
294 LogPrintf(
"WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
295 SetPragma(
m_db,
"synchronous",
"OFF",
"Failed to set synchronous mode to OFF");
300 sqlite3_stmt* check_main_stmt{
nullptr};
301 ret = sqlite3_prepare_v2(
m_db,
"SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt,
nullptr);
302 if (
ret != SQLITE_OK) {
303 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(
ret)));
305 ret = sqlite3_step(check_main_stmt);
306 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
307 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(
ret)));
310 if (
ret == SQLITE_DONE) {
311 table_exists =
false;
312 }
else if (
ret == SQLITE_ROW) {
315 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(
ret)));
320 ret = sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
321 if (
ret != SQLITE_OK) {
322 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(
ret)));
328 "Failed to set the application id");
332 "Failed to set the wallet schema version");
339 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
340 return ret == SQLITE_OK;
346 int res = sqlite3_open(dest.c_str(), &db_copy);
347 if (res != SQLITE_OK) {
348 sqlite3_close(db_copy);
351 sqlite3_backup* backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
353 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(
m_db));
354 sqlite3_close(db_copy);
358 res = sqlite3_backup_step(backup, -1);
359 if (res != SQLITE_DONE) {
360 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
361 sqlite3_backup_finish(backup);
362 sqlite3_close(db_copy);
365 res = sqlite3_backup_finish(backup);
366 sqlite3_close(db_copy);
367 return res == SQLITE_OK;
372 int res = sqlite3_close(
m_db);
373 if (res != SQLITE_OK) {
374 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
382 return m_db && sqlite3_get_autocommit(
m_db) == 0;
387 return sqlite3_exec(database.
m_db, statement.data(),
nullptr,
nullptr,
nullptr);
393 return std::make_unique<SQLiteBatch>(*
this);
397 : m_database(database)
407 bool force_conn_refresh =
false;
412 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
417 force_conn_refresh =
true;
418 LogPrintf(
"SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..\n");
423 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
431 for (
const auto& [stmt_prepared, stmt_description] : statements) {
432 int res = sqlite3_finalize(*stmt_prepared);
433 if (res != SQLITE_OK) {
434 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
435 stmt_description, sqlite3_errstr(res));
437 *stmt_prepared =
nullptr;
440 if (force_conn_refresh) {
446 }
catch (
const std::runtime_error&) {
462 if (res != SQLITE_ROW) {
463 if (res != SQLITE_DONE) {
465 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
501 int res = sqlite3_step(stmt);
502 sqlite3_clear_bindings(stmt);
504 if (res != SQLITE_DONE) {
505 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
510 return res == SQLITE_DONE;
525 int res = sqlite3_step(stmt);
526 sqlite3_clear_bindings(stmt);
528 if (res != SQLITE_DONE) {
529 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
534 return res == SQLITE_DONE;
557 return res == SQLITE_ROW;
563 if (res == SQLITE_DONE) {
566 if (res != SQLITE_ROW) {
567 LogPrintf(
"%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
585 if (res != SQLITE_OK) {
586 LogPrintf(
"%s: cursor closed but could not finalize cursor statement: %s\n",
587 __func__, sqlite3_errstr(res));
594 auto cursor = std::make_unique<SQLiteCursor>();
596 const char* stmt_text =
"SELECT key, value FROM main";
597 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, &cursor->m_cursor_stmt,
nullptr);
598 if (res != SQLITE_OK) {
600 "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res)));
613 std::vector<std::byte> start_range(
prefix.begin(),
prefix.end());
614 std::vector<std::byte> end_range(
prefix.begin(),
prefix.end());
615 auto it = end_range.rbegin();
616 for (; it != end_range.rend(); ++it) {
617 if (*it == std::byte(std::numeric_limits<unsigned char>::max())) {
621 *it = std::byte(std::to_integer<unsigned char>(*it) + 1);
624 if (it == end_range.rend()) {
629 auto cursor = std::make_unique<SQLiteCursor>(start_range, end_range);
630 if (!cursor)
return nullptr;
632 const char* stmt_text = end_range.empty() ?
"SELECT key, value FROM main WHERE key >= ?" :
633 "SELECT key, value FROM main WHERE key >= ? AND key < ?";
634 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, &cursor->m_cursor_stmt,
nullptr);
635 if (res != SQLITE_OK) {
637 "SQLiteDatabase: Failed to setup cursor SQL statement: %s\n", sqlite3_errstr(res)));
640 if (!
BindBlobToStatement(cursor->m_cursor_stmt, 1, cursor->m_prefix_range_start,
"prefix_start"))
return nullptr;
641 if (!end_range.empty()) {
642 if (!
BindBlobToStatement(cursor->m_cursor_stmt, 2, cursor->m_prefix_range_end,
"prefix_end"))
return nullptr;
654 if (res != SQLITE_OK) {
655 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
660 return res == SQLITE_OK;
668 if (res != SQLITE_OK) {
669 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
674 return res == SQLITE_OK;
682 if (res != SQLITE_OK) {
683 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
688 return res == SQLITE_OK;
695 auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options);
696 if (options.
verify && !db->Verify(error)) {
702 }
catch (
const std::runtime_error& e) {
711 return std::string(sqlite3_libversion());
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Double ended buffer combining vector and stream-like interfaces.
void write(std::span< const value_type > src)
bool ErasePrefix(std::span< const std::byte > prefix) override
bool ExecStatement(sqlite3_stmt *stmt, std::span< const std::byte > blob)
bool ReadKey(DataStream &&key, DataStream &value) override
bool TxnCommit() override
SQLiteBatch(SQLiteDatabase &database)
std::unique_ptr< SQliteExecHandler > m_exec_handler
bool HasKey(DataStream &&key) override
bool m_txn
Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_sem...
std::unique_ptr< DatabaseCursor > GetNewCursor() override
bool EraseKey(DataStream &&key) override
sqlite3_stmt * m_delete_stmt
std::unique_ptr< DatabaseCursor > GetNewPrefixCursor(std::span< const std::byte > prefix) override
sqlite3_stmt * m_read_stmt
sqlite3_stmt * m_overwrite_stmt
sqlite3_stmt * m_delete_prefix_stmt
void SetupSQLStatements()
sqlite3_stmt * m_insert_stmt
SQLiteDatabase & m_database
bool WriteKey(DataStream &&key, DataStream &&value, bool overwrite=true) override
Status Next(DataStream &key, DataStream &value) override
sqlite3_stmt * m_cursor_stmt
An instance of this class represents one SQLite3 database.
static Mutex g_sqlite_mutex
This mutex protects SQLite initialization and shutdown.
void Open() override
Open the database if it is not already opened.
std::string Filename() override
Return path to main database file for logs and error messages.
void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex)
const fs::path m_dir_path
void Close() override
Close the database.
bool Rewrite() override
Rewrite the entire database on disk.
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
std::unique_ptr< DatabaseBatch > MakeBatch() override
Make a SQLiteBatch connected to this database.
std::binary_semaphore m_write_semaphore
const std::string m_file_path
bool Verify(bilingual_str &error)
bool HasActiveTxn()
Return true if there is an on-going txn in this connection.
virtual int Exec(SQLiteDatabase &database, const std::string &statement)
An instance of this class represents one database.
uint32_t ReadBE32(const B *ptr)
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogTrace(category,...)
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
fs::path SQLiteDataFile(const fs::path &path)
static std::span< const std::byte > SpanFromBlob(sqlite3_stmt *stmt, int col)
static std::optional< int > ReadPragmaInteger(sqlite3 *db, const std::string &key, const std::string &description, bilingual_str &error)
static constexpr int32_t WALLET_SCHEMA_VERSION
static bool BindBlobToStatement(sqlite3_stmt *stmt, int index, std::span< const std::byte > blob, const std::string &description)
static int TraceSqlCallback(unsigned code, void *context, void *param1, void *param2)
static void SetPragma(sqlite3 *db, const std::string &key, const std::string &value, const std::string &err_msg)
std::string SQLiteDatabaseVersion()
static void ErrorLogCallback(void *arg, int code, const char *msg)
bool verify
Check data integrity on load.
#define AssertLockNotHeld(cs)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.