/Users/deen/code/yugabyte-db/src/yb/docdb/ql_rocksdb_storage.cc
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 | | #include "yb/docdb/ql_rocksdb_storage.h" |
15 | | |
16 | | #include "yb/common/pgsql_protocol.pb.h" |
17 | | #include "yb/common/ql_protocol.pb.h" |
18 | | |
19 | | #include "yb/docdb/doc_key.h" |
20 | | #include "yb/docdb/doc_rowwise_iterator.h" |
21 | | #include "yb/docdb/doc_ql_scanspec.h" |
22 | | #include "yb/docdb/primitive_value_util.h" |
23 | | |
24 | | #include "yb/util/result.h" |
25 | | |
26 | | namespace yb { |
27 | | namespace docdb { |
28 | | |
29 | | QLRocksDBStorage::QLRocksDBStorage(const DocDB& doc_db) |
30 | 276k | : doc_db_(doc_db) { |
31 | 276k | } |
32 | | |
33 | | //-------------------------------------------------------------------------------------------------- |
34 | | |
35 | | Status QLRocksDBStorage::GetIterator(const QLReadRequestPB& request, |
36 | | const Schema& projection, |
37 | | const Schema& schema, |
38 | | const TransactionOperationContext& txn_op_context, |
39 | | CoarseTimePoint deadline, |
40 | | const ReadHybridTime& read_time, |
41 | | const QLScanSpec& spec, |
42 | 7.24M | std::unique_ptr<YQLRowwiseIteratorIf> *iter) const { |
43 | | |
44 | 7.24M | auto doc_iter = std::make_unique<DocRowwiseIterator>( |
45 | 7.24M | projection, schema, txn_op_context, doc_db_, deadline, read_time); |
46 | 7.24M | RETURN_NOT_OK(doc_iter->Init(spec)); |
47 | 7.24M | *iter = std::move(doc_iter); |
48 | 7.24M | return Status::OK(); |
49 | 7.24M | } |
50 | | |
51 | | Status QLRocksDBStorage::BuildYQLScanSpec(const QLReadRequestPB& request, |
52 | | const ReadHybridTime& read_time, |
53 | | const Schema& schema, |
54 | | const bool include_static_columns, |
55 | | const Schema& static_projection, |
56 | | std::unique_ptr<QLScanSpec>* spec, |
57 | 7.27M | std::unique_ptr<QLScanSpec>* static_row_spec) const { |
58 | | // Populate dockey from QL key columns. |
59 | 7.27M | auto hash_code = request.has_hash_code() ? |
60 | 7.26M | boost::make_optional<int32_t>(request.hash_code()) : boost::none11.5k ; |
61 | 7.27M | auto max_hash_code = request.has_max_hash_code() ? |
62 | 7.18M | boost::make_optional<int32_t>(request.max_hash_code()) : boost::none93.9k ; |
63 | | |
64 | 7.27M | vector<PrimitiveValue> hashed_components; |
65 | 7.27M | RETURN_NOT_OK(QLKeyColumnValuesToPrimitiveValues( |
66 | 7.27M | request.hashed_column_values(), schema, 0, schema.num_hash_key_columns(), |
67 | 7.27M | &hashed_components)); |
68 | | |
69 | 7.27M | SubDocKey start_sub_doc_key; |
70 | | // Decode the start SubDocKey from the paging state and set scan start key and hybrid time. |
71 | 7.27M | if (request.has_paging_state() && |
72 | 7.27M | request.paging_state().has_next_row_key()35.0k && |
73 | 7.27M | !request.paging_state().next_row_key().empty()35.0k ) { |
74 | | |
75 | 750 | KeyBytes start_key_bytes(request.paging_state().next_row_key()); |
76 | 750 | RETURN_NOT_OK(start_sub_doc_key.FullyDecodeFrom(start_key_bytes.AsSlice())); |
77 | | |
78 | | // If we start the scan with a specific primary key, the normal scan spec we return below will |
79 | | // not include the static columns if any for the start key. We need to return a separate scan |
80 | | // spec to fetch those static columns. |
81 | 750 | const DocKey& start_doc_key = start_sub_doc_key.doc_key(); |
82 | 750 | if (include_static_columns && !start_doc_key.range_group().empty()0 ) { |
83 | 0 | const DocKey hashed_doc_key(start_doc_key.hash(), start_doc_key.hashed_group()); |
84 | 0 | static_row_spec->reset(new DocQLScanSpec(static_projection, hashed_doc_key, |
85 | 0 | request.query_id(), request.is_forward_scan())); |
86 | 0 | } |
87 | 7.27M | } else if (!request.is_forward_scan() && include_static_columns4.66k ) { |
88 | 3 | const DocKey hashed_doc_key(hash_code ? *hash_code : 00 , hashed_components); |
89 | 3 | static_row_spec->reset(new DocQLScanSpec(static_projection, hashed_doc_key, |
90 | 3 | request.query_id(), /* is_forward_scan = */ true)); |
91 | 3 | } |
92 | | |
93 | | // Construct the scan spec basing on the WHERE condition. |
94 | 7.27M | spec->reset(new DocQLScanSpec(schema, hash_code, max_hash_code, hashed_components, |
95 | 7.27M | request.has_where_expr() ? &request.where_expr().condition()13.7k : nullptr7.26M , |
96 | 7.27M | request.has_if_expr() ? &request.if_expr().condition()784 : nullptr7.27M , |
97 | 7.27M | request.query_id(), request.is_forward_scan(), |
98 | 7.27M | request.is_forward_scan() && include_static_columns7.25M , start_sub_doc_key.doc_key())); |
99 | 7.27M | return Status::OK(); |
100 | 7.27M | } |
101 | | |
102 | | //-------------------------------------------------------------------------------------------------- |
103 | | |
104 | | Status QLRocksDBStorage::CreateIterator(const Schema& projection, |
105 | | const Schema& schema, |
106 | | const TransactionOperationContext& txn_op_context, |
107 | | CoarseTimePoint deadline, |
108 | | const ReadHybridTime& read_time, |
109 | 0 | YQLRowwiseIteratorIf::UniPtr* iter) const { |
110 | 0 | auto doc_iter = std::make_unique<DocRowwiseIterator>( |
111 | 0 | projection, schema, txn_op_context, doc_db_, deadline, read_time); |
112 | 0 | *iter = std::move(doc_iter); |
113 | 0 | return Status::OK(); |
114 | 0 | } |
115 | | |
116 | | Status QLRocksDBStorage::InitIterator(YQLRowwiseIteratorIf* iter, |
117 | | const PgsqlReadRequestPB& request, |
118 | | const Schema& schema, |
119 | 0 | const QLValuePB& ybctid) const { |
120 | | // Populate dockey from ybctid. |
121 | 0 | DocKey range_doc_key(schema); |
122 | 0 | RETURN_NOT_OK(range_doc_key.DecodeFrom(ybctid.binary_value())); |
123 | 0 | DocRowwiseIterator *doc_iter = static_cast<DocRowwiseIterator*>(iter); |
124 | 0 | RETURN_NOT_OK(doc_iter->Init(DocPgsqlScanSpec(schema, request.stmt_id(), range_doc_key))); |
125 | 0 | return Status::OK(); |
126 | 0 | } |
127 | | |
128 | | Status QLRocksDBStorage::GetIterator(uint64 stmt_id, |
129 | | const Schema& projection, |
130 | | const Schema& schema, |
131 | | const TransactionOperationContext& txn_op_context, |
132 | | CoarseTimePoint deadline, |
133 | | const ReadHybridTime& read_time, |
134 | | const QLValuePB& ybctid, |
135 | 1.55M | YQLRowwiseIteratorIf::UniPtr* iter) const { |
136 | 1.55M | DocKey range_doc_key(schema); |
137 | 1.55M | RETURN_NOT_OK(range_doc_key.DecodeFrom(ybctid.binary_value())); |
138 | 1.55M | auto doc_iter = std::make_unique<DocRowwiseIterator>( |
139 | 1.55M | projection, schema, txn_op_context, doc_db_, deadline, read_time); |
140 | 1.55M | RETURN_NOT_OK(doc_iter->Init(DocPgsqlScanSpec(schema, stmt_id, range_doc_key))); |
141 | 1.55M | *iter = std::move(doc_iter); |
142 | 1.55M | return Status::OK(); |
143 | 1.55M | } |
144 | | |
145 | | Status QLRocksDBStorage::GetIterator(const PgsqlReadRequestPB& request, |
146 | | const Schema& projection, |
147 | | const Schema& schema, |
148 | | const TransactionOperationContext& txn_op_context, |
149 | | CoarseTimePoint deadline, |
150 | | const ReadHybridTime& read_time, |
151 | | const DocKey& start_doc_key, |
152 | 3.91M | YQLRowwiseIteratorIf::UniPtr* iter) const { |
153 | | // Populate dockey from QL key columns. |
154 | 3.91M | auto hashed_components = VERIFY_RESULT(InitKeyColumnPrimitiveValues( |
155 | 3.91M | request.partition_column_values(), schema, 0 /* start_idx */)); |
156 | | |
157 | 3.91M | auto range_components = VERIFY_RESULT(InitKeyColumnPrimitiveValues( |
158 | 3.91M | request.range_column_values(), schema, schema.num_hash_key_columns())); |
159 | | |
160 | 0 | auto doc_iter = std::make_unique<DocRowwiseIterator>( |
161 | 3.91M | projection, schema, txn_op_context, doc_db_, deadline, read_time); |
162 | | |
163 | | |
164 | 3.91M | if (range_components.size() == schema.num_range_key_columns()) { |
165 | | // Construct the scan spec basing on the RANGE condition as all range columns are specified. |
166 | 883k | RETURN_NOT_OK(doc_iter->Init(DocPgsqlScanSpec( |
167 | 883k | schema, |
168 | 883k | request.stmt_id(), |
169 | 883k | hashed_components.empty() |
170 | 883k | ? DocKey(schema, std::move(range_components)) |
171 | 883k | : DocKey(schema, |
172 | 883k | request.hash_code(), |
173 | 883k | std::move(hashed_components), |
174 | 883k | std::move(range_components)), |
175 | 883k | request.has_hash_code() ? boost::make_optional<int32_t>(request.hash_code()) |
176 | 883k | : boost::none, |
177 | 883k | request.has_max_hash_code() ? boost::make_optional<int32_t>( |
178 | 883k | request.max_hash_code()) |
179 | 883k | : boost::none, |
180 | 883k | start_doc_key, |
181 | 883k | request.is_forward_scan()))); |
182 | 3.03M | } else { |
183 | | // Construct the scan spec basing on the HASH condition. |
184 | | |
185 | 3.03M | DocKey lower_doc_key(schema); |
186 | 3.03M | if (request.has_lower_bound() |
187 | 3.03M | && schema.num_hash_key_columns() == 01.09k ) { |
188 | 101 | Slice lower_key_slice = request.lower_bound().key(); |
189 | 101 | RETURN_NOT_OK(lower_doc_key.DecodeFrom(&lower_key_slice, |
190 | 101 | DocKeyPart::kWholeDocKey, |
191 | 101 | AllowSpecial::kTrue)); |
192 | 101 | if (request.lower_bound().has_is_inclusive() |
193 | 102 | && !request.lower_bound().is_inclusive()) { |
194 | 14 | lower_doc_key.AddRangeComponent( |
195 | 14 | PrimitiveValue(docdb::ValueType::kHighest)); |
196 | 14 | } |
197 | 101 | } |
198 | | |
199 | 3.03M | DocKey upper_doc_key(schema); |
200 | 3.03M | if (request.has_upper_bound() |
201 | 3.03M | && schema.num_hash_key_columns() == 0157k ) { |
202 | 156k | Slice upper_key_slice = request.upper_bound().key(); |
203 | 156k | RETURN_NOT_OK(upper_doc_key.DecodeFrom(&upper_key_slice, |
204 | 156k | DocKeyPart::kWholeDocKey, |
205 | 156k | AllowSpecial::kTrue)); |
206 | 156k | if (request.upper_bound().has_is_inclusive() |
207 | 156k | && request.upper_bound().is_inclusive()) { |
208 | 156k | upper_doc_key.AddRangeComponent( |
209 | 156k | PrimitiveValue(docdb::ValueType::kHighest)); |
210 | 156k | } |
211 | 156k | } |
212 | | |
213 | | |
214 | 3.03M | SCHECK(!request.has_where_expr(), |
215 | 3.03M | InternalError, |
216 | 3.03M | "WHERE clause is not yet supported in docdb::pgsql"); |
217 | 3.03M | RETURN_NOT_OK(doc_iter->Init(DocPgsqlScanSpec( |
218 | 3.03M | schema, |
219 | 3.03M | request.stmt_id(), |
220 | 3.03M | hashed_components, |
221 | 3.03M | range_components, |
222 | 3.03M | request.has_condition_expr() ? &request.condition_expr().condition() : nullptr, |
223 | 3.03M | request.hash_code(), |
224 | 3.03M | request.has_max_hash_code() ? boost::make_optional<int32_t>(request.max_hash_code()) |
225 | 3.03M | : boost::none, |
226 | 3.03M | nullptr /* where_expr */, |
227 | 3.03M | start_doc_key, |
228 | 3.03M | request.is_forward_scan(), |
229 | 3.03M | lower_doc_key, |
230 | 3.03M | upper_doc_key))); |
231 | 3.03M | } |
232 | | |
233 | 3.91M | *iter = std::move(doc_iter); |
234 | 3.91M | return Status::OK(); |
235 | 3.91M | } |
236 | | |
237 | | } // namespace docdb |
238 | | } // namespace yb |