YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/client/yb_op.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#ifndef YB_CLIENT_YB_OP_H_
33
#define YB_CLIENT_YB_OP_H_
34
35
#include <memory>
36
#include <string>
37
38
#include <boost/optional.hpp>
39
40
#include "yb/client/client_fwd.h"
41
42
#include "yb/common/common_fwd.h"
43
#include "yb/common/common_types.pb.h"
44
#include "yb/common/partial_row.h"
45
#include "yb/common/read_hybrid_time.h"
46
#include "yb/common/transaction.pb.h"
47
48
#include "yb/docdb/docdb_fwd.h"
49
50
#include "yb/util/ref_cnt_buffer.h"
51
52
namespace yb {
53
54
class RedisWriteRequestPB;
55
class RedisReadRequestPB;
56
class RedisResponsePB;
57
58
class QLWriteRequestPB;
59
class QLReadRequestPB;
60
class QLResponsePB;
61
class QLRowBlock;
62
63
namespace client {
64
65
namespace internal {
66
class Batcher;
67
class AsyncRpc;
68
class RemoteTablet;
69
}  // namespace internal
70
71
class YBSession;
72
class YBStatusCallback;
73
class YBTable;
74
75
YB_DEFINE_ENUM(OpGroup, (kWrite)(kLeaderRead)(kConsistentPrefixRead));
76
77
// A write or read operation operates on a single table and partial row.
78
// The YBOperation class itself allows the batcher to get to the
79
// generic information that it needs to process all write operations.
80
//
81
// On its own, the class does not represent any specific change and thus cannot
82
// be constructed independently.
83
//
84
// YBOperation also holds shared ownership of its YBTable to allow client's
85
// scope to end while the YBOperation is still alive.
86
class YBOperation {
87
 public:
88
  enum Type {
89
    // Redis opcodes.
90
    REDIS_WRITE = 4,
91
    REDIS_READ = 5,
92
93
    // CQL opcodes.
94
    QL_WRITE = 6,
95
    QL_READ = 7,
96
97
    // Postgresql opcodes.
98
    PGSQL_WRITE = 8,
99
    PGSQL_READ = 9,
100
  };
101
  virtual ~YBOperation();
102
103
37.3M
  std::shared_ptr<const YBTable> table() const { return table_; }
104
10.9M
  std::shared_ptr<YBTable> mutable_table() const { return table_; }
105
106
  void ResetTable(std::shared_ptr<YBTable> new_table);
107
108
  virtual std::string ToString() const = 0;
109
  virtual Type type() const = 0;
110
  virtual bool read_only() const = 0;
111
  virtual bool succeeded() const = 0;
112
  virtual bool returns_sidecar() = 0;
113
114
30.4M
  virtual OpGroup group() {
115
30.4M
    return read_only() ? OpGroup::kLeaderRead : OpGroup::kWrite;
116
30.4M
  }
117
118
152k
  virtual bool applied() {
119
152k
    return succeeded();
120
152k
  }
121
122
2.51M
  virtual bool should_add_intents(IsolationLevel isolation_level) {
123
2.51M
    return !read_only() || isolation_level == IsolationLevel::SERIALIZABLE_ISOLATION;
124
2.51M
  }
125
126
  virtual void SetHashCode(uint16_t hash_code) = 0;
127
128
11.2M
  const scoped_refptr<internal::RemoteTablet>& tablet() const {
129
11.2M
    return tablet_;
130
11.2M
  }
131
132
  void SetTablet(const scoped_refptr<internal::RemoteTablet>& tablet);
133
134
  // Resets tablet, so it will be re-resolved on applying this operation.
135
  void ResetTablet();
136
137
  // Returns the partition key of the operation.
138
  virtual CHECKED_STATUS GetPartitionKey(std::string* partition_key) const = 0;
139
140
  // Returns whether this operation is being performed on a table where distributed transactions
141
  // are enabled.
142
  virtual bool IsTransactional() const;
143
144
  // Whether this is an operation on one of the YSQL system catalog tables.
145
  bool IsYsqlCatalogOp() const;
146
147
  // Mark table this op is designated for as having stale partitions.
148
  void MarkTablePartitionListAsStale();
149
150
  // If partition_list_version is set YBSession guarantees that this operation instance won't
151
  // be applied to the tablet with a different table partition_list_version (meaning serving
152
  // different range of partition keys). If versions do not match YBSession will report
153
  // ClientError::kTablePartitionListVersionDoesNotMatch.
154
  // If partition_list_version is not set - no such check will be performed.
155
0
  void SetPartitionListVersion(PartitionListVersion partition_list_version) {
156
0
    partition_list_version_ = partition_list_version;
157
0
  }
158
159
11.0M
  boost::optional<PartitionListVersion> partition_list_version() const {
160
11.0M
    return partition_list_version_;
161
11.0M
  }
162
163
5.17M
  int64_t GetQueryId() const {
164
5.17M
    return reinterpret_cast<int64_t>(this);
165
5.17M
  }
166
167
 protected:
168
  explicit YBOperation(const std::shared_ptr<YBTable>& table);
169
170
  std::shared_ptr<YBTable> table_;
171
172
 private:
173
  friend class internal::AsyncRpc;
174
175
  scoped_refptr<internal::RemoteTablet> tablet_;
176
177
  boost::optional<PartitionListVersion> partition_list_version_;
178
179
  DISALLOW_COPY_AND_ASSIGN(YBOperation);
180
};
181
182
//--------------------------------------------------------------------------------------------------
183
// YBRedis Operators.
184
//--------------------------------------------------------------------------------------------------
185
186
class YBRedisOp : public YBOperation {
187
 public:
188
  explicit YBRedisOp(const std::shared_ptr<YBTable>& table);
189
190
0
  bool has_response() { return redis_response_ ? true : false; }
191
  virtual size_t space_used_by_request() const = 0;
192
193
  const RedisResponsePB& response() const;
194
195
  RedisResponsePB* mutable_response();
196
197
5
  uint16_t hash_code() const { return hash_code_; }
198
199
  // Redis does not use sidecars.
200
0
  bool returns_sidecar() override { return false; }
201
202
  virtual const std::string& GetKey() const = 0;
203
204
 protected:
205
  uint16_t hash_code_ = 0;
206
  std::unique_ptr<RedisResponsePB> redis_response_;
207
};
208
209
class YBRedisWriteOp : public YBRedisOp {
210
 public:
211
  explicit YBRedisWriteOp(const std::shared_ptr<YBTable>& table);
212
213
  // Note: to avoid memory copy, this RedisWriteRequestPB is moved into tserver WriteRequestPB
214
  // when the request is sent to tserver. It is restored after response is received from tserver
215
  // (see WriteRpc's constructor).
216
10.5k
  const RedisWriteRequestPB& request() const { return *redis_write_request_; }
217
  size_t space_used_by_request() const override;
218
219
362k
  RedisWriteRequestPB* mutable_request() { return redis_write_request_.get(); }
220
221
  std::string ToString() const override;
222
223
184k
  bool read_only() const override { return false; }
224
0
  bool succeeded() const override { return false; } // TODO(dtxn) implement
225
226
  // Set the hash key in the WriteRequestPB.
227
  void SetHashCode(uint16_t hash_code) override;
228
229
  const std::string& GetKey() const override;
230
231
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
232
233
 protected:
234
246k
  virtual Type type() const override { return REDIS_WRITE; }
235
236
 private:
237
  friend class YBTable;
238
  std::unique_ptr<RedisWriteRequestPB> redis_write_request_;
239
  std::unique_ptr<RedisResponsePB> redis_response_;
240
};
241
242
243
class YBRedisReadOp : public YBRedisOp {
244
 public:
245
  explicit YBRedisReadOp(const std::shared_ptr<YBTable>& table);
246
247
  // Note: to avoid memory copy, this RedisReadRequestPB is moved into tserver ReadRequestPB
248
  // when the request is sent to tserver. It is restored after response is received from tserver
249
  // (see ReadRpc's constructor).
250
0
  const RedisReadRequestPB& request() const { return *redis_read_request_; }
251
  size_t space_used_by_request() const override;
252
253
143k
  RedisReadRequestPB* mutable_request() { return redis_read_request_.get(); }
254
255
  std::string ToString() const override;
256
257
84
  bool read_only() const override { return true; }
258
0
  bool succeeded() const override { return false; } // TODO(dtxn) implement
259
260
  // Set the hash key in the ReadRequestPB.
261
  void SetHashCode(uint16_t hash_code) override;
262
263
  const std::string& GetKey() const override;
264
265
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
266
267
 protected:
268
172k
  Type type() const override { return REDIS_READ; }
269
  OpGroup group() override;
270
271
 private:
272
  friend class YBTable;
273
  std::unique_ptr<RedisReadRequestPB> redis_read_request_;
274
};
275
276
//--------------------------------------------------------------------------------------------------
277
// YBCql Operators.
278
//--------------------------------------------------------------------------------------------------
279
280
class YBqlOp : public YBOperation {
281
 public:
282
  ~YBqlOp();
283
284
23.4M
  const QLResponsePB& response() const { return *ql_response_; }
285
286
7.07M
  QLResponsePB* mutable_response() { return ql_response_.get(); }
287
288
5.18M
  const std::string& rows_data() { return rows_data_; }
289
290
7.88M
  std::string* mutable_rows_data() { return &rows_data_; }
291
292
  bool succeeded() const override;
293
294
 protected:
295
  explicit YBqlOp(const std::shared_ptr<YBTable>& table);
296
  std::unique_ptr<QLResponsePB> ql_response_;
297
  std::string rows_data_;
298
};
299
300
class YBqlWriteOp : public YBqlOp {
301
 public:
302
  explicit YBqlWriteOp(const std::shared_ptr<YBTable>& table);
303
  ~YBqlWriteOp();
304
305
  // Note: to avoid memory copy, this QLWriteRequestPB is moved into tserver WriteRequestPB
306
  // when the request is sent to tserver. It is restored after response is received from tserver
307
  // (see WriteRpc's constructor).
308
3.27M
  const QLWriteRequestPB& request() const { return *ql_write_request_; }
309
310
9.14M
  QLWriteRequestPB* mutable_request() { return ql_write_request_.get(); }
311
312
  std::string ToString() const override;
313
314
14.5M
  bool read_only() const override { return false; };
315
316
  bool returns_sidecar() override;
317
318
  void SetHashCode(uint16_t hash_code) override;
319
320
  uint16_t GetHashCode() const;
321
322
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
323
324
  // Does this operation read/write the static or primary row?
325
  bool ReadsStaticRow() const;
326
  bool ReadsPrimaryRow() const;
327
  bool WritesStaticRow() const;
328
  bool WritesPrimaryRow() const;
329
330
1.29M
  void set_writes_static_row(const bool value) { writes_static_row_ = value; }
331
1.29M
  void set_writes_primary_row(const bool value) { writes_primary_row_ = value; }
332
333
9.54k
  void set_write_time_for_backfill(HybridTime value) {
334
9.54k
    write_time_for_backfill_ = value;
335
9.54k
  }
336
337
3.04M
  HybridTime write_time_for_backfill() const {
338
3.04M
    return write_time_for_backfill_;
339
3.04M
  }
340
341
 protected:
342
10.1M
  Type type() const override { return QL_WRITE; }
343
344
 private:
345
  friend class YBTable;
346
  static std::unique_ptr<YBqlWriteOp> NewInsert(const std::shared_ptr<YBTable>& table);
347
  static std::unique_ptr<YBqlWriteOp> NewUpdate(const std::shared_ptr<YBTable>& table);
348
  static std::unique_ptr<YBqlWriteOp> NewDelete(const std::shared_ptr<YBTable>& table);
349
  std::unique_ptr<QLWriteRequestPB> ql_write_request_;
350
351
  // Does this operation write to the static or primary row?
352
  bool writes_static_row_ = false;
353
  bool writes_primary_row_ = false;
354
  HybridTime write_time_for_backfill_;
355
};
356
357
// Hash and equal functions to define a set of write operations that do not overlap by their
358
// hash (or primary) keys.
359
struct YBqlWriteHashKeyComparator {
360
  size_t operator() (const YBqlWriteOpPtr& op) const;
361
  bool operator() (const YBqlWriteOpPtr& op1, const YBqlWriteOpPtr& op2) const;
362
};
363
364
struct YBqlWritePrimaryKeyComparator {
365
  size_t operator() (const YBqlWriteOpPtr& op) const;
366
  bool operator() (const YBqlWriteOpPtr& op1, const YBqlWriteOpPtr& op2) const;
367
};
368
369
class YBqlReadOp : public YBqlOp {
370
 public:
371
  ~YBqlReadOp();
372
373
  static std::unique_ptr<YBqlReadOp> NewSelect(const std::shared_ptr<YBTable>& table);
374
375
  // Note: to avoid memory copy, this QLReadRequestPB is moved into tserver ReadRequestPB
376
  // when the request is sent to tserver. It is restored after response is received from tserver
377
  // (see ReadRpc's constructor).
378
11.7M
  const QLReadRequestPB& request() const { return *ql_read_request_; }
379
380
15.6M
  QLReadRequestPB* mutable_request() { return ql_read_request_.get(); }
381
382
  std::string ToString() const override;
383
384
172k
  bool read_only() const override { return true; };
385
386
0
  bool returns_sidecar() override { return true; }
387
388
  void SetHashCode(uint16_t hash_code) override;
389
390
  // Returns the partition key of the read request if it exists.
391
  // Also sets the hash_code and max_hash_code in the request.
392
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
393
394
6.00k
  YBConsistencyLevel yb_consistency_level() {
395
6.00k
    return yb_consistency_level_;
396
6.00k
  }
397
398
3.89M
  void set_yb_consistency_level(const YBConsistencyLevel yb_consistency_level) {
399
3.89M
    yb_consistency_level_ = yb_consistency_level;
400
3.89M
  }
401
402
  std::vector<ColumnSchema> MakeColumnSchemasFromRequest() const;
403
  Result<QLRowBlock> MakeRowBlock() const;
404
405
3.93M
  const ReadHybridTime& read_time() const { return read_time_; }
406
6
  void SetReadTime(const ReadHybridTime& value) { read_time_ = value; }
407
408
 protected:
409
27.5M
  Type type() const override { return QL_READ; }
410
  OpGroup group() override;
411
412
 private:
413
  friend class YBTable;
414
  explicit YBqlReadOp(const std::shared_ptr<YBTable>& table);
415
  std::unique_ptr<QLReadRequestPB> ql_read_request_;
416
  YBConsistencyLevel yb_consistency_level_;
417
  ReadHybridTime read_time_;
418
};
419
420
std::vector<ColumnSchema> MakeColumnSchemasFromColDesc(
421
  const google::protobuf::RepeatedPtrField<QLRSColDescPB>& rscol_descs);
422
423
//--------------------------------------------------------------------------------------------------
424
// YB Postgresql Operators.
425
//--------------------------------------------------------------------------------------------------
426
427
class YBPgsqlOp : public YBOperation {
428
 public:
429
  YBPgsqlOp(const std::shared_ptr<YBTable>& table, std::string* partition_key);
430
  ~YBPgsqlOp();
431
432
10.1M
  const PgsqlResponsePB& response() const { return *response_; }
433
434
7.48M
  PgsqlResponsePB* mutable_response() { return response_.get(); }
435
436
  bool succeeded() const override;
437
438
  bool applied() override;
439
440
3.60M
  void SetRowsData(RefCntBuffer holder, const Slice& slice) {
441
3.60M
    rows_data_holder_ = std::move(holder);
442
3.60M
    rows_data_slice_ = slice;
443
3.60M
  }
444
445
3.45M
  const Slice& rows_data() const {
446
3.45M
    return rows_data_slice_;
447
3.45M
  }
448
449
0
  const RefCntBuffer& rows_data_holder() const {
450
0
    return rows_data_holder_;
451
0
  }
452
453
4.02M
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override {
454
4.02M
    *partition_key = partition_key_;
455
4.02M
    return Status::OK();
456
4.02M
  }
457
458
 protected:
459
  std::unique_ptr<PgsqlResponsePB> response_;
460
  RefCntBuffer rows_data_holder_;
461
  Slice rows_data_slice_;
462
  std::string partition_key_;
463
};
464
465
class YBPgsqlWriteOp : public YBPgsqlOp {
466
 public:
467
  explicit YBPgsqlWriteOp(
468
      const std::shared_ptr<YBTable>& table, PgsqlWriteRequestPB* request = nullptr);
469
  ~YBPgsqlWriteOp();
470
471
  // Note: to avoid memory copy, this PgsqlWriteRequestPB is moved into tserver WriteRequestPB
472
  // when the request is sent to tserver. It is restored after response is received from tserver
473
  // (see WriteRpc's constructor).
474
0
  const PgsqlWriteRequestPB& request() const { return *request_; }
475
476
2.12M
  PgsqlWriteRequestPB* mutable_request() { return request_; }
477
478
  std::string ToString() const override;
479
480
20.3M
  bool read_only() const override { return false; };
481
482
  // TODO check for e.g. returning clause.
483
0
  bool returns_sidecar() override { return true; }
484
485
  void SetHashCode(uint16_t hash_code) override;
486
487
  bool IsTransactional() const override;
488
489
0
  void set_is_single_row_txn(bool is_single_row_txn) {
490
0
    is_single_row_txn_ = is_single_row_txn;
491
0
  }
492
493
2.12M
  const HybridTime& write_time() const { return write_time_; }
494
226
  void SetWriteTime(const HybridTime& value) { write_time_ = value; }
495
496
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
497
498
  static std::unique_ptr<YBPgsqlWriteOp> NewInsert(const YBTablePtr& table);
499
  static std::unique_ptr<YBPgsqlWriteOp> NewUpdate(const YBTablePtr& table);
500
  static std::unique_ptr<YBPgsqlWriteOp> NewDelete(const YBTablePtr& table);
501
  static std::unique_ptr<YBPgsqlWriteOp> NewTruncateColocated(const YBTablePtr& table);
502
503
 protected:
504
6.64M
  virtual Type type() const override { return PGSQL_WRITE; }
505
506
 private:
507
  friend class YBTable;
508
509
  PgsqlWriteRequestPB* request_;
510
  std::unique_ptr<PgsqlWriteRequestPB> request_holder_;
511
  // Whether this operation should be run as a single row txn.
512
  // Else could be distributed transaction (or non-transactional) depending on target table type.
513
  bool is_single_row_txn_ = false;
514
  HybridTime write_time_;
515
};
516
517
class YBPgsqlReadOp : public YBPgsqlOp {
518
 public:
519
  explicit YBPgsqlReadOp(
520
      const std::shared_ptr<YBTable>& table, PgsqlReadRequestPB* request = nullptr);
521
522
  static std::unique_ptr<YBPgsqlReadOp> NewSelect(const std::shared_ptr<YBTable>& table);
523
524
  static std::unique_ptr<YBPgsqlReadOp> NewSample(const std::shared_ptr<YBTable>& table);
525
526
  // Note: to avoid memory copy, this PgsqlReadRequestPB is moved into tserver ReadRequestPB
527
  // when the request is sent to tserver. It is restored after response is received from tserver
528
  // (see ReadRpc's constructor).
529
0
  const PgsqlReadRequestPB& request() const { return *request_; }
530
531
1.90M
  PgsqlReadRequestPB* mutable_request() { return request_; }
532
533
  std::string ToString() const override;
534
535
1.41M
  bool read_only() const override { return true; };
536
537
0
  bool returns_sidecar() override { return true; }
538
539
  void SetHashCode(uint16_t hash_code) override;
540
541
0
  YBConsistencyLevel yb_consistency_level() {
542
0
    return yb_consistency_level_;
543
0
  }
544
545
0
  void set_yb_consistency_level(const YBConsistencyLevel yb_consistency_level) {
546
0
    yb_consistency_level_ = yb_consistency_level;
547
0
  }
548
549
  std::vector<ColumnSchema> MakeColumnSchemasFromRequest() const;
550
551
  static std::vector<ColumnSchema> MakeColumnSchemasFromColDesc(
552
      const google::protobuf::RepeatedPtrField<PgsqlRSColDescPB>& rscol_descs);
553
554
  bool should_add_intents(IsolationLevel isolation_level) override;
555
  void SetUsedReadTime(const ReadHybridTime& used_time);
556
399k
  const ReadHybridTime& used_read_time() const { return used_read_time_; }
557
558
  CHECKED_STATUS GetPartitionKey(std::string* partition_key) const override;
559
560
 protected:
561
6.40M
  virtual Type type() const override { return PGSQL_READ; }
562
  OpGroup group() override;
563
564
 private:
565
  friend class YBTable;
566
567
  PgsqlReadRequestPB* request_;
568
  std::unique_ptr<PgsqlReadRequestPB> request_holder_;
569
  YBConsistencyLevel yb_consistency_level_ = YBConsistencyLevel::STRONG;
570
  ReadHybridTime used_read_time_;
571
};
572
573
// This class is not thread-safe, though different YBNoOp objects on
574
// different threads may share a single YBTable object.
575
class YBNoOp {
576
 public:
577
  // Initialize the NoOp request object. The given 'table' object must remain valid
578
  // for the lifetime of this object.
579
  explicit YBNoOp(const std::shared_ptr<YBTable>& table);
580
581
  // Executes a no-op request against the tablet server on which the row specified
582
  // by "key" lives.
583
  CHECKED_STATUS Execute(YBClient* client, const YBPartialRow& key);
584
 private:
585
  const std::shared_ptr<YBTable> table_;
586
587
  DISALLOW_COPY_AND_ASSIGN(YBNoOp);
588
};
589
590
CHECKED_STATUS InitPartitionKey(
591
    const Schema& schema, const PartitionSchema& partition_schema,
592
    const std::string& last_partition, PgsqlReadRequestPB* request);
593
594
CHECKED_STATUS InitPartitionKey(
595
    const Schema& schema, const PartitionSchema& partition_schema, PgsqlWriteRequestPB* request);
596
597
Result<std::vector<docdb::PrimitiveValue>> GetRangeComponents(
598
    const Schema& schema, const google::protobuf::RepeatedPtrField<PgsqlExpressionPB>& range_cols);
599
600
CHECKED_STATUS GetRangePartitionBounds(
601
    const Schema& schema,
602
    const PgsqlReadRequestPB& request,
603
    std::vector<docdb::PrimitiveValue>* lower_bound,
604
    std::vector<docdb::PrimitiveValue>* upper_bound);
605
606
}  // namespace client
607
}  // namespace yb
608
609
#endif  // YB_CLIENT_YB_OP_H_