/Users/deen/code/yugabyte-db/src/yb/docdb/doc_rowwise_iterator.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #ifndef YB_DOCDB_DOC_ROWWISE_ITERATOR_H_ |
15 | | #define YB_DOCDB_DOC_ROWWISE_ITERATOR_H_ |
16 | | |
17 | | #include <string> |
18 | | #include <atomic> |
19 | | |
20 | | #include "yb/docdb/doc_reader.h" |
21 | | #include "yb/rocksdb/db.h" |
22 | | |
23 | | #include "yb/common/hybrid_time.h" |
24 | | #include "yb/common/ql_scanspec.h" |
25 | | #include "yb/common/read_hybrid_time.h" |
26 | | #include "yb/common/schema.h" |
27 | | |
28 | | #include "yb/docdb/doc_pgsql_scanspec.h" |
29 | | #include "yb/docdb/doc_ql_scanspec.h" |
30 | | #include "yb/docdb/key_bounds.h" |
31 | | #include "yb/docdb/ql_rowwise_iterator_interface.h" |
32 | | #include "yb/docdb/subdocument.h" |
33 | | #include "yb/docdb/value.h" |
34 | | |
35 | | #include "yb/util/status_fwd.h" |
36 | | #include "yb/util/operation_counter.h" |
37 | | |
38 | | namespace yb { |
39 | | namespace docdb { |
40 | | |
41 | | class IntentAwareIterator; |
42 | | class ScanChoices; |
43 | | |
44 | | // An SQL-mapped-to-document-DB iterator. |
45 | | class DocRowwiseIterator : public YQLRowwiseIteratorIf { |
46 | | public: |
47 | | DocRowwiseIterator(const Schema &projection, |
48 | | const Schema &schema, |
49 | | const TransactionOperationContext& txn_op_context, |
50 | | const DocDB& doc_db, |
51 | | CoarseTimePoint deadline, |
52 | | const ReadHybridTime& read_time, |
53 | | RWOperationCounter* pending_op_counter = nullptr); |
54 | | |
55 | | DocRowwiseIterator(std::unique_ptr<Schema> projection, |
56 | | const Schema &schema, |
57 | | const TransactionOperationContext& txn_op_context, |
58 | | const DocDB& doc_db, |
59 | | CoarseTimePoint deadline, |
60 | | const ReadHybridTime& read_time, |
61 | | RWOperationCounter* pending_op_counter = nullptr) |
62 | | : DocRowwiseIterator( |
63 | | *projection, schema, txn_op_context, doc_db, deadline, read_time, |
64 | 132k | pending_op_counter) { |
65 | 132k | projection_owner_ = std::move(projection); |
66 | 132k | } Unexecuted instantiation: _ZN2yb5docdb18DocRowwiseIteratorC2ENSt3__110unique_ptrINS_6SchemaENS2_14default_deleteIS4_EEEERKS4_RKNS_27TransactionOperationContextERKNS0_5DocDBENS2_6chrono10time_pointINS_15CoarseMonoClockENSG_8durationIxNS2_5ratioILl1ELl1000000000EEEEEEERKNS_14ReadHybridTimeEPNS_18RWOperationCounterE _ZN2yb5docdb18DocRowwiseIteratorC1ENSt3__110unique_ptrINS_6SchemaENS2_14default_deleteIS4_EEEERKS4_RKNS_27TransactionOperationContextERKNS0_5DocDBENS2_6chrono10time_pointINS_15CoarseMonoClockENSG_8durationIxNS2_5ratioILl1ELl1000000000EEEEEEERKNS_14ReadHybridTimeEPNS_18RWOperationCounterE Line | Count | Source | 64 | 132k | pending_op_counter) { | 65 | 132k | projection_owner_ = std::move(projection); | 66 | 132k | } |
|
67 | | |
68 | | virtual ~DocRowwiseIterator(); |
69 | | |
70 | | // Init scan iterator. |
71 | | CHECKED_STATUS Init(TableType table_type, const Slice& sub_doc_key = Slice()); |
72 | | // Init QL read scan. |
73 | | CHECKED_STATUS Init(const QLScanSpec& spec); |
74 | | CHECKED_STATUS Init(const PgsqlScanSpec& spec); |
75 | | |
76 | | // This must always be called before NextRow. The implementation actually finds the |
77 | | // first row to scan, and NextRow expects the RocksDB iterator to already be properly |
78 | | // positioned. |
79 | | Result<bool> HasNext() const override; |
80 | | |
81 | | std::string ToString() const override; |
82 | | |
83 | 3.68M | const Schema& schema() const override { |
84 | | // Note: this is the schema only for the columns in the projection, not all columns. |
85 | 3.68M | return projection_; |
86 | 3.68M | } |
87 | | |
88 | | // Is the next row to read a row with a static column? |
89 | | bool IsNextStaticColumn() const override; |
90 | | |
91 | 159 | const Slice& row_key() const { |
92 | 159 | return row_key_; |
93 | 159 | } |
94 | | |
95 | | // Check if liveness column exists. Should be called only after HasNext() has been called to |
96 | | // verify the row exists. |
97 | | bool LivenessColumnExists() const; |
98 | | |
99 | | // Skip the current row. |
100 | | void SkipRow() override; |
101 | | |
102 | | HybridTime RestartReadHt() override; |
103 | | |
104 | | // Returns the tuple id of the current tuple. The tuple id returned is the serialized DocKey |
105 | | // and without the cotable id. |
106 | | Result<Slice> GetTupleId() const override; |
107 | | |
108 | | // Seeks to the given tuple by its id. The tuple id should be the serialized DocKey and without |
109 | | // the cotable id. |
110 | | Result<bool> SeekTuple(const Slice& tuple_id) override; |
111 | | |
112 | | // Retrieves the next key to read after the iterator finishes for the given page. |
113 | | CHECKED_STATUS GetNextReadSubDocKey(SubDocKey* sub_doc_key) const override; |
114 | | |
115 | 0 | void set_debug_dump(bool value) { |
116 | 0 | debug_dump_ = value; |
117 | 0 | } |
118 | | |
119 | | private: |
120 | | template <class T> |
121 | | CHECKED_STATUS DoInit(const T& spec); |
122 | | |
123 | | Result<bool> InitScanChoices( |
124 | | const DocQLScanSpec& doc_spec, const KeyBytes& lower_doc_key, const KeyBytes& upper_doc_key); |
125 | | |
126 | | Result<bool> InitScanChoices( |
127 | | const DocPgsqlScanSpec& doc_spec, const KeyBytes& lower_doc_key, |
128 | | const KeyBytes& upper_doc_key); |
129 | | |
130 | | // Get the non-key column values of a QL row. |
131 | | CHECKED_STATUS GetValues(const Schema& projection, vector<SubDocument>* values); |
132 | | |
133 | | // Processes a value for a column(subdoc_key) and determines if the value is valid or not based on |
134 | | // the hybrid time of subdoc_key. If valid, it is added to the values vector and is_null is set |
135 | | // to false. Otherwise, is_null is set to true. |
136 | | CHECKED_STATUS ProcessValues(const Value& value, const SubDocKey& subdoc_key, |
137 | | vector<PrimitiveValue>* values, |
138 | | bool *is_null) const; |
139 | | |
140 | | // Figures out whether the current sub_doc_key with the given top_level_value is a valid column |
141 | | // that has not expired. Sets column_found to true if this is a valid column, false otherwise. |
142 | | CHECKED_STATUS FindValidColumn(bool* column_found) const; |
143 | | |
144 | | // Figures out whether we have a valid column present indicating the existence of the row. |
145 | | // Sets column_found to true if a valid column is found, false otherwise. |
146 | | CHECKED_STATUS ProcessColumnsForHasNext(bool* column_found) const; |
147 | | |
148 | | // Verifies whether or not the column pointed to by subdoc_key is deleted by the current |
149 | | // row_delete_marker_key_. |
150 | | bool IsDeletedByRowDeletion(const SubDocKey& subdoc_key) const; |
151 | | |
152 | | // Given a subdoc_key pointing to a column and its associated value, determine whether or not |
153 | | // the column is valid based on TTL expiry, row level delete markers and column delete markers |
154 | | CHECKED_STATUS CheckColumnValidity(const SubDocKey& subdoc_key, |
155 | | const Value& value, |
156 | | bool* is_valid) const; |
157 | | |
158 | | // For reverse scans, moves the iterator to the first kv-pair of the previous row after having |
159 | | // constructed the current row. For forward scans nothing is necessary because GetSubDocument |
160 | | // ensures that the iterator will be positioned on the first kv-pair of the next row. |
161 | | CHECKED_STATUS AdvanceIteratorToNextDesiredRow() const; |
162 | | |
163 | | // Read next row into a value map using the specified projection. |
164 | | CHECKED_STATUS DoNextRow(const Schema& projection, QLTableRow* table_row) override; |
165 | | |
166 | | const Schema& projection_; |
167 | | // Used to maintain ownership of projection_. |
168 | | // Separate field is used since ownership could be optional. |
169 | | std::unique_ptr<Schema> projection_owner_; |
170 | | |
171 | | // The schema for all columns, not just the columns we're scanning. |
172 | | const Schema& schema_; |
173 | | |
174 | | const TransactionOperationContext txn_op_context_; |
175 | | |
176 | | bool is_forward_scan_ = true; |
177 | | |
178 | | const CoarseTimePoint deadline_; |
179 | | |
180 | | const ReadHybridTime read_time_; |
181 | | |
182 | | const DocDB doc_db_; |
183 | | |
184 | | // A copy of the bound key of the end of the scan range (if any). We stop scan if iterator |
185 | | // reaches this point. This is exclusive bound for forward scans and inclusive bound for |
186 | | // reverse scans. |
187 | | bool has_bound_key_; |
188 | | KeyBytes bound_key_; |
189 | | |
190 | | std::unique_ptr<ScanChoices> scan_choices_; |
191 | | std::unique_ptr<IntentAwareIterator> db_iter_; |
192 | | |
193 | | // We keep the "pending operation" counter incremented for the lifetime of this iterator so that |
194 | | // RocksDB does not get destroyed while the iterator is still in use. |
195 | | ScopedRWOperation pending_op_; |
196 | | |
197 | | // The mutable fields that follow are modified by HasNext, a const method. |
198 | | |
199 | | // Indicates whether we've already finished iterating. |
200 | | mutable bool done_; |
201 | | |
202 | | // HasNext constructs the whole row's SubDocument. |
203 | | mutable SubDocument row_; |
204 | | |
205 | | // The current row's primary key. It is set to lower bound in the beginning. |
206 | | mutable Slice row_key_; |
207 | | |
208 | | // The current row's hash part of primary key. |
209 | | mutable Slice row_hash_key_; |
210 | | |
211 | | // The current row's iterator key. |
212 | | mutable KeyBytes iter_key_; |
213 | | |
214 | | // When HasNext constructs a row, row_ready_ is set to true. |
215 | | // When NextRow consumes the row, this variable is set to false. |
216 | | // It is initialized to false, to make sure first HasNext constructs a new row. |
217 | | mutable bool row_ready_; |
218 | | |
219 | | mutable std::vector<PrimitiveValue> projection_subkeys_; |
220 | | |
221 | | // Used for keeping track of errors in HasNext. |
222 | | mutable Status has_next_status_; |
223 | | |
224 | | // Key for seeking a YSQL tuple. Used only when the table has a cotable id. |
225 | | boost::optional<KeyBytes> tuple_key_; |
226 | | |
227 | | mutable std::unique_ptr<DocDBTableReader> doc_reader_ = nullptr; |
228 | | |
229 | | mutable bool ignore_ttl_ = false; |
230 | | |
231 | | bool debug_dump_ = false; |
232 | | }; |
233 | | |
234 | | } // namespace docdb |
235 | | } // namespace yb |
236 | | |
237 | | #endif // YB_DOCDB_DOC_ROWWISE_ITERATOR_H_ |