/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 |