23 static int g_sqlite_count
GUARDED_BY(g_sqlite_mutex) = 0;
33 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code, msg);
37 :
WalletDatabase(), m_mock(mock), m_dir_path(dir_path.string()), m_file_path(file_path.string())
44 if (++g_sqlite_count == 1) {
47 if (ret != SQLITE_OK) {
48 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
51 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
52 if (ret != SQLITE_OK) {
53 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
56 int ret = sqlite3_initialize();
57 if (ret != SQLITE_OK) {
58 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
64 }
catch (
const std::runtime_error&) {
75 if ((res = sqlite3_prepare_v2(m_database.m_db,
"SELECT value FROM main WHERE key = ?", -1, &m_read_stmt,
nullptr)) != SQLITE_OK) {
76 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
80 if ((res = sqlite3_prepare_v2(m_database.m_db,
"INSERT INTO main VALUES(?, ?)", -1, &m_insert_stmt,
nullptr)) != SQLITE_OK) {
81 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
84 if (!m_overwrite_stmt) {
85 if ((res = sqlite3_prepare_v2(m_database.m_db,
"INSERT or REPLACE into main values(?, ?)", -1, &m_overwrite_stmt,
nullptr)) != SQLITE_OK) {
86 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
90 if ((res = sqlite3_prepare_v2(m_database.m_db,
"DELETE FROM main WHERE key = ?", -1, &m_delete_stmt,
nullptr)) != SQLITE_OK) {
91 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
95 if ((res = sqlite3_prepare_v2(m_database.m_db,
"SELECT key, value FROM main", -1, &m_cursor_stmt,
nullptr)) != SQLITE_OK) {
96 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements : %s\n", sqlite3_errstr(res)));
110 LOCK(g_sqlite_mutex);
111 if (--g_sqlite_count == 0) {
112 int ret = sqlite3_shutdown();
113 if (ret != SQLITE_OK) {
114 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
124 sqlite3_stmt* app_id_stmt{
nullptr};
125 int ret = sqlite3_prepare_v2(
m_db,
"PRAGMA application_id", -1, &app_id_stmt,
nullptr);
126 if (ret != SQLITE_OK) {
127 sqlite3_finalize(app_id_stmt);
128 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s"), sqlite3_errstr(ret));
131 ret = sqlite3_step(app_id_stmt);
132 if (ret != SQLITE_ROW) {
133 sqlite3_finalize(app_id_stmt);
134 error =
strprintf(
_(
"SQLiteDatabase: Failed to fetch the application id: %s"), sqlite3_errstr(ret));
137 uint32_t app_id =
static_cast<uint32_t
>(sqlite3_column_int(app_id_stmt, 0));
138 sqlite3_finalize(app_id_stmt);
140 if (app_id != net_magic) {
141 error =
strprintf(
_(
"SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
146 sqlite3_stmt* user_ver_stmt{
nullptr};
147 ret = sqlite3_prepare_v2(
m_db,
"PRAGMA user_version", -1, &user_ver_stmt,
nullptr);
148 if (ret != SQLITE_OK) {
149 sqlite3_finalize(user_ver_stmt);
150 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
153 ret = sqlite3_step(user_ver_stmt);
154 if (ret != SQLITE_ROW) {
155 sqlite3_finalize(user_ver_stmt);
156 error =
strprintf(
_(
"SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
159 int32_t user_ver = sqlite3_column_int(user_ver_stmt, 0);
160 sqlite3_finalize(user_ver_stmt);
166 sqlite3_stmt* stmt{
nullptr};
167 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)));
217 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
218 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
223 int ret = sqlite3_exec(
m_db,
"PRAGMA locking_mode = exclusive",
nullptr,
nullptr,
nullptr);
224 if (ret != SQLITE_OK) {
225 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to change database locking mode to exclusive: %s\n", sqlite3_errstr(ret)));
228 ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
nullptr);
229 if (ret != SQLITE_OK) {
230 throw std::runtime_error(
"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?\n");
232 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
233 if (ret != SQLITE_OK) {
234 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret)));
238 ret = sqlite3_exec(
m_db,
"PRAGMA fullfsync = true",
nullptr,
nullptr,
nullptr);
239 if (ret != SQLITE_OK) {
240 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to enable fullfsync: %s\n", sqlite3_errstr(ret)));
245 sqlite3_stmt* check_main_stmt{
nullptr};
246 ret = sqlite3_prepare_v2(
m_db,
"SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt,
nullptr);
247 if (ret != SQLITE_OK) {
248 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
250 ret = sqlite3_step(check_main_stmt);
251 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
252 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
255 if (ret == SQLITE_DONE) {
256 table_exists =
false;
257 }
else if (ret == SQLITE_ROW) {
260 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
265 ret = sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
266 if (ret != SQLITE_OK) {
267 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
272 std::string set_app_id =
strprintf(
"PRAGMA application_id = %d", static_cast<int32_t>(app_id));
273 ret = sqlite3_exec(
m_db, set_app_id.c_str(),
nullptr,
nullptr,
nullptr);
274 if (ret != SQLITE_OK) {
275 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to set the application id: %s\n", sqlite3_errstr(ret)));
280 ret = sqlite3_exec(
m_db, set_user_ver.c_str(),
nullptr,
nullptr,
nullptr);
281 if (ret != SQLITE_OK) {
282 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to set the wallet schema version: %s\n", sqlite3_errstr(ret)));
290 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
291 return ret == SQLITE_OK;
297 int res = sqlite3_open(dest.c_str(), &db_copy);
298 if (res != SQLITE_OK) {
299 sqlite3_close(db_copy);
302 sqlite3_backup* backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
304 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(
m_db));
305 sqlite3_close(db_copy);
309 res = sqlite3_backup_step(backup, -1);
310 if (res != SQLITE_DONE) {
311 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
312 sqlite3_backup_finish(backup);
313 sqlite3_close(db_copy);
316 res = sqlite3_backup_finish(backup);
317 sqlite3_close(db_copy);
318 return res == SQLITE_OK;
323 int res = sqlite3_close(
m_db);
324 if (res != SQLITE_OK) {
325 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
333 return MakeUnique<SQLiteBatch>(*this);
337 : m_database(database)
350 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
352 LogPrintf(
"SQLiteBatch: Batch closed and failed to abort transaction\n");
358 if (ret != SQLITE_OK) {
359 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize read statement: %s\n", sqlite3_errstr(ret));
362 if (ret != SQLITE_OK) {
363 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize insert statement: %s\n", sqlite3_errstr(ret));
366 if (ret != SQLITE_OK) {
367 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize overwrite statement: %s\n", sqlite3_errstr(ret));
370 if (ret != SQLITE_OK) {
371 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize delete statement: %s\n", sqlite3_errstr(ret));
374 if (ret != SQLITE_OK) {
375 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize cursor statement: %s\n", sqlite3_errstr(ret));
390 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
391 if (res != SQLITE_OK) {
392 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
398 if (res != SQLITE_ROW) {
399 if (res != SQLITE_DONE) {
401 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
408 const char* data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_read_stmt, 0));
409 int data_size = sqlite3_column_bytes(
m_read_stmt, 0);
410 value.
write(data, data_size);
431 int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
432 if (res != SQLITE_OK) {
433 LogPrintf(
"%s: Unable to bind key to statement: %s\n", __func__, sqlite3_errstr(res));
434 sqlite3_clear_bindings(stmt);
438 res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
439 if (res != SQLITE_OK) {
440 LogPrintf(
"%s: Unable to bind value to statement: %s\n", __func__, sqlite3_errstr(res));
441 sqlite3_clear_bindings(stmt);
447 res = sqlite3_step(stmt);
448 sqlite3_clear_bindings(stmt);
450 if (res != SQLITE_DONE) {
451 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
453 return res == SQLITE_DONE;
462 int res = sqlite3_bind_blob(
m_delete_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
463 if (res != SQLITE_OK) {
464 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
474 if (res != SQLITE_DONE) {
475 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
477 return res == SQLITE_DONE;
487 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
488 if (res == SQLITE_OK) {
490 if (res == SQLITE_ROW) {
515 if (res == SQLITE_DONE) {
519 if (res != SQLITE_ROW) {
520 LogPrintf(
"SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res));
525 const char* key_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 0));
527 key.
write(key_data, key_data_size);
528 const char* value_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 1));
529 int value_data_size = sqlite3_column_bytes(
m_cursor_stmt, 1);
530 value.
write(value_data, value_data_size);
543 int res = sqlite3_exec(
m_database.
m_db,
"BEGIN TRANSACTION",
nullptr,
nullptr,
nullptr);
544 if (res != SQLITE_OK) {
545 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
547 return res == SQLITE_OK;
553 int res = sqlite3_exec(
m_database.
m_db,
"COMMIT TRANSACTION",
nullptr,
nullptr,
nullptr);
554 if (res != SQLITE_OK) {
555 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
557 return res == SQLITE_OK;
563 int res = sqlite3_exec(
m_database.
m_db,
"ROLLBACK TRANSACTION",
nullptr,
nullptr,
nullptr);
564 if (res != SQLITE_OK) {
565 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
567 return res == SQLITE_OK;
574 auto db = MakeUnique<SQLiteDatabase>(data_file.parent_path(), data_file);
575 if (options.
verify && !db->Verify(error)) {
581 }
catch (
const std::runtime_error& e) {
590 return std::string(sqlite3_libversion());
void CloseCursor() override
bool TxnCommit() override
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
bool WriteKey(CDataStream &&key, CDataStream &&value, bool overwrite=true) override
static Mutex g_sqlite_mutex
static int g_sqlite_count GUARDED_BY(g_sqlite_mutex)=0
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
bool Rewrite(const char *skip=nullptr) override
Rewrite the entire database on disk.
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by Boost's create_directories if the requested directory exists...
static void LogPrintf(const char *fmt, const Args &... args)
Double ended buffer combining vector and stream-like interfaces.
void write(const char *pch, size_t nSize)
void SetupSQLStatements()
void Open() override
Open the database if it is not already opened.
bool EraseKey(CDataStream &&key) override
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
sqlite3_stmt * m_read_stmt
sqlite3_stmt * m_overwrite_stmt
bilingual_str _(const char *psz)
Translation function.
const std::string m_dir_path
bool HasKey(CDataStream &&key) override
bool ReadAtCursor(CDataStream &key, CDataStream &value, bool &complete) override
static uint32_t ReadBE32(const unsigned char *ptr)
static constexpr int32_t WALLET_SCHEMA_VERSION
An instance of this class represents one SQLite3 database.
bool StartCursor() override
SQLiteDatabase & m_database
static void ErrorLogCallback(void *arg, int code, const char *msg)
std::string SQLiteDatabaseVersion()
const std::string m_file_path
bool Verify(bilingual_str &error)
sqlite3_stmt * m_cursor_stmt
const CChainParams & Params()
Return the currently selected parameters.
fs::path SQLiteDataFile(const fs::path &path)
SQLiteBatch(SQLiteDatabase &database)
sqlite3_stmt * m_delete_stmt
void Close() override
Close the database.
bool ReadKey(CDataStream &&key, CDataStream &value) override
std::unique_ptr< DatabaseBatch > MakeBatch(bool flush_on_close=true) override
Make a SQLiteBatch connected to this database.
bool error(const char *fmt, const Args &... args)
sqlite3_stmt * m_insert_stmt
An instance of this class represents one database.