1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef SQL_TRANSACTION_H_
6 #define SQL_TRANSACTION_H_
8 #include "base/check.h"
9 #include "base/component_export.h"
10 #include "base/sequence_checker.h"
11 #include "base/thread_annotations.h"
17 // Automatically rolls back uncommitted transactions when going out of scope.
19 // This class is not thread-safe. Each instance must be used from a single
21 class COMPONENT_EXPORT(SQL) Transaction {
23 // Creates an inactive instance.
25 // `database` must be non-null and must outlive the newly created instance.
27 // The instance must be activated by calling Begin().
29 // sql::Database implements "virtual" nested transactions, as documented in
30 // sql::Database::BeginTransaction(). This is a mis-feature, and should not be
31 // used in new code. The sql::Database implementation does not match the
32 // approach recommended at https://www.sqlite.org/lang_transaction.html.
33 explicit Transaction(Database* database);
34 Transaction(const Transaction&) = delete;
35 Transaction& operator=(const Transaction&) = delete;
36 Transaction(Transaction&&) = delete;
37 Transaction& operator=(Transaction&&) = delete;
40 // Activates an inactive transaction. Must be called after construction.
42 // Returns false in case of failure. If this method fails, the database
43 // connection will still execute SQL statements, but they will not be enclosed
44 // in a transaction scope. In most cases, Begin() callers should handle
45 // failures by abandoning the high-level operation that was meant to be
46 // carried out in the transaction.
48 // In most cases (no nested transactions), this method issues a BEGIN
49 // statement, which invokes SQLite's deferred transaction startup documented
50 // in https://www.sqlite.org/lang_transaction.html. This means the database
51 // lock is not acquired by the time Begin() completes. Instead, the first
52 // statement after Begin() will attempt to acquire a read or write lock.
54 // This method is not idempotent. Calling Begin() twice on a Transaction will
55 // cause a DCHECK crash.
56 [[nodiscard]] bool Begin();
58 // Explicitly rolls back the transaction. All changes will be forgotten.
60 // Most features can avoid calling this method, because Transactions that do
61 // not get Commit()ed are automatically rolled back when they go out of scope.
63 // This method is not idempotent. Calling Rollback() twice on a Transaction
64 // will cause a DCHECK crash.
66 // Must be called after a successful call to Begin(). Must not be called after
70 // Commits the transaction. All changes will be persisted in the database.
72 // Returns false in case of failure. The most common failure case is a SQLite
73 // failure in committing the transaction. If sql::Database's support for
74 // nested transactions is in use, this method will also fail if any nested
75 // transaction has been rolled back.
77 // This method is not idempotent. Calling Commit() twice on a Transaction will
78 // cause a DCHECK crash.
80 // Must be called after a successful call to Begin(). Must not be called after
84 // True if Begin() succeeded, and neither Commit() nor Rollback() were called.
85 bool IsActiveForTesting() const {
86 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
91 SEQUENCE_CHECKER(sequence_checker_);
93 Database& database_ GUARDED_BY_CONTEXT(sequence_checker_);
96 bool begin_called_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
97 bool commit_called_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
98 bool rollback_called_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
99 #endif // DCHECK_IS_ON()
101 // True between a successful Begin() and a Commit() / Rollback() call.
102 bool is_active_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
107 #endif // SQL_TRANSACTION_H_