/Users/deen/code/yugabyte-db/src/yb/client/ql-dml-test-base.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | |
16 | | #include "yb/client/ql-dml-test-base.h" |
17 | | |
18 | | #include "yb/bfql/gen_opcodes.h" |
19 | | |
20 | | #include "yb/client/client.h" |
21 | | #include "yb/client/error.h" |
22 | | #include "yb/client/schema.h" |
23 | | #include "yb/client/session.h" |
24 | | #include "yb/client/table.h" |
25 | | #include "yb/client/table_creator.h" |
26 | | #include "yb/client/yb_op.h" |
27 | | |
28 | | #include "yb/common/ql_name.h" |
29 | | #include "yb/common/ql_value.h" |
30 | | #include "yb/common/partition.h" |
31 | | #include "yb/common/schema.h" |
32 | | |
33 | | #include "yb/gutil/casts.h" |
34 | | |
35 | | #include "yb/integration-tests/external_mini_cluster.h" |
36 | | |
37 | | #include "yb/server/clock.h" |
38 | | |
39 | | #include "yb/util/atomic.h" |
40 | | #include "yb/util/format.h" |
41 | | #include "yb/util/status_format.h" |
42 | | #include "yb/util/tsan_util.h" |
43 | | |
44 | | #include "yb/yql/cql/ql/util/errcodes.h" |
45 | | #include "yb/yql/cql/ql/util/statement_result.h" |
46 | | |
47 | | DECLARE_bool(enable_ysql); |
48 | | |
49 | | using namespace std::literals; |
50 | | |
51 | | namespace yb { |
52 | | |
53 | | namespace ql { |
54 | | |
55 | | extern ErrorCode QLStatusToErrorCode(QLResponsePB::QLStatus status); // TODO |
56 | | |
57 | | } |
58 | | |
59 | | namespace client { |
60 | | |
61 | | const client::YBTableName kTableName(YQL_DATABASE_CQL, "my_keyspace", "ql_client_test_table"); |
62 | | |
63 | | template<class MiniClusterType> |
64 | | const std::string KeyValueTableTest<MiniClusterType>::kKeyColumn = kv_table_test::kKeyColumn; |
65 | | |
66 | | template<class MiniClusterType> |
67 | | const std::string KeyValueTableTest<MiniClusterType>::kValueColumn = kv_table_test::kValueColumn; |
68 | | |
69 | | template <> |
70 | | QLDmlTestBase<MiniCluster>::QLDmlTestBase() |
71 | | : mini_cluster_opt_(MiniClusterOptions { |
72 | | .num_masters = 1, |
73 | | .num_tablet_servers = 3, |
74 | | .num_drives = 1, |
75 | | .master_env = env_.get(), |
76 | 204 | }) {} |
77 | | |
78 | | template <> |
79 | 8 | QLDmlTestBase<ExternalMiniCluster>::QLDmlTestBase() { |
80 | 8 | mini_cluster_opt_.num_masters = 1; |
81 | 8 | mini_cluster_opt_.num_tablet_servers = 3; |
82 | 8 | } |
83 | | |
84 | | template<> |
85 | 204 | void QLDmlTestBase<MiniCluster>::SetFlags() { |
86 | 204 | SetAtomicFlag(false, &FLAGS_enable_ysql); |
87 | 204 | } |
88 | | |
89 | | template<> |
90 | 8 | void QLDmlTestBase<ExternalMiniCluster>::SetFlags() { |
91 | | // TODO -- set FLAGS_enable_ysql to false. |
92 | 8 | } |
93 | | |
94 | | template <> |
95 | 204 | void QLDmlTestBase<MiniCluster>::StartCluster() { |
96 | 204 | cluster_.reset(new MiniCluster(mini_cluster_opt_)); |
97 | 204 | ASSERT_OK(cluster_->Start()); |
98 | 204 | } |
99 | | |
100 | | template <> |
101 | 8 | void QLDmlTestBase<ExternalMiniCluster>::StartCluster() { |
102 | 8 | cluster_.reset(new ExternalMiniCluster(mini_cluster_opt_)); |
103 | 8 | ASSERT_OK(cluster_->Start()); |
104 | 8 | } |
105 | | |
106 | | template<class MiniClusterType> |
107 | 212 | void QLDmlTestBase<MiniClusterType>::SetUp() { |
108 | 212 | SetFlags(); |
109 | 212 | HybridTime::TEST_SetPrettyToString(true); |
110 | | |
111 | 212 | YBMiniClusterTestBase<MiniClusterType>::SetUp(); |
112 | | |
113 | | // Start minicluster and wait for tablet servers to connect to master. |
114 | 212 | StartCluster(); |
115 | | |
116 | 212 | ASSERT_OK(this->CreateClient()); |
117 | | |
118 | | // Create test namespace. |
119 | 8 | ASSERT_OK(client_->CreateNamespaceIfNotExists(kTableName.namespace_name(), |
120 | 8 | kTableName.namespace_type())); |
121 | 8 | } _ZN2yb6client13QLDmlTestBaseINS_11MiniClusterEE5SetUpEv Line | Count | Source | 107 | 204 | void QLDmlTestBase<MiniClusterType>::SetUp() { | 108 | 204 | SetFlags(); | 109 | 204 | HybridTime::TEST_SetPrettyToString(true); | 110 | | | 111 | 204 | YBMiniClusterTestBase<MiniClusterType>::SetUp(); | 112 | | | 113 | | // Start minicluster and wait for tablet servers to connect to master. | 114 | 204 | StartCluster(); | 115 | | | 116 | 204 | ASSERT_OK(this->CreateClient()); | 117 | | | 118 | | // Create test namespace. | 119 | 0 | ASSERT_OK(client_->CreateNamespaceIfNotExists(kTableName.namespace_name(), | 120 | 0 | kTableName.namespace_type())); | 121 | 0 | } |
_ZN2yb6client13QLDmlTestBaseINS_19ExternalMiniClusterEE5SetUpEv Line | Count | Source | 107 | 8 | void QLDmlTestBase<MiniClusterType>::SetUp() { | 108 | 8 | SetFlags(); | 109 | 8 | HybridTime::TEST_SetPrettyToString(true); | 110 | | | 111 | 8 | YBMiniClusterTestBase<MiniClusterType>::SetUp(); | 112 | | | 113 | | // Start minicluster and wait for tablet servers to connect to master. | 114 | 8 | StartCluster(); | 115 | | | 116 | 8 | ASSERT_OK(this->CreateClient()); | 117 | | | 118 | | // Create test namespace. | 119 | 8 | ASSERT_OK(client_->CreateNamespaceIfNotExists(kTableName.namespace_name(), | 120 | 8 | kTableName.namespace_type())); | 121 | 8 | } |
|
122 | | |
123 | | template <class MiniClusterType> |
124 | 31 | void QLDmlTestBase<MiniClusterType>::DoTearDown() { |
125 | | // If we enable this, it will break FLAGS_mini_cluster_reuse_data |
126 | | // |
127 | | // This DeleteTable clean up seems to cause a crash because the delete may not succeed |
128 | | // immediately and is retried after the master is restarted (see ENG-663). So disable it for |
129 | | // now. |
130 | | // |
131 | | // if (table_) { |
132 | | // ASSERT_OK(client_->DeleteTable(kTableName)); |
133 | | // } |
134 | 31 | MiniClusterTestWithClient<MiniClusterType>::DoTearDown(); |
135 | 31 | } _ZN2yb6client13QLDmlTestBaseINS_11MiniClusterEE10DoTearDownEv Line | Count | Source | 124 | 24 | void QLDmlTestBase<MiniClusterType>::DoTearDown() { | 125 | | // If we enable this, it will break FLAGS_mini_cluster_reuse_data | 126 | | // | 127 | | // This DeleteTable clean up seems to cause a crash because the delete may not succeed | 128 | | // immediately and is retried after the master is restarted (see ENG-663). So disable it for | 129 | | // now. | 130 | | // | 131 | | // if (table_) { | 132 | | // ASSERT_OK(client_->DeleteTable(kTableName)); | 133 | | // } | 134 | 24 | MiniClusterTestWithClient<MiniClusterType>::DoTearDown(); | 135 | 24 | } |
_ZN2yb6client13QLDmlTestBaseINS_19ExternalMiniClusterEE10DoTearDownEv Line | Count | Source | 124 | 7 | void QLDmlTestBase<MiniClusterType>::DoTearDown() { | 125 | | // If we enable this, it will break FLAGS_mini_cluster_reuse_data | 126 | | // | 127 | | // This DeleteTable clean up seems to cause a crash because the delete may not succeed | 128 | | // immediately and is retried after the master is restarted (see ENG-663). So disable it for | 129 | | // now. | 130 | | // | 131 | | // if (table_) { | 132 | | // ASSERT_OK(client_->DeleteTable(kTableName)); | 133 | | // } | 134 | 7 | MiniClusterTestWithClient<MiniClusterType>::DoTearDown(); | 135 | 7 | } |
|
136 | | |
137 | | template class QLDmlTestBase<MiniCluster>; |
138 | | template class QLDmlTestBase<ExternalMiniCluster>; |
139 | | |
140 | | namespace kv_table_test { |
141 | | |
142 | | namespace { |
143 | | |
144 | 22.5k | QLWriteRequestPB::QLStmtType GetQlStatementType(const WriteOpType op_type) { |
145 | 22.5k | switch (op_type) { |
146 | 22.5k | case WriteOpType::INSERT: |
147 | 22.5k | return QLWriteRequestPB::QL_STMT_INSERT; |
148 | 0 | case WriteOpType::UPDATE: |
149 | 0 | return QLWriteRequestPB::QL_STMT_UPDATE; |
150 | 0 | case WriteOpType::DELETE: |
151 | 0 | return QLWriteRequestPB::QL_STMT_DELETE; |
152 | 0 | } |
153 | 0 | FATAL_INVALID_ENUM_VALUE(WriteOpType, op_type); |
154 | 0 | } |
155 | | |
156 | | } // namespace |
157 | | |
158 | | Result<YBqlWriteOpPtr> Increment( |
159 | | TableHandle* table, const YBSessionPtr& session, int32_t key, int32_t delta, |
160 | 0 | Flush flush) { |
161 | 0 | auto op = table->NewWriteOp(QLWriteRequestPB::QL_STMT_UPDATE); |
162 | 0 | auto value_column_id = table->ColumnId(kValueColumn); |
163 | |
|
164 | 0 | auto* const req = op->mutable_request(); |
165 | 0 | QLAddInt32HashValue(req, key); |
166 | 0 | req->mutable_column_refs()->add_ids(value_column_id); |
167 | 0 | auto* column_value = req->add_column_values(); |
168 | 0 | column_value->set_column_id(value_column_id); |
169 | 0 | auto* bfcall = column_value->mutable_expr()->mutable_bfcall(); |
170 | 0 | bfcall->set_opcode(to_underlying(bfql::BFOpcode::OPCODE_ConvertI64ToI32_18)); |
171 | 0 | bfcall = bfcall->add_operands()->mutable_bfcall(); |
172 | |
|
173 | 0 | bfcall->set_opcode(to_underlying(bfql::BFOpcode::OPCODE_AddI64I64_80)); |
174 | 0 | auto column_op = bfcall->add_operands()->mutable_bfcall(); |
175 | 0 | column_op->set_opcode(to_underlying(bfql::BFOpcode::OPCODE_ConvertI32ToI64_13)); |
176 | 0 | column_op->add_operands()->set_column_id(value_column_id); |
177 | 0 | bfcall->add_operands()->mutable_value()->set_int64_value(delta); |
178 | |
|
179 | 0 | session->Apply(op); |
180 | 0 | if (flush) { |
181 | 0 | RETURN_NOT_OK(session->Flush()); |
182 | 0 | RETURN_NOT_OK(CheckOp(op.get())); |
183 | 0 | } |
184 | |
|
185 | 0 | return op; |
186 | 0 | } |
187 | | |
188 | | void CreateTable( |
189 | | Transactional transactional, int num_tablets, YBClient* client, TableHandle* table, |
190 | 8 | const YBTableName& table_name) { |
191 | 8 | ASSERT_OK(client->CreateNamespaceIfNotExists(table_name.namespace_name(), |
192 | 8 | table_name.namespace_type())); |
193 | | |
194 | 8 | YBSchemaBuilder builder; |
195 | 8 | builder.AddColumn(kKeyColumn)->Type(INT32)->HashPrimaryKey()->NotNull(); |
196 | 8 | builder.AddColumn(kValueColumn)->Type(INT32); |
197 | 8 | if (transactional) { |
198 | 8 | TableProperties table_properties; |
199 | 8 | table_properties.SetTransactional(true); |
200 | 8 | builder.SetTableProperties(table_properties); |
201 | 8 | } |
202 | | |
203 | 8 | ASSERT_OK(table->Create(table_name, num_tablets, client, &builder)); |
204 | 8 | } |
205 | | |
206 | 0 | void BuildSchema(Partitioning partitioning, Schema* schema) { |
207 | 0 | switch (partitioning) { |
208 | 0 | case Partitioning::kHash: |
209 | 0 | *schema = Schema({ ColumnSchema(kKeyColumn, INT32, false, true), |
210 | 0 | ColumnSchema(kValueColumn, INT32) }, 1); |
211 | 0 | return; |
212 | 0 | case Partitioning::kRange: |
213 | 0 | *schema = Schema({ ColumnSchema(kKeyColumn, INT32), |
214 | 0 | ColumnSchema(kValueColumn, INT32) }, 1); |
215 | 0 | return; |
216 | 0 | } |
217 | 0 | FATAL_INVALID_ENUM_VALUE(Partitioning, partitioning); |
218 | 0 | } |
219 | | |
220 | | CHECKED_STATUS CreateTable( |
221 | | const Schema& schema, int num_tablets, YBClient* client, |
222 | 0 | TableHandle* table, const YBTableName& table_name) { |
223 | 0 | RETURN_NOT_OK(client->CreateNamespaceIfNotExists(table_name.namespace_name(), |
224 | 0 | table_name.namespace_type())); |
225 | | |
226 | | // Simple create for hash partitioning. |
227 | 0 | if (schema.num_range_key_columns() == 0) { |
228 | 0 | return table->Create(table_name, num_tablets, YBSchema(schema), client); |
229 | 0 | } |
230 | | |
231 | | // Prepare range keys names. |
232 | 0 | std::vector<std::string> range_columns; |
233 | 0 | range_columns.reserve(schema.num_range_key_columns()); |
234 | 0 | for (size_t i = 0; i < schema.num_key_columns(); ++i) { |
235 | 0 | if (schema.is_range_column(i)) { |
236 | 0 | range_columns.push_back(schema.columns()[i].name()); |
237 | 0 | } |
238 | 0 | } |
239 | | |
240 | | // Create table with range partitioning. |
241 | 0 | YBSchema table_schema(schema); |
242 | 0 | std::unique_ptr<YBTableCreator> table_creator(client->NewTableCreator()); |
243 | 0 | RETURN_NOT_OK(table_creator->table_name(table_name) |
244 | 0 | .schema(&table_schema) |
245 | 0 | .set_range_partition_columns(range_columns) |
246 | 0 | .num_tablets(num_tablets) |
247 | 0 | .Create()); |
248 | |
|
249 | 0 | return table->Open(table_name, client); |
250 | 0 | } |
251 | | |
252 | | void InitIndex( |
253 | | Transactional transactional, |
254 | | size_t indexed_column_index, |
255 | | bool use_mangled_names, |
256 | | const TableHandle& table, |
257 | | IndexInfoPB* index_info, |
258 | 0 | YBSchemaBuilder* builder) { |
259 | 0 | const YBSchema& schema = table.schema(); |
260 | 0 | DCHECK_LT(indexed_column_index, schema.num_columns()); |
261 | | |
262 | | // When creating an index, we construct IndexInfo and associated it with the data-table. |
263 | 0 | index_info->set_indexed_table_id(table->id()); |
264 | 0 | index_info->set_is_local(false); |
265 | 0 | index_info->set_is_unique(false); |
266 | 0 | index_info->set_use_mangled_column_name(use_mangled_names); |
267 | | |
268 | | // List key columns of data-table being indexed. |
269 | 0 | index_info->set_hash_column_count(1); |
270 | 0 | index_info->add_indexed_hash_column_ids(schema.ColumnId(0)); |
271 | |
|
272 | 0 | auto* column = index_info->add_columns(); |
273 | 0 | const string name = schema.Column(indexed_column_index).name(); |
274 | 0 | column->set_column_name(use_mangled_names ? YcqlName::MangleColumnName(name) : name); |
275 | 0 | column->set_indexed_column_id(schema.ColumnId(indexed_column_index)); |
276 | | |
277 | | // Setup Index table schema. |
278 | 0 | builder->AddColumn(use_mangled_names ? YcqlName::MangleColumnName(name) : name) |
279 | 0 | ->Type(schema.Column(indexed_column_index).type()) |
280 | 0 | ->NotNull() |
281 | 0 | ->HashPrimaryKey(); |
282 | |
|
283 | 0 | size_t num_range_keys = 0; |
284 | 0 | for (size_t i = 0; i < schema.num_hash_key_columns(); ++i) { |
285 | 0 | if (i != indexed_column_index) { |
286 | 0 | const string name = schema.Column(i).name(); |
287 | 0 | builder->AddColumn(use_mangled_names ? YcqlName::MangleColumnName(name) : name) |
288 | 0 | ->Type(schema.Column(i).type()) |
289 | 0 | ->NotNull() |
290 | 0 | ->PrimaryKey(); |
291 | |
|
292 | 0 | column = index_info->add_columns(); |
293 | 0 | column->set_column_name(use_mangled_names ? YcqlName::MangleColumnName(name) : name); |
294 | 0 | column->set_indexed_column_id(schema.ColumnId(i)); |
295 | 0 | ++num_range_keys; |
296 | 0 | } |
297 | 0 | } |
298 | |
|
299 | 0 | index_info->set_range_column_count(narrow_cast<uint32_t>(num_range_keys)); |
300 | 0 | TableProperties table_properties; |
301 | 0 | table_properties.SetUseMangledColumnName(use_mangled_names); |
302 | |
|
303 | 0 | if (transactional) { |
304 | 0 | table_properties.SetTransactional(true); |
305 | 0 | } |
306 | |
|
307 | 0 | builder->SetTableProperties(table_properties); |
308 | 0 | } |
309 | | |
310 | | void CreateIndex( |
311 | | Transactional transactional, |
312 | | int indexed_column_index, |
313 | | bool use_mangled_names, |
314 | | const TableHandle& table, |
315 | | YBClient* client, |
316 | 0 | TableHandle* index) { |
317 | 0 | IndexInfoPB index_info; |
318 | 0 | YBSchemaBuilder builder; |
319 | 0 | InitIndex(transactional, indexed_column_index, use_mangled_names, table, &index_info, &builder); |
320 | |
|
321 | 0 | const YBSchema& schema = table.schema(); |
322 | 0 | const YBTableName index_name(YQL_DATABASE_CQL, table.name().namespace_name(), |
323 | 0 | table.name().table_name() + '_' + schema.Column(indexed_column_index).name() + "_idx"); |
324 | |
|
325 | 0 | ASSERT_OK(index->Create(index_name, table->GetPartitionCount(), client, &builder, &index_info)); |
326 | 0 | } |
327 | | |
328 | | void PrepareIndex( |
329 | | Transactional transactional, |
330 | | int indexed_column_index, |
331 | | bool use_mangled_names, |
332 | | const TableHandle& table, |
333 | | YBClient* client, |
334 | 0 | const YBTableName& index_name) { |
335 | 0 | IndexInfoPB index_info; |
336 | 0 | YBSchemaBuilder builder; |
337 | 0 | InitIndex(transactional, indexed_column_index, use_mangled_names, table, &index_info, &builder); |
338 | |
|
339 | 0 | YBSchema schema; |
340 | 0 | ASSERT_OK(builder.Build(&schema)); |
341 | |
|
342 | 0 | std::unique_ptr<YBTableCreator> table_creator(client->NewTableCreator()); |
343 | 0 | table_creator->table_name(index_name) |
344 | 0 | .schema(&schema) |
345 | 0 | .num_tablets(schema.table_properties().num_tablets()); |
346 | | |
347 | | // Setup Index properties. |
348 | 0 | table_creator->indexed_table_id(index_info.indexed_table_id()) |
349 | 0 | .is_local_index(index_info.is_local()) |
350 | 0 | .is_unique_index(index_info.is_unique()) |
351 | 0 | .wait(false) |
352 | 0 | .mutable_index_info()->CopyFrom(index_info); |
353 | |
|
354 | 0 | ASSERT_OK(table_creator->Create()); |
355 | 0 | } |
356 | | |
357 | | Result<YBqlWriteOpPtr> WriteRow( |
358 | | TableHandle* table, const YBSessionPtr& session, int32_t key, int32_t value, |
359 | 22.5k | const WriteOpType op_type, Flush flush) { |
360 | 0 | VLOG(4) << "Calling WriteRow key=" << key << " value=" << value << " op_type=" |
361 | 0 | << yb::ToString(op_type); |
362 | 22.5k | const QLWriteRequestPB::QLStmtType stmt_type = GetQlStatementType(op_type); |
363 | 22.5k | const auto op = table->NewWriteOp(stmt_type); |
364 | 22.5k | auto* const req = op->mutable_request(); |
365 | 22.5k | if (table->table()->partition_schema().IsHashPartitioning()) { |
366 | 22.5k | QLAddInt32HashValue(req, key); |
367 | 0 | } else { |
368 | 0 | QLAddInt32RangeValue(req, key); |
369 | 0 | } |
370 | 22.5k | if (op_type != WriteOpType::DELETE) { |
371 | 22.5k | table->AddInt32ColumnValue(req, kValueColumn, value); |
372 | 22.5k | } |
373 | 22.5k | session->Apply(op); |
374 | 22.5k | if (flush) { |
375 | 22.5k | RETURN_NOT_OK(session->Flush()); |
376 | 22.5k | RETURN_NOT_OK(CheckOp(op.get())); |
377 | 22.5k | } |
378 | 22.5k | return op; |
379 | 22.5k | } |
380 | | |
381 | | Result<YBqlWriteOpPtr> DeleteRow( |
382 | 0 | TableHandle* table, const YBSessionPtr& session, int32_t key) { |
383 | 0 | return kv_table_test::WriteRow(table, session, key, 0 /* value */, WriteOpType::DELETE); |
384 | 0 | } |
385 | | |
386 | | Result<YBqlWriteOpPtr> UpdateRow( |
387 | 0 | TableHandle* table, const YBSessionPtr& session, int32_t key, int32_t value) { |
388 | 0 | return kv_table_test::WriteRow(table, session, key, value, WriteOpType::UPDATE); |
389 | 0 | } |
390 | | |
391 | | Result<int32_t> SelectRow( |
392 | 0 | TableHandle* table, const YBSessionPtr& session, int32_t key, const std::string& column) { |
393 | 0 | const YBqlReadOpPtr op = table->NewReadOp(); |
394 | 0 | auto* const req = op->mutable_request(); |
395 | 0 | QLAddInt32HashValue(req, key); |
396 | 0 | table->AddColumns({column}, req); |
397 | 0 | session->Apply(op); |
398 | 0 | auto flush_status = session->FlushAndGetOpsErrors(); |
399 | 0 | if (flush_status.status.IsIOError()) { |
400 | 0 | for (const auto& error : flush_status.errors) { |
401 | 0 | LOG(WARNING) << "Error: " << error->status() << ", op: " << error->failed_op().ToString(); |
402 | 0 | } |
403 | 0 | } |
404 | 0 | RETURN_NOT_OK(CheckOp(op.get())); |
405 | 0 | auto rowblock = yb::ql::RowsResult(op.get()).GetRowBlock(); |
406 | 0 | if (rowblock->row_count() == 0) { |
407 | 0 | return STATUS_FORMAT(NotFound, "Row not found for key $0", key); |
408 | 0 | } |
409 | 0 | return rowblock->row(0).column(0).int32_value(); |
410 | 0 | } |
411 | | |
412 | | Result<std::map<int32_t, int32_t>> SelectAllRows( |
413 | 0 | TableHandle* table, const YBSessionPtr& session) { |
414 | 0 | std::vector<YBqlReadOpPtr> ops; |
415 | 0 | auto partitions = table->table()->GetPartitionsCopy(); |
416 | 0 | partitions.push_back(std::string()); // Upper bound for last partition. |
417 | |
|
418 | 0 | uint16_t prev_code = 0; |
419 | 0 | for (const auto& partition : partitions) { |
420 | 0 | const YBqlReadOpPtr op = table->NewReadOp(); |
421 | 0 | auto* const req = op->mutable_request(); |
422 | 0 | table->AddColumns(table->AllColumnNames(), req); |
423 | 0 | if (prev_code) { |
424 | 0 | req->set_hash_code(prev_code); |
425 | 0 | } |
426 | | // Partition could be empty, or contain 2 bytes of partition start. |
427 | 0 | if (partition.size() == 2) { |
428 | 0 | uint16_t current_code = BigEndian::Load16(partition.c_str()); |
429 | 0 | req->set_max_hash_code(current_code - 1); |
430 | 0 | prev_code = current_code; |
431 | 0 | } else if (!prev_code) { |
432 | | // Partitions contain starts of partition, so we always skip first iteration, because don't |
433 | | // know end of first partition at this point. |
434 | 0 | continue; |
435 | 0 | } |
436 | 0 | ops.push_back(op); |
437 | 0 | session->Apply(op); |
438 | 0 | } |
439 | |
|
440 | 0 | RETURN_NOT_OK(session->Flush()); |
441 | |
|
442 | 0 | std::map<int32_t, int32_t> result; |
443 | 0 | for (const auto& op : ops) { |
444 | 0 | RETURN_NOT_OK(CheckOp(op.get())); |
445 | 0 | auto rowblock = yb::ql::RowsResult(op.get()).GetRowBlock(); |
446 | 0 | for (const auto& row : rowblock->rows()) { |
447 | 0 | result.emplace(row.column(0).int32_value(), row.column(1).int32_value()); |
448 | 0 | } |
449 | 0 | } |
450 | |
|
451 | 0 | return result; |
452 | 0 | } |
453 | | |
454 | | } // namespace kv_table_test |
455 | | |
456 | | template <class MiniClusterType> |
457 | 8 | void KeyValueTableTest<MiniClusterType>::CreateTable(Transactional transactional) { |
458 | 8 | kv_table_test::CreateTable(transactional, NumTablets(), client_.get(), &table_); |
459 | 8 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE11CreateTableENS_17StronglyTypedBoolINS0_17Transactional_TagEEE _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE11CreateTableENS_17StronglyTypedBoolINS0_17Transactional_TagEEE Line | Count | Source | 457 | 8 | void KeyValueTableTest<MiniClusterType>::CreateTable(Transactional transactional) { | 458 | 8 | kv_table_test::CreateTable(transactional, NumTablets(), client_.get(), &table_); | 459 | 8 | } |
|
460 | | |
461 | | template <class MiniClusterType> |
462 | 0 | CHECKED_STATUS KeyValueTableTest<MiniClusterType>::CreateTable(const Schema& schema) { |
463 | 0 | return kv_table_test::CreateTable(schema, NumTablets(), client_.get(), &table_); |
464 | 0 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE11CreateTableERKNS_6SchemaE Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE11CreateTableERKNS_6SchemaE |
465 | | |
466 | | template <class MiniClusterType> |
467 | | void KeyValueTableTest<MiniClusterType>::CreateIndex( |
468 | 0 | Transactional transactional, int indexed_column_index, bool use_mangled_names) { |
469 | 0 | kv_table_test::CreateIndex( |
470 | 0 | transactional, indexed_column_index, use_mangled_names, table_, client_.get(), &index_); |
471 | 0 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE11CreateIndexENS_17StronglyTypedBoolINS0_17Transactional_TagEEEib Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE11CreateIndexENS_17StronglyTypedBoolINS0_17Transactional_TagEEEib |
472 | | |
473 | | template <class MiniClusterType> |
474 | | void KeyValueTableTest<MiniClusterType>::PrepareIndex( |
475 | | Transactional transactional, |
476 | | const YBTableName &index_name, |
477 | | int indexed_column_index, |
478 | 0 | bool use_mangled_names) { |
479 | 0 | kv_table_test::PrepareIndex( |
480 | 0 | transactional, indexed_column_index, use_mangled_names, table_, client_.get(), index_name); |
481 | 0 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE12PrepareIndexENS_17StronglyTypedBoolINS0_17Transactional_TagEEERKNS0_11YBTableNameEib Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE12PrepareIndexENS_17StronglyTypedBoolINS0_17Transactional_TagEEERKNS0_11YBTableNameEib |
482 | | |
483 | | template <class MiniClusterType> |
484 | 8 | int KeyValueTableTest<MiniClusterType>::NumTablets() { |
485 | 8 | return num_tablets_; |
486 | 8 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE10NumTabletsEv _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE10NumTabletsEv Line | Count | Source | 484 | 8 | int KeyValueTableTest<MiniClusterType>::NumTablets() { | 485 | 8 | return num_tablets_; | 486 | 8 | } |
|
487 | | |
488 | | template <class MiniClusterType> |
489 | | YBSessionPtr KeyValueTableTest<MiniClusterType>::CreateSession( |
490 | 15 | const YBTransactionPtr& transaction, const server::ClockPtr& clock) { |
491 | 15 | auto session = std::make_shared<YBSession>(client_.get(), clock); |
492 | 15 | if (transaction) { |
493 | 15 | session->SetTransaction(transaction); |
494 | 15 | } |
495 | 15 | session->SetTimeout(RegularBuildVsSanitizers(15s, 60s)); |
496 | 15 | return session; |
497 | 15 | } Unexecuted instantiation: _ZN2yb6client17KeyValueTableTestINS_11MiniClusterEE13CreateSessionERKNSt3__110shared_ptrINS0_13YBTransactionEEERK13scoped_refptrINS_6server5ClockEE _ZN2yb6client17KeyValueTableTestINS_19ExternalMiniClusterEE13CreateSessionERKNSt3__110shared_ptrINS0_13YBTransactionEEERK13scoped_refptrINS_6server5ClockEE Line | Count | Source | 490 | 15 | const YBTransactionPtr& transaction, const server::ClockPtr& clock) { | 491 | 15 | auto session = std::make_shared<YBSession>(client_.get(), clock); | 492 | 15 | if (transaction) { | 493 | 15 | session->SetTransaction(transaction); | 494 | 15 | } | 495 | 15 | session->SetTimeout(RegularBuildVsSanitizers(15s, 60s)); | 496 | 15 | return session; | 497 | 15 | } |
|
498 | | |
499 | | template class KeyValueTableTest<MiniCluster>; |
500 | | template class KeyValueTableTest<ExternalMiniCluster>; |
501 | | |
502 | 22.5k | Status CheckOp(YBqlOp* op) { |
503 | 22.5k | if (!op->succeeded()) { |
504 | 0 | return STATUS(QLError, |
505 | 0 | op->response().error_message(), |
506 | 0 | Slice(), |
507 | 0 | ql::QLError(ql::QLStatusToErrorCode(op->response().status()))); |
508 | 0 | } |
509 | | |
510 | 22.5k | return Status::OK(); |
511 | 22.5k | } |
512 | | |
513 | | } // namespace client |
514 | | } // namespace yb |