diff options
author | Andrew Chow <achow101-github@achow101.com> | 2022-04-11 15:14:24 -0400 |
---|---|---|
committer | Andrew Chow <github@achow101.com> | 2022-12-14 12:41:41 -0500 |
commit | 7a198bba0a1d0a0f0fd4ca947955cb52b84bdd4b (patch) | |
tree | ac500d26ed18aeb2265c814aac88158c858a9e8f /src/wallet/sqlite.cpp | |
parent | 69efbc011bb74fcd8dd9ed2a8a5d31bc9e323c10 (diff) | |
download | bitcoin-7a198bba0a1d0a0f0fd4ca947955cb52b84bdd4b.tar.xz |
wallet: Introduce DatabaseCursor RAII class for managing cursor
Instead of having DatabaseBatch deal with opening and closing database
cursors, have a separate RAII class that deals with those.
For now, DatabaseBatch manages DatabaseCursor, but this will change
later.
Diffstat (limited to 'src/wallet/sqlite.cpp')
-rw-r--r-- | src/wallet/sqlite.cpp | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index 053fb8f983..bc1b524adc 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -125,7 +125,6 @@ void SQLiteBatch::SetupSQLStatements() {&m_insert_stmt, "INSERT INTO main VALUES(?, ?)"}, {&m_overwrite_stmt, "INSERT or REPLACE into main values(?, ?)"}, {&m_delete_stmt, "DELETE FROM main WHERE key = ?"}, - {&m_cursor_stmt, "SELECT key, value FROM main"}, }; for (const auto& [stmt_prepared, stmt_text] : statements) { @@ -374,7 +373,6 @@ void SQLiteBatch::Close() {&m_insert_stmt, "insert"}, {&m_overwrite_stmt, "overwrite"}, {&m_delete_stmt, "delete"}, - {&m_cursor_stmt, "cursor"}, }; for (const auto& [stmt_prepared, stmt_description] : statements) { @@ -472,27 +470,17 @@ bool SQLiteBatch::HasKey(CDataStream&& key) return res == SQLITE_ROW; } -bool SQLiteBatch::StartCursor() -{ - assert(!m_cursor_init); - if (!m_database.m_db) return false; - m_cursor_init = true; - return true; -} - -bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& complete) +bool SQLiteCursor::Next(CDataStream& key, CDataStream& value, bool& complete) { complete = false; - if (!m_cursor_init) return false; - int res = sqlite3_step(m_cursor_stmt); if (res == SQLITE_DONE) { complete = true; return true; } if (res != SQLITE_ROW) { - LogPrintf("SQLiteBatch::ReadAtCursor: Unable to execute cursor step: %s\n", sqlite3_errstr(res)); + LogPrintf("%s: Unable to execute cursor step: %s\n", __func__, sqlite3_errstr(res)); return false; } @@ -506,10 +494,29 @@ bool SQLiteBatch::ReadAtCursor(CDataStream& key, CDataStream& value, bool& compl return true; } -void SQLiteBatch::CloseCursor() +SQLiteCursor::~SQLiteCursor() { sqlite3_reset(m_cursor_stmt); - m_cursor_init = false; + int res = sqlite3_finalize(m_cursor_stmt); + if (res != SQLITE_OK) { + LogPrintf("%s: cursor closed but could not finalize cursor statement: %s\n", + __func__, sqlite3_errstr(res)); + } +} + +std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewCursor() +{ + if (!m_database.m_db) return nullptr; + auto cursor = std::make_unique<SQLiteCursor>(); + + const char* stmt_text = "SELECT key, value FROM main"; + int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr); + if (res != SQLITE_OK) { + throw std::runtime_error(strprintf( + "%s: Failed to setup cursor SQL statement: %s\n", __func__, sqlite3_errstr(res))); + } + + return cursor; } bool SQLiteBatch::TxnBegin() |