5#include <bitcoin-build-config.h>
9#include <chainparams.h>
43 LogWarning(
"SQLite Error. Code: %d. Message: %s", code, msg);
63 std::span<const std::byte>
blob,
64 const std::string& description)
102static void SetPragma(
sqlite3*
db,
const std::string& key,
const std::string& value,
const std::string& err_msg)
112int SQLiteDatabase::g_sqlite_count = 0;
132 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to configure serialized threading mode: %s",
sqlite3_errstr(
ret)));
143 }
catch (
const std::runtime_error&) {
152 const std::vector<std::pair<sqlite3_stmt**, const char*>>
statements{
153 {&
m_read_stmt,
"SELECT value FROM main WHERE key = ?"},
245 return error.
empty();
251 throw std::runtime_error(
"SQLiteDatabase: Cannot reopen an in-memory database");
260 if (
m_db ==
nullptr) {
286 throw std::runtime_error(
"SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed");
291 SetPragma(
m_db,
"locking_mode",
"exclusive",
"Unable to change database locking mode to exclusive");
295 throw std::runtime_error(
"SQLiteDatabase: Unable to obtain an exclusive lock on the database, is it being used by another instance of " CLIENT_NAME "?");
303 SetPragma(
m_db,
"fullfsync",
"true",
"Failed to enable fullfsync");
307 LogWarning(
"SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.");
308 SetPragma(
m_db,
"synchronous",
"OFF",
"Failed to set synchronous mode to OFF");
316 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to prepare statement to check table existence: %s",
sqlite3_errstr(
ret)));
320 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to finalize statement checking table existence: %s",
sqlite3_errstr(
ret)));
328 throw std::runtime_error(
strprintf(
"SQLiteDatabase: Failed to execute statement to check table existence: %s",
sqlite3_errstr(
ret)));
333 ret =
sqlite3_exec(
m_db,
"CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)",
nullptr,
nullptr,
nullptr);
341 "Failed to set the application id");
345 "Failed to set the wallet schema version");
406 return std::make_unique<SQLiteBatch>(*
this);
425 LogWarning(
"SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted");
431 LogWarning(
"SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..");
436 const std::vector<std::pair<sqlite3_stmt**, const char*>>
statements{
447 LogWarning(
"SQLiteBatch: Batch closed but could not finalize %s statement: %s",
455 throw std::runtime_error(
"SQLiteDatabase: Cannot recover in-memory database connection");
462 }
catch (
const std::runtime_error&) {
602 LogWarning(
"Cursor closed but could not finalize cursor statement: %s",
610 auto cursor = std::make_unique<SQLiteCursor>();
612 const char*
stmt_text =
"SELECT key, value FROM main";
633 if (*it == std::byte(std::numeric_limits<unsigned char>::max())) {
637 *it = std::byte(std::to_integer<unsigned char>(*it) + 1);
646 if (!
cursor)
return nullptr;
648 const char*
stmt_text =
end_range.empty() ?
"SELECT key, value FROM main WHERE key >= ?" :
649 "SELECT key, value FROM main WHERE key >= ? AND key < ?";
653 "SQLiteDatabase: Failed to setup cursor SQL statement: %s",
sqlite3_errstr(
res)));
671 LogWarning(
"SQLiteBatch: Failed to begin the transaction");
685 LogWarning(
"SQLiteBatch: Failed to commit the transaction");
699 LogWarning(
"SQLiteBatch: Failed to abort the transaction");
712 if (options.
verify && !
db->Verify(error)) {
718 }
catch (
const std::runtime_error&
e) {
731 return std::make_unique<InMemoryWalletDatabase>();
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
Double ended buffer combining vector and stream-like interfaces.
void write(std::span< const value_type > src)
bool ErasePrefix(std::span< const std::byte > prefix) override
bool ExecStatement(sqlite3_stmt *stmt, std::span< const std::byte > blob)
bool ReadKey(DataStream &&key, DataStream &value) override
bool TxnCommit() override
SQLiteBatch(SQLiteDatabase &database)
std::unique_ptr< SQliteExecHandler > m_exec_handler
bool HasKey(DataStream &&key) override
bool m_txn
Whether this batch has started a database transaction and whether it owns SQLiteDatabase::m_write_sem...
std::unique_ptr< DatabaseCursor > GetNewCursor() override
bool EraseKey(DataStream &&key) override
sqlite3_stmt * m_delete_stmt
std::unique_ptr< DatabaseCursor > GetNewPrefixCursor(std::span< const std::byte > prefix) override
sqlite3_stmt * m_read_stmt
sqlite3_stmt * m_overwrite_stmt
sqlite3_stmt * m_delete_prefix_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.
std::string Filename() override
Return path to main database file for logs and error messages.
const int m_additional_flags
void Cleanup() noexcept EXCLUSIVE_LOCKS_REQUIRED(!g_sqlite_mutex)
const fs::path m_dir_path
void Close() override
Close the database.
bool Rewrite() override
Rewrite the entire database on disk.
bool Backup(const std::string &dest) const override
Back up the entire database to a file.
std::unique_ptr< DatabaseBatch > MakeBatch() override
Make a SQLiteBatch connected to this database.
void Open(int additional_flags)
std::binary_semaphore m_write_semaphore
const std::string m_file_path
bool Verify(bilingual_str &error)
bool HasActiveTxn()
Return true if there is an on-going txn in this connection.
virtual int Exec(SQLiteDatabase &database, const std::string &statement)
An instance of this class represents one database.
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
uint32_t ReadBE32(const B *ptr)
static std::string PathToString(const path &path)
Convert path object to a byte string.
bool IsDirWritable(const fs::path &dir_path)
Check if a directory is writable by creating a temporary file on it.
bool TryCreateDirectories(const fs::path &p)
Ignores exceptions thrown by create_directories if the requested directory exists.
#define LogTrace(category,...)
bool ShouldTraceLog(Category)
Return whether messages with specified category should be trace logged.
std::unique_ptr< WalletDatabase > MakeInMemoryWalletDatabase()
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 std::span< const std::byte > SpanFromBlob(sqlite3_stmt *stmt, int col)
static std::optional< int > ReadPragmaInteger(sqlite3 *db, const std::string &key, const std::string &description, bilingual_str &error)
static constexpr int32_t WALLET_SCHEMA_VERSION
static bool BindBlobToStatement(sqlite3_stmt *stmt, int index, std::span< const std::byte > blob, const std::string &description)
static int TraceSqlCallback(unsigned code, void *context, void *param1, void *param2)
static void SetPragma(sqlite3 *db, const std::string &key, const std::string &value, const std::string &err_msg)
std::string SQLiteDatabaseVersion()
static void ErrorLogCallback(void *arg, int code, const char *msg)
bool verify
Check data integrity on load.
#define AssertLockNotHeld(cs)
consteval auto _(util::TranslatedLiteral str)
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.