sqlite.cpp
1 // Copyright (c) 2020-2022 The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #if defined(HAVE_CONFIG_H) 6 #include <config/bitcoin-config.h> 7 #endif 8 9 #include <wallet/sqlite.h> 10 11 #include <chainparams.h> 12 #include <crypto/common.h> 13 #include <logging.h> 14 #include <sync.h> 15 #include <util/fs_helpers.h> 16 #include <util/check.h> 17 #include <util/strencodings.h> 18 #include <util/translation.h> 19 #include <wallet/db.h> 20 21 #include <sqlite3.h> 22 #include <stdint.h> 23 24 #include <optional> 25 #include <utility> 26 #include <vector> 27 28 namespace wallet { 29 static constexpr int32_t WALLET_SCHEMA_VERSION = 0; 30 31 static Span<const std::byte> SpanFromBlob(sqlite3_stmt* stmt, int col) 32 { 33 return {reinterpret_cast<const std::byte*>(sqlite3_column_blob(stmt, col)), 34 static_cast<size_t>(sqlite3_column_bytes(stmt, col))}; 35 } 36 37 static void ErrorLogCallback(void* arg, int code, const char* msg) 38 { 39 // From sqlite3_config() documentation for the SQLITE_CONFIG_LOG option: 40 // "The void pointer that is the second argument to SQLITE_CONFIG_LOG is passed through as 41 // the first parameter to the application-defined logger function whenever that function is 42 // invoked." 43 // Assert that this is the case: 44 assert(arg == nullptr); 45 LogPrintf("SQLite Error. Code: %d. Message: %s\n", code, msg); 46 } 47 48 static int TraceSqlCallback(unsigned code, void* context, void* param1, void* param2) 49 { 50 auto* db = static_cast<SQLiteDatabase*>(context); 51 if (code == SQLITE_TRACE_STMT) { 52 auto* stmt = static_cast<sqlite3_stmt*>(param1); 53 // To be conservative and avoid leaking potentially secret information 54 // in the log file, only expand statements that query the database, not 55 // statements that update the database. 56 char* expanded{sqlite3_stmt_readonly(stmt) ? sqlite3_expanded_sql(stmt) : nullptr}; 57 LogPrintf("[%s] SQLite Statement: %s\n", db->Filename(), expanded ? expanded : sqlite3_sql(stmt)); 58 if (expanded) sqlite3_free(expanded); 59 } 60 return SQLITE_OK; 61 } 62 63 static bool BindBlobToStatement(sqlite3_stmt* stmt, 64 int index, 65 Span<const std::byte> blob, 66 const std::string& description) 67 { 68 // Pass a pointer to the empty string "" below instead of passing the 69 // blob.data() pointer if the blob.data() pointer is null. Passing a null 70 // data pointer to bind_blob would cause sqlite to bind the SQL NULL value 71 // instead of the empty blob value X'', which would mess up SQL comparisons. 72 int res = sqlite3_bind_blob(stmt, index, blob.data() ? static_cast<const void*>(blob.data()) : "", blob.size(), SQLITE_STATIC); 73 if (res != SQLITE_OK) { 74 LogPrintf("Unable to bind %s to statement: %s\n", description, sqlite3_errstr(res)); 75 sqlite3_clear_bindings(stmt); 76 sqlite3_reset(stmt); 77 return false; 78 } 79 80 return true; 81 } 82 83 static std::optional<int> ReadPragmaInteger(sqlite3* db, const std::string& key, const std::string& description, bilingual_str& error) 84 { 85 std::string stmt_text = strprintf("PRAGMA %s", key); 86 sqlite3_stmt* pragma_read_stmt{nullptr}; 87 int ret = sqlite3_prepare_v2(db, stmt_text.c_str(), -1, &pragma_read_stmt, nullptr); 88 if (ret != SQLITE_OK) { 89 sqlite3_finalize(pragma_read_stmt); 90 error = Untranslated(strprintf("SQLiteDatabase: Failed to prepare the statement to fetch %s: %s", description, sqlite3_errstr(ret))); 91 return std::nullopt; 92 } 93 ret = sqlite3_step(pragma_read_stmt); 94 if (ret != SQLITE_ROW) { 95 sqlite3_finalize(pragma_read_stmt); 96 error = Untranslated(strprintf("SQLiteDatabase: Failed to fetch %s: %s", description, sqlite3_errstr(ret))); 97 return std::nullopt; 98 } 99 int result = sqlite3_column_int(pragma_read_stmt, 0); 100 sqlite3_finalize(pragma_read_stmt); 101 return result; 102 } 103 104 static void SetPragma(sqlite3* db, const std::string& key, const std::string& value, const std::string& err_msg) 105 { 106 std::string stmt_text = strprintf("PRAGMA %s = %s", key, value); 107 int ret = sqlite3_exec(db, stmt_text.c_str(), nullptr, nullptr, nullptr); 108 if (ret != SQLITE_OK) { 109 throw std::runtime_error(strprintf("SQLiteDatabase: %s: %s\n", err_msg, sqlite3_errstr(ret))); 110 } 111 } 112 113 Mutex SQLiteDatabase::g_sqlite_mutex; 114 int SQLiteDatabase::g_sqlite_count = 0; 115 116 SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, bool mock) 117 : WalletDatabase(), m_mock(mock), m_dir_path(fs::PathToString(dir_path)), m_file_path(fs::PathToString(file_path)), m_write_semaphore(1), m_use_unsafe_sync(options.use_unsafe_sync) 118 { 119 { 120 LOCK(g_sqlite_mutex); 121 LogPrintf("Using SQLite Version %s\n", SQLiteDatabaseVersion()); 122 LogPrintf("Using wallet %s\n", m_dir_path); 123 124 if (++g_sqlite_count == 1) { 125 // Setup logging 126 int ret = sqlite3_config(SQLITE_CONFIG_LOG, ErrorLogCallback, nullptr); 127 if (ret != SQLITE_OK) { 128 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to setup error log: %s\n", sqlite3_errstr(ret))); 129 } 130 // Force serialized threading mode 131 ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED); 132 if (ret != SQLITE_OK) { 133 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to configure serialized threading mode: %s\n", sqlite3_errstr(ret))); 134 } 135 } 136 int ret = sqlite3_initialize(); // This is a no-op if sqlite3 is already initialized 137 if (ret != SQLITE_OK) { 138 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to initialize SQLite: %s\n", sqlite3_errstr(ret))); 139 } 140 } 141 142 try { 143 Open(); 144 } catch (const std::runtime_error&) { 145 // If open fails, cleanup this object and rethrow the exception 146 Cleanup(); 147 throw; 148 } 149 } 150 151 void SQLiteBatch::SetupSQLStatements() 152 { 153 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{ 154 {&m_read_stmt, "SELECT value FROM main WHERE key = ?"}, 155 {&m_insert_stmt, "INSERT INTO main VALUES(?, ?)"}, 156 {&m_overwrite_stmt, "INSERT or REPLACE into main values(?, ?)"}, 157 {&m_delete_stmt, "DELETE FROM main WHERE key = ?"}, 158 {&m_delete_prefix_stmt, "DELETE FROM main WHERE instr(key, ?) = 1"}, 159 }; 160 161 for (const auto& [stmt_prepared, stmt_text] : statements) { 162 if (*stmt_prepared == nullptr) { 163 int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, stmt_prepared, nullptr); 164 if (res != SQLITE_OK) { 165 throw std::runtime_error(strprintf( 166 "SQLiteDatabase: Failed to setup SQL statements: %s\n", sqlite3_errstr(res))); 167 } 168 } 169 } 170 } 171 172 SQLiteDatabase::~SQLiteDatabase() 173 { 174 Cleanup(); 175 } 176 177 void SQLiteDatabase::Cleanup() noexcept 178 { 179 AssertLockNotHeld(g_sqlite_mutex); 180 181 Close(); 182 183 LOCK(g_sqlite_mutex); 184 if (--g_sqlite_count == 0) { 185 int ret = sqlite3_shutdown(); 186 if (ret != SQLITE_OK) { 187 LogPrintf("SQLiteDatabase: Failed to shutdown SQLite: %s\n", sqlite3_errstr(ret)); 188 } 189 } 190 } 191 192 bool SQLiteDatabase::Verify(bilingual_str& error) 193 { 194 assert(m_db); 195 196 // Check the application ID matches our network magic 197 auto read_result = ReadPragmaInteger(m_db, "application_id", "the application id", error); 198 if (!read_result.has_value()) return false; 199 uint32_t app_id = static_cast<uint32_t>(read_result.value()); 200 uint32_t net_magic = ReadBE32(Params().MessageStart().data()); 201 if (app_id != net_magic) { 202 error = strprintf(_("SQLiteDatabase: Unexpected application id. Expected %u, got %u"), net_magic, app_id); 203 return false; 204 } 205 206 // Check our schema version 207 read_result = ReadPragmaInteger(m_db, "user_version", "sqlite wallet schema version", error); 208 if (!read_result.has_value()) return false; 209 int32_t user_ver = read_result.value(); 210 if (user_ver != WALLET_SCHEMA_VERSION) { 211 error = strprintf(_("SQLiteDatabase: Unknown sqlite wallet schema version %d. Only version %d is supported"), user_ver, WALLET_SCHEMA_VERSION); 212 return false; 213 } 214 215 sqlite3_stmt* stmt{nullptr}; 216 int ret = sqlite3_prepare_v2(m_db, "PRAGMA integrity_check", -1, &stmt, nullptr); 217 if (ret != SQLITE_OK) { 218 sqlite3_finalize(stmt); 219 error = strprintf(_("SQLiteDatabase: Failed to prepare statement to verify database: %s"), sqlite3_errstr(ret)); 220 return false; 221 } 222 while (true) { 223 ret = sqlite3_step(stmt); 224 if (ret == SQLITE_DONE) { 225 break; 226 } 227 if (ret != SQLITE_ROW) { 228 error = strprintf(_("SQLiteDatabase: Failed to execute statement to verify database: %s"), sqlite3_errstr(ret)); 229 break; 230 } 231 const char* msg = (const char*)sqlite3_column_text(stmt, 0); 232 if (!msg) { 233 error = strprintf(_("SQLiteDatabase: Failed to read database verification error: %s"), sqlite3_errstr(ret)); 234 break; 235 } 236 std::string str_msg(msg); 237 if (str_msg == "ok") { 238 continue; 239 } 240 if (error.empty()) { 241 error = _("Failed to verify database") + Untranslated("\n"); 242 } 243 error += Untranslated(strprintf("%s\n", str_msg)); 244 } 245 sqlite3_finalize(stmt); 246 return error.empty(); 247 } 248 249 void SQLiteDatabase::Open() 250 { 251 int flags = SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 252 if (m_mock) { 253 flags |= SQLITE_OPEN_MEMORY; // In memory database for mock db 254 } 255 256 if (m_db == nullptr) { 257 if (!m_mock) { 258 TryCreateDirectories(fs::PathFromString(m_dir_path)); 259 } 260 int ret = sqlite3_open_v2(m_file_path.c_str(), &m_db, flags, nullptr); 261 if (ret != SQLITE_OK) { 262 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to open database: %s\n", sqlite3_errstr(ret))); 263 } 264 ret = sqlite3_extended_result_codes(m_db, 1); 265 if (ret != SQLITE_OK) { 266 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to enable extended result codes: %s\n", sqlite3_errstr(ret))); 267 } 268 // Trace SQL statements if tracing is enabled with -debug=walletdb -loglevel=walletdb:trace 269 if (LogAcceptCategory(BCLog::WALLETDB, BCLog::Level::Trace)) { 270 ret = sqlite3_trace_v2(m_db, SQLITE_TRACE_STMT, TraceSqlCallback, this); 271 if (ret != SQLITE_OK) { 272 LogPrintf("Failed to enable SQL tracing for %s\n", Filename()); 273 } 274 } 275 } 276 277 if (sqlite3_db_readonly(m_db, "main") != 0) { 278 throw std::runtime_error("SQLiteDatabase: Database opened in readonly mode but read-write permissions are needed"); 279 } 280 281 // Acquire an exclusive lock on the database 282 // First change the locking mode to exclusive 283 SetPragma(m_db, "locking_mode", "exclusive", "Unable to change database locking mode to exclusive"); 284 // Now begin a transaction to acquire the exclusive lock. This lock won't be released until we close because of the exclusive locking mode. 285 int ret = sqlite3_exec(m_db, "BEGIN EXCLUSIVE TRANSACTION", nullptr, nullptr, nullptr); 286 if (ret != SQLITE_OK) { 287 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"); 288 } 289 ret = sqlite3_exec(m_db, "COMMIT", nullptr, nullptr, nullptr); 290 if (ret != SQLITE_OK) { 291 throw std::runtime_error(strprintf("SQLiteDatabase: Unable to end exclusive lock transaction: %s\n", sqlite3_errstr(ret))); 292 } 293 294 // Enable fullfsync for the platforms that use it 295 SetPragma(m_db, "fullfsync", "true", "Failed to enable fullfsync"); 296 297 if (m_use_unsafe_sync) { 298 // Use normal synchronous mode for the journal 299 LogPrintf("WARNING SQLite is configured to not wait for data to be flushed to disk. Data loss and corruption may occur.\n"); 300 SetPragma(m_db, "synchronous", "OFF", "Failed to set synchronous mode to OFF"); 301 } 302 303 // Make the table for our key-value pairs 304 // First check that the main table exists 305 sqlite3_stmt* check_main_stmt{nullptr}; 306 ret = sqlite3_prepare_v2(m_db, "SELECT name FROM sqlite_master WHERE type='table' AND name='main'", -1, &check_main_stmt, nullptr); 307 if (ret != SQLITE_OK) { 308 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to prepare statement to check table existence: %s\n", sqlite3_errstr(ret))); 309 } 310 ret = sqlite3_step(check_main_stmt); 311 if (sqlite3_finalize(check_main_stmt) != SQLITE_OK) { 312 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to finalize statement checking table existence: %s\n", sqlite3_errstr(ret))); 313 } 314 bool table_exists; 315 if (ret == SQLITE_DONE) { 316 table_exists = false; 317 } else if (ret == SQLITE_ROW) { 318 table_exists = true; 319 } else { 320 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to execute statement to check table existence: %s\n", sqlite3_errstr(ret))); 321 } 322 323 // Do the db setup things because the table doesn't exist only when we are creating a new wallet 324 if (!table_exists) { 325 ret = sqlite3_exec(m_db, "CREATE TABLE main(key BLOB PRIMARY KEY NOT NULL, value BLOB NOT NULL)", nullptr, nullptr, nullptr); 326 if (ret != SQLITE_OK) { 327 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to create new database: %s\n", sqlite3_errstr(ret))); 328 } 329 330 // Set the application id 331 uint32_t app_id = ReadBE32(Params().MessageStart().data()); 332 SetPragma(m_db, "application_id", strprintf("%d", static_cast<int32_t>(app_id)), 333 "Failed to set the application id"); 334 335 // Set the user version 336 SetPragma(m_db, "user_version", strprintf("%d", WALLET_SCHEMA_VERSION), 337 "Failed to set the wallet schema version"); 338 } 339 } 340 341 bool SQLiteDatabase::Rewrite(const char* skip) 342 { 343 // Rewrite the database using the VACUUM command: https://sqlite.org/lang_vacuum.html 344 int ret = sqlite3_exec(m_db, "VACUUM", nullptr, nullptr, nullptr); 345 return ret == SQLITE_OK; 346 } 347 348 bool SQLiteDatabase::Backup(const std::string& dest) const 349 { 350 sqlite3* db_copy; 351 int res = sqlite3_open(dest.c_str(), &db_copy); 352 if (res != SQLITE_OK) { 353 sqlite3_close(db_copy); 354 return false; 355 } 356 sqlite3_backup* backup = sqlite3_backup_init(db_copy, "main", m_db, "main"); 357 if (!backup) { 358 LogPrintf("%s: Unable to begin backup: %s\n", __func__, sqlite3_errmsg(m_db)); 359 sqlite3_close(db_copy); 360 return false; 361 } 362 // Specifying -1 will copy all of the pages 363 res = sqlite3_backup_step(backup, -1); 364 if (res != SQLITE_DONE) { 365 LogPrintf("%s: Unable to backup: %s\n", __func__, sqlite3_errstr(res)); 366 sqlite3_backup_finish(backup); 367 sqlite3_close(db_copy); 368 return false; 369 } 370 res = sqlite3_backup_finish(backup); 371 sqlite3_close(db_copy); 372 return res == SQLITE_OK; 373 } 374 375 void SQLiteDatabase::Close() 376 { 377 int res = sqlite3_close(m_db); 378 if (res != SQLITE_OK) { 379 throw std::runtime_error(strprintf("SQLiteDatabase: Failed to close database: %s\n", sqlite3_errstr(res))); 380 } 381 m_db = nullptr; 382 } 383 384 bool SQLiteDatabase::HasActiveTxn() 385 { 386 // 'sqlite3_get_autocommit' returns true by default, and false if a transaction has begun and not been committed or rolled back. 387 return m_db && sqlite3_get_autocommit(m_db) == 0; 388 } 389 390 int SQliteExecHandler::Exec(SQLiteDatabase& database, const std::string& statement) 391 { 392 return sqlite3_exec(database.m_db, statement.data(), nullptr, nullptr, nullptr); 393 } 394 395 std::unique_ptr<DatabaseBatch> SQLiteDatabase::MakeBatch(bool flush_on_close) 396 { 397 // We ignore flush_on_close because we don't do manual flushing for SQLite 398 return std::make_unique<SQLiteBatch>(*this); 399 } 400 401 SQLiteBatch::SQLiteBatch(SQLiteDatabase& database) 402 : m_database(database) 403 { 404 // Make sure we have a db handle 405 assert(m_database.m_db); 406 407 SetupSQLStatements(); 408 } 409 410 void SQLiteBatch::Close() 411 { 412 bool force_conn_refresh = false; 413 414 // If we began a transaction, and it wasn't committed, abort the transaction in progress 415 if (m_txn) { 416 if (TxnAbort()) { 417 LogPrintf("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n"); 418 } else { 419 // If transaction cannot be aborted, it means there is a bug or there has been data corruption. Try to recover in this case 420 // by closing and reopening the database. Closing the database should also ensure that any changes made since the transaction 421 // was opened will be rolled back and future transactions can succeed without committing old data. 422 force_conn_refresh = true; 423 LogPrintf("SQLiteBatch: Batch closed and failed to abort transaction, resetting db connection..\n"); 424 } 425 } 426 427 // Free all of the prepared statements 428 const std::vector<std::pair<sqlite3_stmt**, const char*>> statements{ 429 {&m_read_stmt, "read"}, 430 {&m_insert_stmt, "insert"}, 431 {&m_overwrite_stmt, "overwrite"}, 432 {&m_delete_stmt, "delete"}, 433 {&m_delete_prefix_stmt, "delete prefix"}, 434 }; 435 436 for (const auto& [stmt_prepared, stmt_description] : statements) { 437 int res = sqlite3_finalize(*stmt_prepared); 438 if (res != SQLITE_OK) { 439 LogPrintf("SQLiteBatch: Batch closed but could not finalize %s statement: %s\n", 440 stmt_description, sqlite3_errstr(res)); 441 } 442 *stmt_prepared = nullptr; 443 } 444 445 if (force_conn_refresh) { 446 m_database.Close(); 447 try { 448 m_database.Open(); 449 // If TxnAbort failed and we refreshed the connection, the semaphore was not released, so release it here to avoid deadlocks on future writes. 450 m_database.m_write_semaphore.post(); 451 } catch (const std::runtime_error&) { 452 // If open fails, cleanup this object and rethrow the exception 453 m_database.Close(); 454 throw; 455 } 456 } 457 } 458 459 bool SQLiteBatch::ReadKey(DataStream&& key, DataStream& value) 460 { 461 if (!m_database.m_db) return false; 462 assert(m_read_stmt); 463 464 // Bind: leftmost parameter in statement is index 1 465 if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false; 466 int res = sqlite3_step(m_read_stmt); 467 if (res != SQLITE_ROW) { 468 if (res != SQLITE_DONE) { 469 // SQLITE_DONE means "not found", don't log an error in that case. 470 LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res)); 471 } 472 sqlite3_clear_bindings(m_read_stmt); 473 sqlite3_reset(m_read_stmt); 474 return false; 475 } 476 // Leftmost column in result is index 0 477 value.clear(); 478 value.write(SpanFromBlob(m_read_stmt, 0)); 479 480 sqlite3_clear_bindings(m_read_stmt); 481 sqlite3_reset(m_read_stmt); 482 return true; 483 } 484 485 bool SQLiteBatch::WriteKey(DataStream&& key, DataStream&& value, bool overwrite) 486 { 487 if (!m_database.m_db) return false; 488 assert(m_insert_stmt && m_overwrite_stmt); 489 490 sqlite3_stmt* stmt; 491 if (overwrite) { 492 stmt = m_overwrite_stmt; 493 } else { 494 stmt = m_insert_stmt; 495 } 496 497 // Bind: leftmost parameter in statement is index 1 498 // Insert index 1 is key, 2 is value 499 if (!BindBlobToStatement(stmt, 1, key, "key")) return false; 500 if (!BindBlobToStatement(stmt, 2, value, "value")) return false; 501 502 // Acquire semaphore if not previously acquired when creating a transaction. 503 if (!m_txn) m_database.m_write_semaphore.wait(); 504 505 // Execute 506 int res = sqlite3_step(stmt); 507 sqlite3_clear_bindings(stmt); 508 sqlite3_reset(stmt); 509 if (res != SQLITE_DONE) { 510 LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res)); 511 } 512 513 if (!m_txn) m_database.m_write_semaphore.post(); 514 515 return res == SQLITE_DONE; 516 } 517 518 bool SQLiteBatch::ExecStatement(sqlite3_stmt* stmt, Span<const std::byte> blob) 519 { 520 if (!m_database.m_db) return false; 521 assert(stmt); 522 523 // Bind: leftmost parameter in statement is index 1 524 if (!BindBlobToStatement(stmt, 1, blob, "key")) return false; 525 526 // Acquire semaphore if not previously acquired when creating a transaction. 527 if (!m_txn) m_database.m_write_semaphore.wait(); 528 529 // Execute 530 int res = sqlite3_step(stmt); 531 sqlite3_clear_bindings(stmt); 532 sqlite3_reset(stmt); 533 if (res != SQLITE_DONE) { 534 LogPrintf("%s: Unable to execute statement: %s\n", __func__, sqlite3_errstr(res)); 535 } 536 537 if (!m_txn) m_database.m_write_semaphore.post(); 538 539 return res == SQLITE_DONE; 540 } 541 542 bool SQLiteBatch::EraseKey(DataStream&& key) 543 { 544 return ExecStatement(m_delete_stmt, key); 545 } 546 547 bool SQLiteBatch::ErasePrefix(Span<const std::byte> prefix) 548 { 549 return ExecStatement(m_delete_prefix_stmt, prefix); 550 } 551 552 bool SQLiteBatch::HasKey(DataStream&& key) 553 { 554 if (!m_database.m_db) return false; 555 assert(m_read_stmt); 556 557 // Bind: leftmost parameter in statement is index 1 558 if (!BindBlobToStatement(m_read_stmt, 1, key, "key")) return false; 559 int res = sqlite3_step(m_read_stmt); 560 sqlite3_clear_bindings(m_read_stmt); 561 sqlite3_reset(m_read_stmt); 562 return res == SQLITE_ROW; 563 } 564 565 DatabaseCursor::Status SQLiteCursor::Next(DataStream& key, DataStream& value) 566 { 567 int res = sqlite3_step(m_cursor_stmt); 568 if (res == SQLITE_DONE) { 569 return Status::DONE; 570 } 571 if (res != SQLITE_ROW) { 572 LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res)); 573 return Status::FAIL; 574 } 575 576 key.clear(); 577 value.clear(); 578 579 // Leftmost column in result is index 0 580 key.write(SpanFromBlob(m_cursor_stmt, 0)); 581 value.write(SpanFromBlob(m_cursor_stmt, 1)); 582 return Status::MORE; 583 } 584 585 SQLiteCursor::~SQLiteCursor() 586 { 587 sqlite3_clear_bindings(m_cursor_stmt); 588 sqlite3_reset(m_cursor_stmt); 589 int res = sqlite3_finalize(m_cursor_stmt); 590 if (res != SQLITE_OK) { 591 LogPrintf("%s: cursor closed but could not finalize cursor statement: %s\n", 592 __func__, sqlite3_errstr(res)); 593 } 594 } 595 596 std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewCursor() 597 { 598 if (!m_database.m_db) return nullptr; 599 auto cursor = std::make_unique<SQLiteCursor>(); 600 601 const char* stmt_text = "SELECT key, value FROM main"; 602 int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr); 603 if (res != SQLITE_OK) { 604 throw std::runtime_error(strprintf( 605 "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res))); 606 } 607 608 return cursor; 609 } 610 611 std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewPrefixCursor(Span<const std::byte> prefix) 612 { 613 if (!m_database.m_db) return nullptr; 614 615 // To get just the records we want, the SQL statement does a comparison of the binary data 616 // where the data must be greater than or equal to the prefix, and less than 617 // the prefix incremented by one (when interpreted as an integer) 618 std::vector<std::byte> start_range(prefix.begin(), prefix.end()); 619 std::vector<std::byte> end_range(prefix.begin(), prefix.end()); 620 auto it = end_range.rbegin(); 621 for (; it != end_range.rend(); ++it) { 622 if (*it == std::byte(std::numeric_limits<unsigned char>::max())) { 623 *it = std::byte(0); 624 continue; 625 } 626 *it = std::byte(std::to_integer<unsigned char>(*it) + 1); 627 break; 628 } 629 if (it == end_range.rend()) { 630 // If the prefix is all 0xff bytes, clear end_range as we won't need it 631 end_range.clear(); 632 } 633 634 auto cursor = std::make_unique<SQLiteCursor>(start_range, end_range); 635 if (!cursor) return nullptr; 636 637 const char* stmt_text = end_range.empty() ? "SELECT key, value FROM main WHERE key >= ?" : 638 "SELECT key, value FROM main WHERE key >= ? AND key < ?"; 639 int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr); 640 if (res != SQLITE_OK) { 641 throw std::runtime_error(strprintf( 642 "SQLiteDatabase: Failed to setup cursor SQL statement: %s\n", sqlite3_errstr(res))); 643 } 644 645 if (!BindBlobToStatement(cursor->m_cursor_stmt, 1, cursor->m_prefix_range_start, "prefix_start")) return nullptr; 646 if (!end_range.empty()) { 647 if (!BindBlobToStatement(cursor->m_cursor_stmt, 2, cursor->m_prefix_range_end, "prefix_end")) return nullptr; 648 } 649 650 return cursor; 651 } 652 653 bool SQLiteBatch::TxnBegin() 654 { 655 if (!m_database.m_db || m_txn) return false; 656 m_database.m_write_semaphore.wait(); 657 Assert(!m_database.HasActiveTxn()); 658 int res = Assert(m_exec_handler)->Exec(m_database, "BEGIN TRANSACTION"); 659 if (res != SQLITE_OK) { 660 LogPrintf("SQLiteBatch: Failed to begin the transaction\n"); 661 m_database.m_write_semaphore.post(); 662 } else { 663 m_txn = true; 664 } 665 return res == SQLITE_OK; 666 } 667 668 bool SQLiteBatch::TxnCommit() 669 { 670 if (!m_database.m_db || !m_txn) return false; 671 Assert(m_database.HasActiveTxn()); 672 int res = Assert(m_exec_handler)->Exec(m_database, "COMMIT TRANSACTION"); 673 if (res != SQLITE_OK) { 674 LogPrintf("SQLiteBatch: Failed to commit the transaction\n"); 675 } else { 676 m_txn = false; 677 m_database.m_write_semaphore.post(); 678 } 679 return res == SQLITE_OK; 680 } 681 682 bool SQLiteBatch::TxnAbort() 683 { 684 if (!m_database.m_db || !m_txn) return false; 685 Assert(m_database.HasActiveTxn()); 686 int res = Assert(m_exec_handler)->Exec(m_database, "ROLLBACK TRANSACTION"); 687 if (res != SQLITE_OK) { 688 LogPrintf("SQLiteBatch: Failed to abort the transaction\n"); 689 } else { 690 m_txn = false; 691 m_database.m_write_semaphore.post(); 692 } 693 return res == SQLITE_OK; 694 } 695 696 std::unique_ptr<SQLiteDatabase> MakeSQLiteDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error) 697 { 698 try { 699 fs::path data_file = SQLiteDataFile(path); 700 auto db = std::make_unique<SQLiteDatabase>(data_file.parent_path(), data_file, options); 701 if (options.verify && !db->Verify(error)) { 702 status = DatabaseStatus::FAILED_VERIFY; 703 return nullptr; 704 } 705 status = DatabaseStatus::SUCCESS; 706 return db; 707 } catch (const std::runtime_error& e) { 708 status = DatabaseStatus::FAILED_LOAD; 709 error = Untranslated(e.what()); 710 return nullptr; 711 } 712 } 713 714 std::string SQLiteDatabaseVersion() 715 { 716 return std::string(sqlite3_libversion()); 717 } 718 } // namespace wallet