From 472d2ca98170049e0edec830e2d11c5ef23740a4 Mon Sep 17 00:00:00 2001 From: furszy Date: Mon, 15 Jan 2024 20:18:34 -0300 Subject: [PATCH] sqlite: introduce HasActiveTxn method Util function to clean up code and let us verify, in the following-up commit, that dangling, to-be-reverted db transactions cannot occur anymore. --- src/wallet/sqlite.cpp | 16 +++++++++++----- src/wallet/sqlite.h | 3 +++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/wallet/sqlite.cpp b/src/wallet/sqlite.cpp index bcb77c18f7..89bb917b52 100644 --- a/src/wallet/sqlite.cpp +++ b/src/wallet/sqlite.cpp @@ -377,6 +377,12 @@ void SQLiteDatabase::Close() m_db = nullptr; } +bool SQLiteDatabase::HasActiveTxn() +{ + // 'sqlite3_get_autocommit' returns true by default, and false if a transaction has begun and not been committed or rolled back. + return m_db && sqlite3_get_autocommit(m_db) == 0; +} + int SQliteExecHandler::Exec(SQLiteDatabase& database, const std::string& statement) { return sqlite3_exec(database.m_db, statement.data(), nullptr, nullptr, nullptr); @@ -399,8 +405,8 @@ SQLiteBatch::SQLiteBatch(SQLiteDatabase& database) void SQLiteBatch::Close() { - // If m_db is in a transaction (i.e. not in autocommit mode), then abort the transaction in progress - if (m_database.m_db && sqlite3_get_autocommit(m_database.m_db) == 0) { + // If we began a transaction, and it wasn't committed, abort the transaction in progress + if (m_database.HasActiveTxn()) { if (TxnAbort()) { LogPrintf("SQLiteBatch: Batch closed unexpectedly without the transaction being explicitly committed or aborted\n"); } else { @@ -611,7 +617,7 @@ std::unique_ptr SQLiteBatch::GetNewPrefixCursor(SpanExec(m_database, "BEGIN TRANSACTION"); if (res != SQLITE_OK) { LogPrintf("SQLiteBatch: Failed to begin the transaction\n"); @@ -621,7 +627,7 @@ bool SQLiteBatch::TxnBegin() bool SQLiteBatch::TxnCommit() { - if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false; + if (!m_database.HasActiveTxn()) return false; int res = Assert(m_exec_handler)->Exec(m_database, "COMMIT TRANSACTION"); if (res != SQLITE_OK) { LogPrintf("SQLiteBatch: Failed to commit the transaction\n"); @@ -631,7 +637,7 @@ bool SQLiteBatch::TxnCommit() bool SQLiteBatch::TxnAbort() { - if (!m_database.m_db || sqlite3_get_autocommit(m_database.m_db) != 0) return false; + if (!m_database.HasActiveTxn()) return false; int res = Assert(m_exec_handler)->Exec(m_database, "ROLLBACK TRANSACTION"); if (res != SQLITE_OK) { LogPrintf("SQLiteBatch: Failed to abort the transaction\n"); diff --git a/src/wallet/sqlite.h b/src/wallet/sqlite.h index de9ba8fd99..ad91be1064 100644 --- a/src/wallet/sqlite.h +++ b/src/wallet/sqlite.h @@ -154,6 +154,9 @@ public: /** Make a SQLiteBatch connected to this database */ std::unique_ptr MakeBatch(bool flush_on_close = true) override; + /** Return true if there is an on-going txn in this connection */ + bool HasActiveTxn(); + sqlite3* m_db{nullptr}; bool m_use_unsafe_sync; };