transaction.h 3.9 KB

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