YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/docdb/pgsql_operation.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_PGSQL_OPERATION_H
15
#define YB_DOCDB_PGSQL_OPERATION_H
16
17
#include "yb/common/pgsql_protocol.pb.h"
18
19
#include "yb/docdb/doc_expr.h"
20
#include "yb/docdb/doc_key.h"
21
#include "yb/docdb/doc_operation.h"
22
#include "yb/docdb/intent_aware_iterator.h"
23
#include "yb/docdb/ql_rowwise_iterator_interface.h"
24
25
namespace yb {
26
27
class IndexInfo;
28
29
namespace docdb {
30
31
YB_STRONGLY_TYPED_BOOL(IsUpsert);
32
33
class PgsqlWriteOperation :
34
    public DocOperationBase<DocOperationType::PGSQL_WRITE_OPERATION, PgsqlWriteRequestPB>,
35
    public DocExprExecutor {
36
 public:
37
  PgsqlWriteOperation(std::reference_wrapper<const PgsqlWriteRequestPB> request,
38
                      const Schema& schema,
39
                      const TransactionOperationContext& txn_op_context)
40
      : DocOperationBase(request),
41
        schema_(schema),
42
12.8M
        txn_op_context_(txn_op_context) {
43
12.8M
  }
44
45
  // Initialize PgsqlWriteOperation. Content of request will be swapped out by the constructor.
46
  CHECKED_STATUS Init(PgsqlResponsePB* response);
47
33.0M
  bool RequireReadSnapshot() const override {
48
    // For YSQL the the standard operations (INSERT/UPDATE/DELETE) will read/check the primary key.
49
    // We use UPSERT stmt type for specific requests when we can guarantee we can skip the read.
50
33.0M
    return request_.stmt_type() != PgsqlWriteRequestPB::PGSQL_UPSERT;
51
33.0M
  }
52
53
0
  const PgsqlWriteRequestPB& request() const { return request_; }
54
7.14M
  PgsqlResponsePB* response() const { return response_; }
55
56
14.3M
  const faststring& result_buffer() const { return result_buffer_; }
57
58
0
  bool result_is_single_empty_row() const {
59
0
    return result_rows_ == 1 && result_buffer_.size() == sizeof(int64_t);
60
0
  }
61
62
  Result<bool> HasDuplicateUniqueIndexValue(const DocOperationApplyData& data);
63
  Result<bool> HasDuplicateUniqueIndexValue(
64
      const DocOperationApplyData& data,
65
      yb::docdb::Direction direction);
66
  Result<bool> HasDuplicateUniqueIndexValue(
67
      const DocOperationApplyData& data,
68
      ReadHybridTime read_time);
69
  Result<HybridTime> FindOldestOverwrittenTimestamp(
70
      IntentAwareIterator* iter,
71
      const SubDocKey& sub_doc_key,
72
      HybridTime min_hybrid_time);
73
74
  // Execute write.
75
  CHECKED_STATUS Apply(const DocOperationApplyData& data) override;
76
77
 private:
78
0
  void ClearResponse() override {
79
0
    if (response_) {
80
0
      response_->Clear();
81
0
    }
82
0
  }
83
84
  // Insert, update, delete, and colocated truncate operations.
85
  CHECKED_STATUS ApplyInsert(
86
      const DocOperationApplyData& data, IsUpsert is_upsert = IsUpsert::kFalse);
87
  CHECKED_STATUS ApplyUpdate(const DocOperationApplyData& data);
88
  CHECKED_STATUS ApplyDelete(const DocOperationApplyData& data, const bool is_persist_needed);
89
  CHECKED_STATUS ApplyTruncateColocated(const DocOperationApplyData& data);
90
91
  CHECKED_STATUS DeleteRow(const DocPath& row_path, DocWriteBatch* doc_write_batch,
92
                           const ReadHybridTime& read_ht, CoarseTimePoint deadline);
93
94
  // Reading current row before operating on it.
95
  CHECKED_STATUS ReadColumns(const DocOperationApplyData& data,
96
                             QLTableRow* table_row);
97
98
  CHECKED_STATUS PopulateResultSet(const QLTableRow& table_row);
99
100
  // Reading path to operate on.
101
  CHECKED_STATUS GetDocPaths(GetDocPathsMode mode,
102
                             DocPathsToLock *paths,
103
                             IsolationLevel *level) const override;
104
105
  //------------------------------------------------------------------------------------------------
106
  // Context.
107
  const Schema& schema_;
108
  const TransactionOperationContext txn_op_context_;
109
110
  // Input arguments.
111
  PgsqlResponsePB* response_ = nullptr;
112
113
  // TODO(neil) Output arguments.
114
  // UPDATE, DELETE, INSERT operations should return total number of new or changed rows.
115
116
  // Doc key and encoded doc key for the primary key.
117
  boost::optional<DocKey> doc_key_;
118
  RefCntPrefix encoded_doc_key_;
119
120
  // Rows result requested.
121
  int64_t result_rows_ = 0;
122
  faststring result_buffer_;
123
};
124
125
class PgsqlReadOperation : public DocExprExecutor {
126
 public:
127
  // Construct and access methods.
128
  PgsqlReadOperation(const PgsqlReadRequestPB& request,
129
                     const TransactionOperationContext& txn_op_context)
130
6.23M
      : request_(request), txn_op_context_(txn_op_context) {
131
6.23M
  }
132
133
0
  const PgsqlReadRequestPB& request() const { return request_; }
134
3.47M
  PgsqlResponsePB& response() { return response_; }
135
136
  // Driver of the execution for READ operators for the given conditions in Protobuf request.
137
  // The protobuf request carries two different types of arguments.
138
  // - Scalar argument: The query condition is represented by one set of values. For example, each
139
  //   of the following scalar protobuf requests will carry one "ybctid" (ROWID).
140
  //     SELECT ... WHERE ybctid = y1;
141
  //     SELECT ... WHERE ybctid = y2;
142
  //     SELECT ... WHERE ybctid = y3;
143
  //
144
  // - Batch argument: The query condition is represented by many sets of values. For example, a
145
  //   batch protobuf will carry many ybctids.
146
  //     SELECT ... WHERE ybctid IN (y1, y2, y3)
147
  Result<size_t> Execute(const YQLStorageIf& ql_storage,
148
                         CoarseTimePoint deadline,
149
                         const ReadHybridTime& read_time,
150
                         bool is_explicit_request_read_time,
151
                         const Schema& schema,
152
                         const Schema *index_schema,
153
                         faststring *result_buffer,
154
                         HybridTime *restart_read_ht);
155
156
  CHECKED_STATUS GetTupleId(QLValue *result) const override;
157
158
  CHECKED_STATUS GetIntents(const Schema& schema, KeyValueWriteBatchPB* out);
159
160
 private:
161
  // Execute a READ operator for a given scalar argument.
162
  Result<size_t> ExecuteScalar(const YQLStorageIf& ql_storage,
163
                               CoarseTimePoint deadline,
164
                               const ReadHybridTime& read_time,
165
                               bool is_explicit_request_read_time,
166
                               const Schema& schema,
167
                               const Schema *index_schema,
168
                               faststring *result_buffer,
169
                               HybridTime *restart_read_ht,
170
                               bool *has_paging_state);
171
172
  // Execute a READ operator for a given batch of ybctids.
173
  Result<size_t> ExecuteBatchYbctid(const YQLStorageIf& ql_storage,
174
                                    CoarseTimePoint deadline,
175
                                    const ReadHybridTime& read_time,
176
                                    const Schema& schema,
177
                                    faststring *result_buffer,
178
                                    HybridTime *restart_read_ht);
179
180
  Result<size_t> ExecuteSample(const YQLStorageIf& ql_storage,
181
                               CoarseTimePoint deadline,
182
                               const ReadHybridTime& read_time,
183
                               bool is_explicit_request_read_time,
184
                               const Schema& schema,
185
                               faststring *result_buffer,
186
                               HybridTime *restart_read_ht,
187
                               bool *has_paging_state);
188
189
  CHECKED_STATUS PopulateResultSet(const QLTableRow& table_row,
190
                                   faststring *result_buffer);
191
192
  CHECKED_STATUS EvalAggregate(const QLTableRow& table_row);
193
194
  CHECKED_STATUS PopulateAggregate(const QLTableRow& table_row,
195
                                   faststring *result_buffer);
196
197
  // Checks whether we have processed enough rows for a page and sets the appropriate paging
198
  // state in the response object.
199
  CHECKED_STATUS SetPagingStateIfNecessary(const YQLRowwiseIteratorIf* iter,
200
                                           size_t fetched_rows,
201
                                           const size_t row_count_limit,
202
                                           const bool scan_time_exceeded,
203
                                           const Schema* schema,
204
                                           const ReadHybridTime& read_time,
205
                                           bool *has_paging_state);
206
207
  //------------------------------------------------------------------------------------------------
208
  const PgsqlReadRequestPB& request_;
209
  const TransactionOperationContext txn_op_context_;
210
  PgsqlResponsePB response_;
211
  YQLRowwiseIteratorIf::UniPtr table_iter_;
212
  YQLRowwiseIteratorIf::UniPtr index_iter_;
213
};
214
215
}  // namespace docdb
216
}  // namespace yb
217
218
#endif // YB_DOCDB_PGSQL_OPERATION_H