7 #include <chainparams.h>
34 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code, msg);
40 const std::string& description)
42 int res = sqlite3_bind_blob(stmt, index, blob.
data(), blob.
size(), SQLITE_STATIC);
43 if (res != SQLITE_OK) {
44 LogPrintf(
"Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res));
45 sqlite3_clear_bindings(stmt);
55 std::string stmt_text =
strprintf(
"PRAGMA %s", key);
56 sqlite3_stmt* pragma_read_stmt{
nullptr};
57 int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt,
nullptr);
58 if (
ret != SQLITE_OK) {
59 sqlite3_finalize(pragma_read_stmt);
63 ret = sqlite3_step(pragma_read_stmt);
64 if (
ret != SQLITE_ROW) {
65 sqlite3_finalize(pragma_read_stmt);
69 int result = sqlite3_column_int(pragma_read_stmt, 0);
70 sqlite3_finalize(pragma_read_stmt);
74 static void SetPragma(sqlite3* db,
const std::string& key,
const std::string& value,
const std::string& err_msg)
76 std::string stmt_text =
strprintf(
"PRAGMA %s = %s", key, value);
77 int ret = sqlite3_exec(db, stmt_text.c_str(),
nullptr,
nullptr,
nullptr);
78 if (
ret != SQLITE_OK) {
79 throw std::runtime_error(
strprintf(
"SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(
ret)));
84 int SQLiteDatabase::g_sqlite_count = 0;
94 if (++g_sqlite_count == 1) {
97 if (
ret != SQLITE_OK) {
98 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(
ret)));
101 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
102 if (
ret != SQLITE_OK) {
103 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(
ret)));
106 int ret = sqlite3_initialize();
107 if (
ret != SQLITE_OK) {
108 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(
ret)));
114 }
catch (
const std::runtime_error&) {
123 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
124 {&
m_read_stmt,
"SELECT value FROM main WHERE key = ?"},
130 for (
const auto& [stmt_prepared, stmt_text] : statements) {
131 if (*stmt_prepared ==
nullptr) {
132 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, stmt_prepared,
nullptr);
133 if (res != SQLITE_OK) {
135 "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res)));
153 if (--g_sqlite_count == 0) {
154 int ret = sqlite3_shutdown();
155 if (
ret != SQLITE_OK) {
156 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(
ret));
167 if (!read_result.has_value())
return false;
168 uint32_t app_id =
static_cast<uint32_t
>(read_result.value());
170 if (app_id != net_magic) {
171 error =
strprintf(
_(
"SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id);
177 if (!read_result.has_value())
return false;
178 int32_t user_ver = read_result.value();
184 sqlite3_stmt* stmt{
nullptr};
185 int ret = sqlite3_prepare_v2(
m_db,
"PRAGMA integrity_check", -1, &stmt,
nullptr);
186 if (
ret != SQLITE_OK) {
187 sqlite3_finalize(stmt);
188 error =
strprintf(
_(
"SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(
ret));
192 ret = sqlite3_step(stmt);
193 if (
ret == SQLITE_DONE) {
196 if (
ret != SQLITE_ROW) {
197 error =
strprintf(
_(
"SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(
ret));
200 const char* msg = (
const char*)sqlite3_column_text(stmt, 0);
202 error =
strprintf(
_(
"SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(
ret));
205 std::string str_msg(msg);
206 if (str_msg ==
"ok") {
214 sqlite3_finalize(stmt);
215 return error.empty();
220 int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
222 flags |= SQLITE_OPEN_MEMORY;
225 if (
m_db ==
nullptr) {
230 if (
ret != SQLITE_OK) {
231 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(
ret)));
233 ret = sqlite3_extended_result_codes(
m_db, 1);
234 if (
ret != SQLITE_OK) {
235 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(
ret)));
239 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
240 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
245 SetPragma(
m_db,
"locking_mode",
"exclusive",
"Unable to change database locking mode to exclusive");
247 int ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
nullptr);
248 if (
ret != SQLITE_OK) {
249 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");
251 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
252 if (
ret != SQLITE_OK) {
253 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(
ret)));
257 SetPragma(
m_db,
"fullfsync",
"true",
"Failed to enable fullfsync");
261 LogPrintf(
"WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n");
262 SetPragma(
m_db,
"synchronous",
"OFF",
"Failed to set synchronous mode to OFF");
267 sqlite3_stmt* check_main_stmt{
nullptr};
268 ret = sqlite3_prepare_v2(
m_db,
"SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt,
nullptr);
269 if (
ret != SQLITE_OK) {
270 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(
ret)));
272 ret = sqlite3_step(check_main_stmt);
273 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
274 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(
ret)));
277 if (
ret == SQLITE_DONE) {
278 table_exists =
false;
279 }
else if (
ret == SQLITE_ROW) {
282 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(
ret)));
287 ret = sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
288 if (
ret != SQLITE_OK) {
289 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(
ret)));
295 "Failed to set the application id");
299 "Failed to set the wallet schema version");
306 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
307 return ret == SQLITE_OK;
313 int res = sqlite3_open(dest.c_str(), &db_copy);
314 if (res != SQLITE_OK) {
315 sqlite3_close(db_copy);
318 sqlite3_backup* backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
320 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(
m_db));
321 sqlite3_close(db_copy);
325 res = sqlite3_backup_step(backup, -1);
326 if (res != SQLITE_DONE) {
327 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
328 sqlite3_backup_finish(backup);
329 sqlite3_close(db_copy);
332 res = sqlite3_backup_finish(backup);
333 sqlite3_close(db_copy);
334 return res == SQLITE_OK;
339 int res = sqlite3_close(
m_db);
340 if (res != SQLITE_OK) {
341 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res)));
349 return std::make_unique<SQLiteBatch>(*
this);
353 : m_database(database)
366 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n");
368 LogPrintf(
"SQLiteBatch: Batch closed and failed to abort transaction\n");
373 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{
380 for (
const auto& [stmt_prepared, stmt_description] : statements) {
381 int res = sqlite3_finalize(*stmt_prepared);
382 if (res != SQLITE_OK) {
383 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize %s statement: %s\n",
384 stmt_description, sqlite3_errstr(res));
386 *stmt_prepared =
nullptr;
398 if (res != SQLITE_ROW) {
399 if (res != SQLITE_DONE) {
401 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
409 size_t data_size(sqlite3_column_bytes(
m_read_stmt, 0));
410 value.
write({data, data_size});
435 int res = sqlite3_step(stmt);
436 sqlite3_clear_bindings(stmt);
438 if (res != SQLITE_DONE) {
439 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
441 return res == SQLITE_DONE;
456 if (res != SQLITE_DONE) {
457 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res));
459 return res == SQLITE_DONE;
472 return res == SQLITE_ROW;
478 if (res == SQLITE_DONE) {
481 if (res != SQLITE_ROW) {
482 LogPrintf(
"%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res));
488 size_t key_data_size(sqlite3_column_bytes(
m_cursor_stmt, 0));
489 key.
write({key_data, key_data_size});
491 size_t value_data_size(sqlite3_column_bytes(
m_cursor_stmt, 1));
492 value.
write({value_data, value_data_size});
500 if (res != SQLITE_OK) {
501 LogPrintf(
"%s: cursor closed but could not finalize cursor statement: %s\n",
502 __func__, sqlite3_errstr(res));
509 auto cursor = std::make_unique<SQLiteCursor>();
511 const char* stmt_text =
"SELECT key, value FROM main";
512 int res = sqlite3_prepare_v2(
m_database.
m_db, stmt_text, -1, &cursor->m_cursor_stmt,
nullptr);
513 if (res != SQLITE_OK) {
515 "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res)));
524 int res = sqlite3_exec(
m_database.
m_db,
"BEGIN TRANSACTION",
nullptr,
nullptr,
nullptr);
525 if (res != SQLITE_OK) {
526 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
528 return res == SQLITE_OK;
534 int res = sqlite3_exec(
m_database.
m_db,
"COMMIT TRANSACTION",
nullptr,
nullptr,
nullptr);
535 if (res != SQLITE_OK) {
536 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
538 return res == SQLITE_OK;
544 int res = sqlite3_exec(
m_database.
m_db,
"ROLLBACK TRANSACTION",
nullptr,
nullptr,
nullptr);
545 if (res != SQLITE_OK) {
546 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
548 return res == SQLITE_OK;
555 auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options);
562 }
catch (
const std::runtime_error& e) {
571 return std::string(sqlite3_libversion());
const CChainParams & Params()
Return the currently selected parameters.
Double ended buffer combining vector and stream-like interfaces.
void write(Span< const value_type > src)
A Span is an object that can refer to a contiguous sequence of objects.
constexpr std::size_t size() const noexcept
constexpr C * data() const noexcept
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
bool ReadKey(DataStream &&key, DataStream &value) override
bool TxnCommit() override
SQLiteBatch(SQLiteDatabase &database)
bool HasKey(DataStream &&key) override
std::unique_ptr< DatabaseCursor > GetNewCursor() override
bool EraseKey(DataStream &&key) override
sqlite3_stmt * m_delete_stmt
sqlite3_stmt * m_read_stmt
sqlite3_stmt * m_overwrite_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.
bool Rewrite(const char *skip=nullptr) override
Rewrite the entire database on disk.
void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex)
void Close() override
Close the database.
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
const std::string m_dir_path
const std::string m_file_path
std::unique_ptr< DatabaseBatch > MakeBatch(bool flush_on_close=true) override
Make a SQLiteBatch connected to this database.
bool Verify(bilingual_str &error)
An instance of this class represents one database.
static uint32_t ReadBE32(const unsigned char *ptr)
bool error(const char *fmt, const Args &... args)
Filesystem operations and types.
static std::string PathToString(const path &path)
Convert path object to a byte string.
static path PathFromString(const std::string &string)
Convert byte string to path object.
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 constexpr int32_t WALLET_SCHEMA_VERSION
static bool BindBlobToStatement(sqlite3_stmt *stmt, int index, Span< const std::byte > blob, const std::string &description)
static void SetPragma(sqlite3 *db, const std::string &key, const std::string &value, const std::string &err_msg)
static std::optional< int > ReadPragmaInteger(sqlite3 *db, const std::string &key, const std::string &description, bilingual_str &error)
std::string SQLiteDatabaseVersion()
static void ErrorLogCallback(void *arg, int code, const char *msg)
const std::byte * AsBytePtr(const void *data)
Convert a data pointer to a std::byte data pointer.
bool verify
Check data integrity on load.
#define AssertLockNotHeld(cs)
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 create_directories if the requested directory exists.