wallet, sqlite: Encapsulate SQLite statements in a RAII class #33033

pull achow101 wants to merge 9 commits into bitcoin:master from achow101:sqlite-stmt-raii changing 2 files +169 −177
  1. achow101 commented at 10:43 pm on July 21, 2025: member

    SQLite statements are C objects which can be long lived, so having them be initialized in a constructor, and cleanup everything in a destructor, makes the sqlite code cleaner and easier to read. This also lets us have the various functions needed to interact with sqlite statements be member functions.

    This will be particularly useful in future work which makes use of more complicated SQL statements.

  2. DrahtBot commented at 10:43 pm on July 21, 2025: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/33033.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Stale ACK w0xlt

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33034 (wallet: Store transactions in a separate sqlite table by achow101)
    • #29641 (scripted-diff: Use LogInfo over LogPrintf [WIP, NOMERGE, DRAFT] by maflcko)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  3. DrahtBot added the label CI failed on Jul 22, 2025
  4. DrahtBot commented at 2:33 am on July 22, 2025: contributor

    🚧 At least one of the CI tasks failed. Task previous releases, depends DEBUG: https://github.com/bitcoin/bitcoin/runs/46428794695 LLM reason (✨ experimental): The CI failure is caused by a static assertion failure in the sqlite.cpp file during compilation.

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

  5. achow101 force-pushed on Jul 22, 2025
  6. achow101 force-pushed on Jul 22, 2025
  7. achow101 force-pushed on Jul 22, 2025
  8. in src/wallet/sqlite.cpp:132 in 2c1edccfc5 outdated
    143+                static_cast<size_t>(sqlite3_column_bytes(m_stmt, col))
    144+            );
    145+        } else {
    146+            // GCC <= 12 and Clang <= 16 don't like static_assert(false) in an else, so we use the following to achieve the same effect
    147+            // From: https://devblogs.microsoft.com/oldnewthing/20200311-00/?p=103553
    148+            static_assert(!sizeof(T*));
    


    maflcko commented at 8:07 am on July 22, 2025:
    nit: you can use ALWAYS_FALSE for this, so that the workaround docs for the C++23 defect report are in one place only.

    achow101 commented at 5:01 pm on July 22, 2025:
    Done
  9. DrahtBot removed the label CI failed on Jul 22, 2025
  10. achow101 force-pushed on Jul 22, 2025
  11. in src/util/transaction_identifier.h:42 in 15d21068ce outdated
    35@@ -36,7 +36,10 @@ class transaction_identifier
    36     }
    37 
    38 public:
    39+    using value_type = uint256::value_type;
    40+
    41     transaction_identifier() : m_wrapped{} {}
    42+    transaction_identifier(std::span<const value_type> sp) : m_wrapped(sp) {}
    


    w0xlt commented at 9:00 pm on July 23, 2025:
    Is there any specific reason not to use unsigned char directly, like std::span<const unsigned char > sp) ?

    achow101 commented at 9:15 pm on July 23, 2025:
    In theory we could change uint256’s value_type, and we wouldn’t need to make any changes here in that case.

    maflcko commented at 7:58 am on July 24, 2025:

    I don’t understand this change. The commit message just says “util: Add value_type and span constructor to (W)Txid”, but it doesn’t say why or where this is needed. Compiling without this (locally) seems to pass.

    Also, conceptually, it seems to go in the opposite direction that we want to go in. This makes implicit construction from any byte span to transaction_identifier possible again. The constructor transaction_identifier(const uint256& wrapped) is private and will still catch those cases, but if this implementation detail is changed in the future, I presume direct and implicit construction from uint256 will be possible again.

    I think it would be good to explain this change a bit better for reviewers.


    achow101 commented at 5:40 pm on July 24, 2025:

    In SQLiteStatement::Column<T>(), one of the ways we construct the appropriate data from a blob is to do reinterpret_cast<T::value_type>. Txid met all of the requirements for using that constructor, except that it didn’t have a value_type, hence this commit adding it.

    But it looks like I didn’t include that commit in this PR. Rather, it’s https://github.com/bitcoin/bitcoin/pull/33034/commits/afe99b3b7df6c658fb4068c6418dfd7ebf151460 in #33034.


    maflcko commented at 7:50 pm on July 24, 2025:

    I see. Though, it may still be good to make this one explicit to avoid silent uint256 conversions in the future?

    Also, Txid::data is std::byte*, so value_type should probably be std::byte as well.

    I haven’t tried, but I presume both modifications should compile with afe99b3b7df6c658fb4068c6418dfd7ebf151460


    achow101 commented at 8:49 pm on July 24, 2025:
    I’ve dropped this commit from this PR and moved it to #33034. Also dropped value_type and made the constructor just take span<const std::byte> and that seems to work.
  12. w0xlt commented at 11:03 pm on July 23, 2025: contributor
  13. in src/wallet/sqlite.cpp:61 in b2c824a3ce outdated
    70-        sqlite3_reset(stmt);
    71-        return false;
    72+    T(data, size);
    73+};
    74+
    75+/** RAII class that encapsualtes a sqlite3_stmt */
    


    maflcko commented at 7:13 am on July 24, 2025:
    encapsualtes -> encapsulates [spelling error in comment “encapsualtes” makes the word misspelled]
    

    achow101 commented at 8:50 pm on July 24, 2025:
    Done
  14. achow101 force-pushed on Jul 24, 2025
  15. sqlite: Add SQLiteStatement RAII class
    This class will be used to encapsulate a sqlite3_stmt
    41b05eac91
  16. sqlite: Make Column template function 57ddadca73
  17. sqlite: Refactor ReadPragmaInteger to use SQLiteStatement 22fd72f01a
  18. sqlite: Use SQLiteStatement in PRAGMA integrity_check 1eb086bf0e
  19. sqlite: Use SQLiteStatement in check_main_stmt c5afca0361
  20. sqlite: Have SQLiteCursor store SQLiteStatement d13ffed94a
  21. sqlite: Replace remaining sqlite3_stmt usage with SQLiteStatement 0e4f5cdfeb
  22. sqlite: Refactor common writing code from WriteKey and ExecStatement
    WriteKey and ExecStatement use the same code for the actual execution of
    the statement. This is refactored into a separate function, also called
    ExecStatement, and the original ExecStatement renamed to
    ExecEraseStatement as it is only used by the erase functions.
    8ffbe413d0
  23. sqlite: Inline BindBlobToStatement and SpanFromBlob 1829b3512d
  24. achow101 force-pushed on Jul 24, 2025

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-07-26 09:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me