cursor.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright 2019 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_RECOVER_MODULE_CURSOR_H_
  5. #define SQL_RECOVER_MODULE_CURSOR_H_
  6. #include <cstddef>
  7. #include <cstdint>
  8. #include <memory>
  9. #include <utility>
  10. #include "base/check_op.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/sequence_checker.h"
  13. #include "sql/recover_module/btree.h"
  14. #include "sql/recover_module/pager.h"
  15. #include "sql/recover_module/parsing.h"
  16. #include "sql/recover_module/payload.h"
  17. #include "sql/recover_module/record.h"
  18. #include "third_party/sqlite/sqlite3.h"
  19. namespace sql {
  20. namespace recover {
  21. class VirtualTable;
  22. // Represents a virtual table cursor created by SQLite in a recovery table.
  23. //
  24. // Instances are allocated on the heap using the C++ new operator, and passed to
  25. // SQLite via pointers to the sqlite_vtab members. SQLite is responsible for
  26. // managing the instances' lifetimes. SQLite will call xClose() for every
  27. // successful xOpen().
  28. //
  29. // Instances are not thread-safe. This should be fine, as long as each SQLite
  30. // statement that reads from a virtual table is only used on one sequence. This
  31. // assumption is verified by a sequence checker.
  32. //
  33. // If it turns out that VirtualCursor needs to be thread-safe, the best solution
  34. // is to add a base::Lock to VirtualCursor, and keep all underlying classes not
  35. // thread-safe.
  36. class VirtualCursor {
  37. public:
  38. // Creates a cursor that iterates over |table|.
  39. //
  40. // |table| must outlive this instance. SQLite is trusted to call xClose() for
  41. // this cursor before calling xDestroy() / xDisconnect() for the virtual table
  42. // related to the cursor.
  43. explicit VirtualCursor(VirtualTable* table);
  44. ~VirtualCursor();
  45. VirtualCursor(const VirtualCursor&) = delete;
  46. VirtualCursor& operator=(const VirtualCursor&) = delete;
  47. // Returns the embedded SQLite virtual table cursor.
  48. //
  49. // This getter is not const because SQLite wants a non-const pointer to the
  50. // structure.
  51. sqlite3_vtab_cursor* SqliteCursor() { return &sqlite_cursor_; }
  52. // The VirtualCursor instance that embeds a given SQLite virtual table cursor.
  53. //
  54. // |sqlite_cursor| must have been returned by VirtualTable::SqliteCursor().
  55. static inline VirtualCursor* FromSqliteCursor(
  56. sqlite3_vtab_cursor* sqlite_cursor) {
  57. static_assert(std::is_standard_layout<VirtualCursor>::value,
  58. "needed for the reinterpret_cast below");
  59. static_assert(offsetof(VirtualCursor, sqlite_cursor_) == 0,
  60. "sqlite_cursor_ must be the first member of the class");
  61. VirtualCursor* result = reinterpret_cast<VirtualCursor*>(sqlite_cursor);
  62. DCHECK_EQ(sqlite_cursor, &result->sqlite_cursor_);
  63. return result;
  64. }
  65. // Seeks the cursor to the first readable row. Returns a SQLite status code.
  66. int First();
  67. // Seeks the cursor to the next row. Returns a SQLite status code.
  68. int Next();
  69. // Returns true if the cursor points to a valid row, false otherwise.
  70. bool IsValid() const {
  71. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  72. return record_reader_.IsInitialized();
  73. }
  74. // Reports a value in the record to SQLite. |column_index| is 0-based.
  75. //
  76. // Returns a SQLite error code. This method can fail can happen if a value is
  77. // stored across overflow pages, and reading one of the overflow pages results
  78. // in an I/O error.
  79. int ReadColumn(int column_index, sqlite3_context* result_context);
  80. // Returns the rowid of the current row. The cursor must point to a valid row.
  81. int64_t RowId();
  82. private:
  83. // Appends a decoder for the given page at the end of the current chain.
  84. //
  85. // No modification is performed in case of failures due to I/O errors or
  86. // database corruption.
  87. void AppendPageDecoder(int page_id);
  88. // True if the current record is acceptable given the recovery schema.
  89. bool IsAcceptableRecord();
  90. // SQLite handle for this cursor. The struct is populated and used by SQLite.
  91. sqlite3_vtab_cursor sqlite_cursor_;
  92. // The table this cursor was created for.
  93. //
  94. // Raw pointer usage is acceptable because SQLite will ensure that the
  95. // VirtualTable, which is passed around as a sqlite3_vtab*, will outlive this
  96. // cursor, which is passed around as a sqlite3_cursor*.
  97. const raw_ptr<VirtualTable> table_;
  98. // Reads database pages for this cursor.
  99. DatabasePageReader db_reader_;
  100. // Reads record payloads for this cursor.
  101. LeafPayloadReader payload_reader_;
  102. // Reads record rows for this cursor.
  103. RecordReader record_reader_;
  104. // Decoders for the current chain of inner pages.
  105. //
  106. // The current chain of pages consists of the inner page decoders here and the
  107. // decoder in |leaf_decoder_|.
  108. std::vector<std::unique_ptr<InnerPageDecoder>> inner_decoders_;
  109. // Decodes the leaf page containing records.
  110. LeafPageDecoder leaf_decoder_;
  111. SEQUENCE_CHECKER(sequence_checker_);
  112. };
  113. } // namespace recover
  114. } // namespace sql
  115. #endif // SQL_RECOVER_MODULE_CURSOR_H_