29 LogPrintf(
"SQLite Error. Code: %d. Message: %s\n", code, msg);
33 const fs::path &file_path,
bool mock)
41 if (++g_sqlite_count == 1) {
45 if (ret != SQLITE_OK) {
46 throw std::runtime_error(
47 strprintf(
"SQLiteDatabase: Failed to setup error log: %s\n",
48 sqlite3_errstr(ret)));
52 int ret = sqlite3_initialize();
53 if (ret != SQLITE_OK) {
54 throw std::runtime_error(
55 strprintf(
"SQLiteDatabase: Failed to initialize SQLite: %s\n",
56 sqlite3_errstr(ret)));
62 }
catch (
const std::runtime_error &) {
72 if ((res = sqlite3_prepare_v2(
76 "SQLiteDatabase: Failed to setup SQL statements: %s\n",
77 sqlite3_errstr(res)));
82 "INSERT INTO main VALUES(?, ?)", -1,
85 "SQLiteDatabase: Failed to setup SQL statements: %s\n",
86 sqlite3_errstr(res)));
90 if ((res = sqlite3_prepare_v2(
94 "SQLiteDatabase: Failed to setup SQL statements: %s\n",
95 sqlite3_errstr(res)));
100 "DELETE FROM main WHERE key = ?", -1,
103 "SQLiteDatabase: Failed to setup SQL statements: %s\n",
104 sqlite3_errstr(res)));
109 "SELECT key, value FROM main", -1,
112 "SQLiteDatabase: Failed to setup SQL statements : %s\n",
113 sqlite3_errstr(res)));
126 if (--g_sqlite_count == 0) {
127 int ret = sqlite3_shutdown();
128 if (ret != SQLITE_OK) {
129 LogPrintf(
"SQLiteDatabase: Failed to shutdown SQLite: %s\n",
130 sqlite3_errstr(ret));
138 sqlite3_stmt *stmt{
nullptr};
140 sqlite3_prepare_v2(
m_db,
"PRAGMA integrity_check", -1, &stmt,
nullptr);
141 if (ret != SQLITE_OK) {
142 sqlite3_finalize(stmt);
144 "verify database: %s"),
145 sqlite3_errstr(ret));
149 ret = sqlite3_step(stmt);
150 if (ret == SQLITE_DONE) {
153 if (ret != SQLITE_ROW) {
155 "to verify database: %s"),
156 sqlite3_errstr(ret));
159 const char *msg = (
const char *)sqlite3_column_text(stmt, 0);
162 "verification error: %s"),
163 sqlite3_errstr(ret));
166 std::string str_msg(msg);
167 if (str_msg ==
"ok") {
175 sqlite3_finalize(stmt);
176 return error.empty();
181 SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
184 flags |= SQLITE_OPEN_MEMORY;
187 if (
m_db ==
nullptr) {
190 if (ret != SQLITE_OK) {
191 throw std::runtime_error(
192 strprintf(
"SQLiteDatabase: Failed to open database: %s\n",
193 sqlite3_errstr(ret)));
197 if (sqlite3_db_readonly(
m_db,
"main") != 0) {
198 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly "
199 "mode but read-write permissions are needed");
204 int ret = sqlite3_exec(
m_db,
"PRAGMA locking_mode = exclusive",
nullptr,
206 if (ret != SQLITE_OK) {
207 throw std::runtime_error(
208 strprintf(
"SQLiteDatabase: Unable to change database locking mode "
209 "to exclusive: %s\n",
210 sqlite3_errstr(ret)));
214 ret = sqlite3_exec(
m_db,
"BEGIN EXCLUSIVE TRANSACTION",
nullptr,
nullptr,
216 if (ret != SQLITE_OK) {
217 throw std::runtime_error(
218 "SQLiteDatabase: Unable to obtain an exclusive lock on the "
219 "database, is it being used by another bitcoind?\n");
221 ret = sqlite3_exec(
m_db,
"COMMIT",
nullptr,
nullptr,
nullptr);
222 if (ret != SQLITE_OK) {
224 "SQLiteDatabase: Unable to end exclusive lock transaction: %s\n",
225 sqlite3_errstr(ret)));
229 ret = sqlite3_exec(
m_db,
"PRAGMA fullfsync = true",
nullptr,
nullptr,
231 if (ret != SQLITE_OK) {
232 throw std::runtime_error(
233 strprintf(
"SQLiteDatabase: Failed to enable fullfsync: %s\n",
234 sqlite3_errstr(ret)));
239 sqlite3_stmt *check_main_stmt{
nullptr};
240 ret = sqlite3_prepare_v2(
242 "SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1,
243 &check_main_stmt,
nullptr);
244 if (ret != SQLITE_OK) {
245 throw std::runtime_error(
246 strprintf(
"SQLiteDatabase: Failed to prepare statement to check "
247 "table existence: %s\n",
248 sqlite3_errstr(ret)));
250 ret = sqlite3_step(check_main_stmt);
251 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) {
252 throw std::runtime_error(
253 strprintf(
"SQLiteDatabase: Failed to finalize statement checking "
254 "table existence: %s\n",
255 sqlite3_errstr(ret)));
258 if (ret == SQLITE_DONE) {
259 table_exists =
false;
260 }
else if (ret == SQLITE_ROW) {
263 throw std::runtime_error(
264 strprintf(
"SQLiteDatabase: Failed to execute statement to check "
265 "table existence: %s\n",
266 sqlite3_errstr(ret)));
272 ret = sqlite3_exec(
m_db,
273 "CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, "
274 "value BLOB NOT NULL)",
275 nullptr,
nullptr,
nullptr);
276 if (ret != SQLITE_OK) {
277 throw std::runtime_error(
278 strprintf(
"SQLiteDatabase: Failed to create new database: %s\n",
279 sqlite3_errstr(ret)));
287 int ret = sqlite3_exec(
m_db,
"VACUUM",
nullptr,
nullptr,
nullptr);
288 return ret == SQLITE_OK;
293 int res = sqlite3_open(dest.c_str(), &db_copy);
294 if (res != SQLITE_OK) {
295 sqlite3_close(db_copy);
298 sqlite3_backup *backup = sqlite3_backup_init(db_copy,
"main",
m_db,
"main");
300 LogPrintf(
"%s: Unable to begin backup: %s\n", __func__,
301 sqlite3_errmsg(
m_db));
302 sqlite3_close(db_copy);
306 res = sqlite3_backup_step(backup, -1);
307 if (res != SQLITE_DONE) {
308 LogPrintf(
"%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res));
309 sqlite3_backup_finish(backup);
310 sqlite3_close(db_copy);
313 res = sqlite3_backup_finish(backup);
314 sqlite3_close(db_copy);
315 return res == SQLITE_OK;
319 int res = sqlite3_close(
m_db);
320 if (res != SQLITE_OK) {
321 throw std::runtime_error(
322 strprintf(
"SQLiteDatabase: Failed to close database: %s\n",
323 sqlite3_errstr(res)));
330 return std::make_unique<SQLiteBatch>(*
this);
345 LogPrintf(
"SQLiteBatch: Batch closed unexpectedly without the "
346 "transaction being explicitly committed or aborted\n");
349 "SQLiteBatch: Batch closed and failed to abort transaction\n");
355 if (ret != SQLITE_OK) {
356 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize read "
358 sqlite3_errstr(ret));
361 if (ret != SQLITE_OK) {
362 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize insert "
364 sqlite3_errstr(ret));
367 if (ret != SQLITE_OK) {
368 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize overwrite "
370 sqlite3_errstr(ret));
373 if (ret != SQLITE_OK) {
374 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize delete "
376 sqlite3_errstr(ret));
379 if (ret != SQLITE_OK) {
380 LogPrintf(
"SQLiteBatch: Batch closed but could not finalize cursor "
382 sqlite3_errstr(ret));
398 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(),
400 if (res != SQLITE_OK) {
401 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__,
402 sqlite3_errstr(res));
408 if (res != SQLITE_ROW) {
409 if (res != SQLITE_DONE) {
411 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__,
412 sqlite3_errstr(res));
420 size_t data_size(sqlite3_column_bytes(
m_read_stmt, 0));
421 value.
write({data, data_size});
444 int res = sqlite3_bind_blob(stmt, 1, key.data(), key.size(), SQLITE_STATIC);
445 if (res != SQLITE_OK) {
446 LogPrintf(
"%s: Unable to bind key to statement: %s\n", __func__,
447 sqlite3_errstr(res));
448 sqlite3_clear_bindings(stmt);
452 res = sqlite3_bind_blob(stmt, 2, value.data(), value.size(), SQLITE_STATIC);
453 if (res != SQLITE_OK) {
454 LogPrintf(
"%s: Unable to bind value to statement: %s\n", __func__,
455 sqlite3_errstr(res));
456 sqlite3_clear_bindings(stmt);
462 res = sqlite3_step(stmt);
463 sqlite3_clear_bindings(stmt);
465 if (res != SQLITE_DONE) {
466 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__,
467 sqlite3_errstr(res));
469 return res == SQLITE_DONE;
479 int res = sqlite3_bind_blob(
m_delete_stmt, 1, key.data(), key.size(),
481 if (res != SQLITE_OK) {
482 LogPrintf(
"%s: Unable to bind statement: %s\n", __func__,
483 sqlite3_errstr(res));
493 if (res != SQLITE_DONE) {
494 LogPrintf(
"%s: Unable to execute statement: %s\n", __func__,
495 sqlite3_errstr(res));
497 return res == SQLITE_DONE;
508 int res = sqlite3_bind_blob(
m_read_stmt, 1, key.data(), key.size(),
510 if (res == SQLITE_OK) {
512 if (res == SQLITE_ROW) {
540 if (res == SQLITE_DONE) {
544 if (res != SQLITE_ROW) {
546 "SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n",
547 sqlite3_errstr(res));
553 size_t key_data_size(sqlite3_column_bytes(
m_cursor_stmt, 0));
554 key.
write({key_data, key_data_size});
556 size_t value_data_size(sqlite3_column_bytes(
m_cursor_stmt, 1));
557 value.
write({value_data, value_data_size});
570 int res = sqlite3_exec(
m_database.
m_db,
"BEGIN TRANSACTION",
nullptr,
572 if (res != SQLITE_OK) {
573 LogPrintf(
"SQLiteBatch: Failed to begin the transaction\n");
575 return res == SQLITE_OK;
582 int res = sqlite3_exec(
m_database.
m_db,
"COMMIT TRANSACTION",
nullptr,
584 if (res != SQLITE_OK) {
585 LogPrintf(
"SQLiteBatch: Failed to commit the transaction\n");
587 return res == SQLITE_OK;
594 int res = sqlite3_exec(
m_database.
m_db,
"ROLLBACK TRANSACTION",
nullptr,
596 if (res != SQLITE_OK) {
597 LogPrintf(
"SQLiteBatch: Failed to abort the transaction\n");
599 return res == SQLITE_OK;
606std::unique_ptr<SQLiteDatabase>
611 auto db = std::make_unique<SQLiteDatabase>(path, file);
617 }
catch (
const std::runtime_error &e) {
619 error.original = e.what();
625 return std::string(sqlite3_libversion());
Double ended buffer combining vector and stream-like interfaces.
void write(Span< const value_type > src)
Different type to mark Mutex at global scope.
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 block calls to the fs::path(std::string) implicit constructor and the fs::path:...
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
bool error(const char *fmt, const Args &...args)
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.
const std::byte * BytePtr(const void *data)
Convert a data pointer to a std::byte data pointer.
static void ErrorLogCallback(void *arg, int code, const char *msg)
std::string SQLiteDatabaseVersion()
static GlobalMutex g_sqlite_mutex
std::unique_ptr< SQLiteDatabase > MakeSQLiteDatabase(const fs::path &path, const DatabaseOptions &options, DatabaseStatus &status, bilingual_str &error)
static const char *const DATABASE_FILENAME
bool ExistsSQLiteDatabase(const fs::path &path)
static int g_sqlite_count GUARDED_BY(g_sqlite_mutex)=0
bilingual_str _(const char *psz)
Translation function.
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.