24 static int g_sqlite_count
GUARDED_BY(g_sqlite_mutex) = 0;
33 assert(arg ==
nullptr);
34 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code, msg);
38 :
WalletDatabase(), m_mock(mock), m_dir_path(dir_path.string()), m_file_path(file_path.string())
45 if (++g_sqlite_count == 1) {
48 if (ret != SQLITE_OK) {
49 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret)));
52 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
53 if (ret != SQLITE_OK) {
54 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret)));
57 int ret = sqlite3_initialize();
58 if (ret != SQLITE_OK) {
59 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret)));
65 }
catch (
const std::runtime_error&) {
76 if ((res = sqlite3_prepare_v2(
m_database.
m_db,
"SELECT value FROM main WHERE key = ?", -1, &
m_read_stmt,
nullptr)) != SQLITE_OK) {
77 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
82 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
87 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
92 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
97 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup SQL statements : %s\n", sqlite3_errstr(res)));
111 LOCK(g_sqlite_mutex);
112 if (--g_sqlite_count == 0) {
113 int ret = sqlite3_shutdown();
114 if (ret != SQLITE_OK) {
115 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret));
125 sqlite3_stmt* app_id_stmt{
nullptr};
126 int ret = sqlite3_prepare_v2(
m_db,
"PRAGMA application_id", -1, &app_id_stmt,
nullptr);
127 if (ret != SQLITE_OK) {
128 sqlite3_finalize(app_id_stmt);
129 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare the statement to fetch the application id: %s"), sqlite3_errstr(ret));
132 ret = sqlite3_step(app_id_stmt);
133 if (ret != SQLITE_ROW) {
134 sqlite3_finalize(app_id_stmt);
135 error =
strprintf(
_(
"SQLiteDatabase: Failed to fetch the application id: %s"), sqlite3_errstr(ret));
138 uint32_t app_id =
static_cast<uint32_t
>(sqlite3_column_int(app_id_stmt, 0));
139 sqlite3_finalize(app_id_stmt);
141 if (app_id != net_magic) {
142 error =
strprintf(
_(
"SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
147 sqlite3_stmt* user_ver_stmt{
nullptr};
148 ret = sqlite3_prepare_v2(
m_db,
"PRAGMA user_version", -1, &user_ver_stmt,
nullptr);
149 if (ret != SQLITE_OK) {
150 sqlite3_finalize(user_ver_stmt);
151 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare the statement to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
154 ret = sqlite3_step(user_ver_stmt);
155 if (ret != SQLITE_ROW) {
156 sqlite3_finalize(user_ver_stmt);
157 error =
strprintf(
_(
"SQLiteDatabase: Failed to fetch sqlite wallet schema version: %s"), sqlite3_errstr(ret));
160 int32_t user_ver = sqlite3_column_int(user_ver_stmt, 0);
161 sqlite3_finalize(user_ver_stmt);
167 sqlite3_stmt* stmt{
nullptr};
168 ret = sqlite3_prepare_v2(
m_db,
"PRAGMA integrity_check", -1, &stmt,
nullptr);
169 if (ret != SQLITE_OK) {
170 sqlite3_finalize(stmt);
171 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(ret));
175 ret = sqlite3_step(stmt);
176 if (ret == SQLITE_DONE) {
179 if (ret != SQLITE_ROW) {
180 error =
strprintf(
_(
"SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(ret));
183 const char* msg = (
const char*)sqlite3_column_text(stmt, 0);
185 error =
strprintf(
_(
"SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(ret));
188 std::string str_msg(msg);
189 if (str_msg ==
"ok") {
197 sqlite3_finalize(stmt);
198 return error.
empty();
203 int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
205 flags |= SQLITE_OPEN_MEMORY;
208 if (
m_db ==
nullptr) {
211 if (ret != SQLITE_OK) {
212 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret)));
216 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
217 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
222 int ret = sqlite3_exec(
m_db,
"PRAGMA locking_mode = exclusive",
nullptr,
nullptr,
nullptr);
223 if (ret != SQLITE_OK) {
224 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to change database locking mode to exclusive: %s\n", sqlite3_errstr(ret)));
227 ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
nullptr);
228 if (ret != SQLITE_OK) {
229 throw std::runtime_error(
"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another bitcoind?\n");
231 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
232 if (ret != SQLITE_OK) {
233 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret)));
237 ret = sqlite3_exec(
m_db,
"PRAGMA fullfsync = true",
nullptr,
nullptr,
nullptr);
238 if (ret != SQLITE_OK) {
239 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to enable fullfsync: %s\n", sqlite3_errstr(ret)));
244 sqlite3_stmt* check_main_stmt{
nullptr};
245 ret = sqlite3_prepare_v2(
m_db,
"SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt,
nullptr);
246 if (ret != SQLITE_OK) {
247 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret)));
249 ret = sqlite3_step(check_main_stmt);
250 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
251 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret)));
254 if (ret == SQLITE_DONE) {
255 table_exists =
false;
256 }
else if (ret == SQLITE_ROW) {
259 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret)));
264 ret = sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
265 if (ret != SQLITE_OK) {
266 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret)));
271 std::string set_app_id =
strprintf(
"PRAGMA application_id = %d", static_cast<int32_t>(app_id));
272 ret = sqlite3_exec(
m_db, set_app_id.c_str(),
nullptr,
nullptr,
nullptr);
273 if (ret != SQLITE_OK) {
274 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to set the application id: %s\n", sqlite3_errstr(ret)));
279 ret = sqlite3_exec(
m_db, set_user_ver.c_str(),
nullptr,
nullptr,
nullptr);
280 if (ret != SQLITE_OK) {
281 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to set the wallet schema version: %s\n", sqlite3_errstr(ret)));
289 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
290 return ret == SQLITE_OK;
296 int res = sqlite3_open(dest.c_str(), &db_copy);
297 if (res != SQLITE_OK) {
298 sqlite3_close(db_copy);
301 sqlite3_backup* backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
303 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(
m_db));
304 sqlite3_close(db_copy);
308 res = sqlite3_backup_step(backup, -1);
309 if (res != SQLITE_DONE) {
310 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
311 sqlite3_backup_finish(backup);
312 sqlite3_close(db_copy);
315 res = sqlite3_backup_finish(backup);
316 sqlite3_close(db_copy);
317 return res == SQLITE_OK;
322 int res = sqlite3_close(
m_db);
323 if (res != SQLITE_OK) {
324 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
332 return MakeUnique<SQLiteBatch>(*this);
336 : m_database(database)
349 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
351 LogPrintf(
"SQLiteBatch: Batch closed and failed to abort transaction\n");
357 if (ret != SQLITE_OK) {
358 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize read statement: %s\n", sqlite3_errstr(ret));
361 if (ret != SQLITE_OK) {
362 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize insert statement: %s\n", sqlite3_errstr(ret));
365 if (ret != SQLITE_OK) {
366 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize overwrite statement: %s\n", sqlite3_errstr(ret));
369 if (ret != SQLITE_OK) {
370 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize delete statement: %s\n", sqlite3_errstr(ret));
373 if (ret != SQLITE_OK) {
374 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize cursor statement: %s\n", sqlite3_errstr(ret));
389 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
390 if (res != SQLITE_OK) {
391 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
397 if (res != SQLITE_ROW) {
398 if (res != SQLITE_DONE) {
400 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
407 const char* data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_read_stmt, 0));
408 int data_size = sqlite3_column_bytes(
m_read_stmt, 0);
409 value.
write(data, data_size);
430 int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
431 if (res != SQLITE_OK) {
432 LogPrintf(
"%s: Unable to bind key to statement: %s\n", __func__, sqlite3_errstr(res));
433 sqlite3_clear_bindings(stmt);
437 res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
438 if (res != SQLITE_OK) {
439 LogPrintf(
"%s: Unable to bind value to statement: %s\n", __func__, sqlite3_errstr(res));
440 sqlite3_clear_bindings(stmt);
446 res = sqlite3_step(stmt);
447 sqlite3_clear_bindings(stmt);
449 if (res != SQLITE_DONE) {
450 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
452 return res == SQLITE_DONE;
461 int res = sqlite3_bind_blob(
m_delete_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
462 if (res != SQLITE_OK) {
463 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__, sqlite3_errstr(res));
473 if (res != SQLITE_DONE) {
474 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
476 return res == SQLITE_DONE;
486 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(), SQLITE_STATIC);
487 if (res == SQLITE_OK) {
489 if (res == SQLITE_ROW) {
514 if (res == SQLITE_DONE) {
518 if (res != SQLITE_ROW) {
519 LogPrintf(
"SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res));
524 const char* key_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 0));
526 key.
write(key_data, key_data_size);
527 const char* value_data =
reinterpret_cast<const char*
>(sqlite3_column_blob(
m_cursor_stmt, 1));
528 int value_data_size = sqlite3_column_bytes(
m_cursor_stmt, 1);
529 value.
write(value_data, value_data_size);
542 int res = sqlite3_exec(
m_database.
m_db,
"BEGIN TRANSACTION",
nullptr,
nullptr,
nullptr);
543 if (res != SQLITE_OK) {
544 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
546 return res == SQLITE_OK;
552 int res = sqlite3_exec(
m_database.
m_db,
"COMMIT TRANSACTION",
nullptr,
nullptr,
nullptr);
553 if (res != SQLITE_OK) {
554 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
556 return res == SQLITE_OK;
562 int res = sqlite3_exec(
m_database.
m_db,
"ROLLBACK TRANSACTION",
nullptr,
nullptr,
nullptr);
563 if (res != SQLITE_OK) {
564 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
566 return res == SQLITE_OK;
572 return fs::symlink_status(file).type() == fs::regular_file &&
IsSQLiteFile(file);
579 auto db = MakeUnique<SQLiteDatabase>(path, file);
580 if (options.
verify && !db->Verify(error)) {
586 }
catch (
const std::runtime_error& e) {
595 return std::string(sqlite3_libversion());
600 if (!fs::exists(path))
return false;
603 boost::system::error_code ec;
604 auto size = fs::file_size(path, ec);
605 if (ec)
LogPrintf(
"%s: %s %s\n", __func__, ec.message(), path.string());
606 if (size < 512)
return false;
609 if (!file.is_open())
return false;
613 file.read(magic, 16);
616 file.seekg(68, std::ios::beg);
618 file.read(app_id, 4);
623 std::string magic_str(magic, 16);
624 if (magic_str != std::string(
"SQLite format 3", 16)) {
629 return memcmp(
Params().MessageStart(), app_id, 4) == 0;
void CloseCursor() override
bool TxnCommit() override
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
static const char *const DATABASE_FILENAME
bool WriteKey(CDataStream &&key, CDataStream &&value, bool overwrite=true) override
bool ExistsSQLiteDatabase(const fs::path &path)
static void LogPrintf(const char *fmt, const Args &...args)
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...
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
bool IsSQLiteFile(const fs::path &path)
bool error(const char *fmt, const Args &...args)
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.
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.
sqlite3_stmt * m_insert_stmt
An instance of this class represents one database.