36 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code, msg);
41 std::string stmt_text =
strprintf(
"PRAGMA %s", key);
42 sqlite3_stmt* pragma_read_stmt{
nullptr};
43 int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt,
nullptr);
44 if (ret != SQLITE_OK) {
45 sqlite3_finalize(pragma_read_stmt);
46 error =
Untranslated(
strprintf(
"SQLiteDatabase: Failed to prepare the statement to fetch %s: %s", description, sqlite3_errstr(ret)));
49 ret = sqlite3_step(pragma_read_stmt);
50 if (ret != SQLITE_ROW) {
51 sqlite3_finalize(pragma_read_stmt);
55 int result = sqlite3_column_int(pragma_read_stmt, 0);
56 sqlite3_finalize(pragma_read_stmt);
60static void SetPragma(sqlite3* db,
const std::string& key,
const std::string& value,
const std::string& err_msg)
62 std::string stmt_text =
strprintf(
"PRAGMA %s = %s", key, value);
63 int ret = sqlite3_exec(db, stmt_text.c_str(),
nullptr,
nullptr,
nullptr);
64 if (ret != SQLITE_OK) {
65 throw std::runtime_error(
strprintf(
"SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(ret)));
77 if (++g_sqlite_count == 1) {
80 if (ret != SQLITE_OK) {
81 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
84 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
85 if (ret != SQLITE_OK) {
86 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
89 int ret = sqlite3_initialize();
90 if (ret != SQLITE_OK) {
91 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
97 }
catch (
const std::runtime_error&) {
106 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
107 {&
m_read_stmt,
"SELECT value FROM main WHERE key = ?"},
114 for (
const auto& [stmt_prepared, stmt_text] : statements) {
115 if (*stmt_prepared ==
nullptr) {
116 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, stmt_prepared,
nullptr);
117 if (res != SQLITE_OK) {
119 "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
135 if (--g_sqlite_count == 0) {
136 int ret = sqlite3_shutdown();
137 if (ret != SQLITE_OK) {
138 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
149 if (!read_result.has_value())
return false;
150 uint32_t app_id =
static_cast<uint32_t
>(read_result.value());
152 if (app_id != net_magic) {
153 error =
strprintf(
_(
"SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
159 if (!read_result.has_value())
return false;
160 int32_t user_ver = read_result.value();
166 sqlite3_stmt* stmt{
nullptr};
167 int ret = sqlite3_prepare_v2(
m_db,
"PRAGMA integrity_check", -1, &stmt,
nullptr);
168 if (ret != SQLITE_OK) {
169 sqlite3_finalize(stmt);
170 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(ret));
174 ret = sqlite3_step(stmt);
175 if (ret == SQLITE_DONE) {
178 if (ret != SQLITE_ROW) {
179 error =
strprintf(
_(
"SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(ret));
182 const char* msg = (
const char*)sqlite3_column_text(stmt, 0);
184 error =
strprintf(
_(
"SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(ret));
187 std::string str_msg(msg);
188 if (str_msg ==
"ok") {
196 sqlite3_finalize(stmt);
197 return error.empty();
202 int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
204 flags |= SQLITE_OPEN_MEMORY;
207 if (
m_db ==
nullptr) {
212 if (ret != SQLITE_OK) {
213 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
215 ret = sqlite3_extended_result_codes(
m_db, 1);
216 if (ret != SQLITE_OK) {
217 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(ret)));
221 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
222 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
227 SetPragma(
m_db,
"locking_mode",
"exclusive",
"Unable to change database locking mode to exclusive");
229 int ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
nullptr);
230 if (ret != SQLITE_OK) {
231 throw std::runtime_error(
"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of " PACKAGE_NAME "?\n");
233 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
234 if (ret != SQLITE_OK) {
235 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret)));
239 SetPragma(
m_db,
"fullfsync",
"true",
"Failed to enable fullfsync");
243 LogPrintf(
"WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
244 SetPragma(
m_db,
"synchronous",
"OFF",
"Failed to set synchronous mode to OFF");
249 sqlite3_stmt* check_main_stmt{
nullptr};
250 ret = sqlite3_prepare_v2(
m_db,
"SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt,
nullptr);
251 if (ret != SQLITE_OK) {
252 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
254 ret = sqlite3_step(check_main_stmt);
255 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
256 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
259 if (ret == SQLITE_DONE) {
260 table_exists =
false;
261 }
else if (ret == SQLITE_ROW) {
264 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
269 ret = sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
270 if (ret != SQLITE_OK) {
271 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
277 "Failed to set the application id");
281 "Failed to set the wallet schema version");
288 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
289 return ret == SQLITE_OK;
295 int res = sqlite3_open(dest.c_str(), &db_copy);
296 if (res != SQLITE_OK) {
297 sqlite3_close(db_copy);
300 sqlite3_backup* backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
302 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(
m_db));
303 sqlite3_close(db_copy);
307 res = sqlite3_backup_step(backup, -1);
308 if (res != SQLITE_DONE) {
309 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
310 sqlite3_backup_finish(backup);
311 sqlite3_close(db_copy);
314 res = sqlite3_backup_finish(backup);
315 sqlite3_close(db_copy);
316 return res == SQLITE_OK;
321 int res = sqlite3_close(
m_db);
322 if (res != SQLITE_OK) {
323 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
331 return std::make_unique<SQLiteBatch>(*
this);
335 : m_database(database)
348 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
350 LogPrintf(
"SQLiteBatch: Batch closed and failed to abort transaction\n");
355 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
363 for (
const auto& [stmt_prepared, stmt_description] : statements) {
364 int res = sqlite3_finalize(*stmt_prepared);
365 if (res != SQLITE_OK) {
366 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
367 stmt_description, sqlite3_errstr(res));
369 *stmt_prepared =
nullptr;
379 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
380 if (res != SQLITE_OK) {
381 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
387 if (res != SQLITE_ROW) {
388 if (res != SQLITE_DONE) {
390 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
397 const char* data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_read_stmt, 0));
398 int data_size = sqlite3_column_bytes(
m_read_stmt, 0);
399 value.
write(data, data_size);
420 int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
421 if (res != SQLITE_OK) {
422 LogPrintf(
"%s: Unable to bind key to statement: %s\n", __func__, sqlite3_errstr(res));
423 sqlite3_clear_bindings(stmt);
427 res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
428 if (res != SQLITE_OK) {
429 LogPrintf(
"%s: Unable to bind value to statement: %s\n", __func__, sqlite3_errstr(res));
430 sqlite3_clear_bindings(stmt);
436 res = sqlite3_step(stmt);
437 sqlite3_clear_bindings(stmt);
439 if (res != SQLITE_DONE) {
440 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
442 return res == SQLITE_DONE;
451 int res = sqlite3_bind_blob(
m_delete_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
452 if (res != SQLITE_OK) {
453 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
463 if (res != SQLITE_DONE) {
464 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
466 return res == SQLITE_DONE;
476 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
477 if (res == SQLITE_OK) {
479 if (res == SQLITE_ROW) {
504 if (res == SQLITE_DONE) {
508 if (res != SQLITE_ROW) {
509 LogPrintf(
"SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res));
514 const char* key_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 0));
516 key.
write(key_data, key_data_size);
517 const char* value_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 1));
518 int value_data_size = sqlite3_column_bytes(
m_cursor_stmt, 1);
519 value.
write(value_data, value_data_size);
532 int res = sqlite3_exec(
m_database.
m_db,
"BEGIN TRANSACTION",
nullptr,
nullptr,
nullptr);
533 if (res != SQLITE_OK) {
534 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
536 return res == SQLITE_OK;
542 int res = sqlite3_exec(
m_database.
m_db,
"COMMIT TRANSACTION",
nullptr,
nullptr,
nullptr);
543 if (res != SQLITE_OK) {
544 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
546 return res == SQLITE_OK;
552 int res = sqlite3_exec(
m_database.
m_db,
"ROLLBACK TRANSACTION",
nullptr,
nullptr,
nullptr);
553 if (res != SQLITE_OK) {
554 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
556 return res == SQLITE_OK;
563 auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file);
570 }
catch (
const std::runtime_error& e) {
579 return std::string(sqlite3_libversion());
const CChainParams & Params()
Return the currently selected parameters.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Double ended buffer combining vector and stream-like interfaces.
void write(const char *pch, size_t nSize)
bool WriteKey(CDataStream &&key, CDataStream &&value, bool overwrite=true) override
sqlite3_stmt * m_read_stmt
sqlite3_stmt * m_cursor_stmt
void SetupSQLStatements()
bool HasKey(CDataStream &&key) override
sqlite3_stmt * m_insert_stmt
sqlite3_stmt * m_overwrite_stmt
bool StartCursor() override
bool EraseKey(CDataStream &&key) override
bool ReadAtCursor(CDataStream &key, CDataStream &value, bool &complete) override
sqlite3_stmt * m_delete_stmt
bool ReadKey(CDataStream &&key, CDataStream &value) override
bool TxnCommit() override
SQLiteDatabase & m_database
void CloseCursor() override
SQLiteBatch(SQLiteDatabase &database)
An instance of this class represents one SQLite3 database.
void Close() override
Close the database.
void Open() override
Open the database if it is not already opened.
std::unique_ptr< DatabaseBatch > MakeBatch(bool flush_on_close=true) override
Make a SQLiteBatch connected to this database.
const std::string m_dir_path
bool Verify(bilingual_str &error)
const std::string m_file_path
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
bool Rewrite(const char *skip=nullptr) override
Rewrite the entire database on disk.
An instance of this class represents one database.
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
static uint32_t ReadBE32(const unsigned char *ptr)
fs::path SQLiteDataFile(const fs::path &path)
Filesystem operations and types.
static std::string PathToString(const path &path)
Convert path object to byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
static constexpr int32_t WALLET_SCHEMA_VERSION
static void SetPragma(sqlite3 *db, const std::string &key, const std::string &value, const std::string &err_msg)
static void ErrorLogCallback(void *arg, int code, const char *msg)
std::string SQLiteDatabaseVersion()
static Mutex g_sqlite_mutex
static std::optional< int > ReadPragmaInteger(sqlite3 *db, const std::string &key, const std::string &description, bilingual_str &error)
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
static int g_sqlite_count GUARDED_BY(g_sqlite_mutex)=0
bool error(const char *fmt, const Args &... args)
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists.