/Users/deen/code/yugabyte-db/src/yb/docdb/cql_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_CQL_OPERATION_H |
15 | | #define YB_DOCDB_CQL_OPERATION_H |
16 | | |
17 | | #include "yb/common/jsonb.h" |
18 | | #include "yb/common/ql_protocol.pb.h" |
19 | | #include "yb/common/typedefs.h" |
20 | | |
21 | | #include "yb/docdb/doc_expr.h" |
22 | | #include "yb/docdb/doc_key.h" |
23 | | #include "yb/docdb/doc_operation.h" |
24 | | #include "yb/docdb/intent_aware_iterator.h" |
25 | | |
26 | | namespace yb { |
27 | | |
28 | | class IndexInfo; |
29 | | class IndexMap; |
30 | | class QLResultSet; |
31 | | class QLRowBlock; |
32 | | |
33 | | namespace docdb { |
34 | | |
35 | | class QLWriteOperation : |
36 | | public DocOperationBase<DocOperationType::QL_WRITE_OPERATION, QLWriteRequestPB>, |
37 | | public DocExprExecutor { |
38 | | public: |
39 | | QLWriteOperation(std::reference_wrapper<const QLWriteRequestPB> request, |
40 | | std::shared_ptr<const Schema> schema, |
41 | | std::reference_wrapper<const IndexMap> index_map, |
42 | | const Schema* unique_index_key_schema, |
43 | | const TransactionOperationContext& txn_op_context); |
44 | | ~QLWriteOperation(); |
45 | | |
46 | | // Construct a QLWriteOperation. Content of request will be swapped out by the constructor. |
47 | | CHECKED_STATUS Init(QLResponsePB* response); |
48 | | |
49 | 3.38M | bool RequireReadSnapshot() const override { return require_read_; } |
50 | | |
51 | | CHECKED_STATUS GetDocPaths( |
52 | | GetDocPathsMode mode, DocPathsToLock *paths, IsolationLevel *level) const override; |
53 | | |
54 | | CHECKED_STATUS Apply(const DocOperationApplyData& data) override; |
55 | | |
56 | | CHECKED_STATUS ApplyForJsonOperators( |
57 | | std::unordered_map<ColumnIdRep, rapidjson::Document>* res_map, |
58 | | const QLColumnValuePB& column_value, |
59 | | const DocOperationApplyData& data, |
60 | | const DocPath& sub_path, const MonoDelta& ttl, |
61 | | const UserTimeMicros& user_timestamp, |
62 | | const ColumnSchema& column, |
63 | | QLTableRow* current_row, |
64 | | bool is_insert); |
65 | | |
66 | | CHECKED_STATUS ApplyForSubscriptArgs(const QLColumnValuePB& column_value, |
67 | | const QLTableRow& current_row, |
68 | | const DocOperationApplyData& data, |
69 | | const MonoDelta& ttl, |
70 | | const UserTimeMicros& user_timestamp, |
71 | | const ColumnSchema& column, |
72 | | DocPath* sub_path); |
73 | | |
74 | | CHECKED_STATUS ApplyForRegularColumns(const QLColumnValuePB& column_value, |
75 | | const QLTableRow& current_row, |
76 | | const DocOperationApplyData& data, |
77 | | const DocPath& sub_path, const MonoDelta& ttl, |
78 | | const UserTimeMicros& user_timestamp, |
79 | | const ColumnSchema& column, |
80 | | const ColumnId& column_id, |
81 | | QLTableRow* new_row); |
82 | | |
83 | 49.2k | const QLWriteRequestPB& request() const { return request_; } |
84 | 42.3k | QLResponsePB* response() const { return response_; } |
85 | | |
86 | 3.35M | std::vector<std::pair<const IndexInfo*, QLWriteRequestPB>>* index_requests() { |
87 | 3.35M | return &index_requests_; |
88 | 3.35M | } |
89 | | |
90 | | // Rowblock to return the "[applied]" status for conditional DML. |
91 | 3.34M | const QLRowBlock* rowblock() const { return rowblock_.get(); } |
92 | | |
93 | | MonoDelta request_ttl() const; |
94 | | |
95 | | private: |
96 | 0 | void ClearResponse() override { |
97 | 0 | if (response_) { |
98 | 0 | response_->Clear(); |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | // Initialize hashed_doc_key_ and/or pk_doc_key_. |
103 | | CHECKED_STATUS InitializeKeys(bool hashed_key, bool primary_key); |
104 | | |
105 | | CHECKED_STATUS ReadColumns(const DocOperationApplyData& data, |
106 | | Schema *static_projection, |
107 | | Schema *non_static_projection, |
108 | | QLTableRow* table_row); |
109 | | |
110 | | CHECKED_STATUS PopulateConditionalDmlRow(const DocOperationApplyData& data, |
111 | | bool should_apply, |
112 | | const QLTableRow& table_row, |
113 | | Schema static_projection, |
114 | | Schema non_static_projection, |
115 | | std::unique_ptr<QLRowBlock>* rowblock); |
116 | | |
117 | | CHECKED_STATUS PopulateStatusRow(const DocOperationApplyData& data, |
118 | | bool should_apply, |
119 | | const QLTableRow& table_row, |
120 | | std::unique_ptr<QLRowBlock>* rowblock); |
121 | | |
122 | | Result<bool> HasDuplicateUniqueIndexValue(const DocOperationApplyData& data); |
123 | | Result<bool> HasDuplicateUniqueIndexValue( |
124 | | const DocOperationApplyData& data, yb::docdb::Direction direction); |
125 | | Result<bool> HasDuplicateUniqueIndexValue( |
126 | | const DocOperationApplyData& data, ReadHybridTime read_time); |
127 | | Result<HybridTime> FindOldestOverwrittenTimestamp( |
128 | | IntentAwareIterator* iter, const SubDocKey& sub_doc_key, |
129 | | HybridTime min_hybrid_time); |
130 | | |
131 | | CHECKED_STATUS DeleteRow(const DocPath& row_path, DocWriteBatch* doc_write_batch, |
132 | | const ReadHybridTime& read_ht, CoarseTimePoint deadline); |
133 | | |
134 | | Result<bool> IsRowDeleted(const QLTableRow& current_row, const QLTableRow& new_row) const; |
135 | | |
136 | | CHECKED_STATUS UpdateIndexes(const QLTableRow& current_row, const QLTableRow& new_row); |
137 | | |
138 | | std::shared_ptr<const Schema> schema_; |
139 | | const IndexMap& index_map_; |
140 | | const Schema* unique_index_key_schema_ = nullptr; |
141 | | |
142 | | // Doc key and encoded Doc key for hashed key (i.e. without range columns). Present when there is |
143 | | // a static column being written. |
144 | | boost::optional<DocKey> hashed_doc_key_; |
145 | | RefCntPrefix encoded_hashed_doc_key_; |
146 | | |
147 | | // Doc key and encoded Doc key for primary key (i.e. with range columns). Present when there is a |
148 | | // non-static column being written or when writing the primary key alone (i.e. range columns are |
149 | | // present or table does not have range columns). |
150 | | boost::optional<DocKey> pk_doc_key_; |
151 | | RefCntPrefix encoded_pk_doc_key_; |
152 | | |
153 | | QLResponsePB* response_ = nullptr; |
154 | | |
155 | | std::vector<std::pair<const IndexInfo*, QLWriteRequestPB>> index_requests_; |
156 | | |
157 | | const TransactionOperationContext txn_op_context_; |
158 | | |
159 | | // The row that is returned to the CQL client for an INSERT/UPDATE/DELETE that has a |
160 | | // "... IF <condition> ..." clause. The row contains the "[applied]" status column |
161 | | // plus the values of all columns referenced in the if-clause if the condition is not satisfied. |
162 | | std::unique_ptr<QLRowBlock> rowblock_; |
163 | | |
164 | | // Does this write operation require a read? |
165 | | bool require_read_ = false; |
166 | | |
167 | | // Any indexes that may need update? |
168 | | bool update_indexes_ = false; |
169 | | |
170 | | // Is this an insert into a unique index? |
171 | | bool insert_into_unique_index_ = false; |
172 | | |
173 | | // Does the liveness column exist before the write operation? |
174 | | bool liveness_column_exists_ = false; |
175 | | }; |
176 | | |
177 | | Result<QLWriteRequestPB*> CreateAndSetupIndexInsertRequest( |
178 | | QLExprExecutor* expr_executor, |
179 | | bool index_has_write_permission, |
180 | | const QLTableRow& existing_row, |
181 | | const QLTableRow& new_row, |
182 | | const IndexInfo* index, |
183 | | std::vector<std::pair<const IndexInfo*, QLWriteRequestPB>>* index_requests, |
184 | | bool* has_index_key_changed = nullptr, |
185 | | bool* index_pred_new_row = nullptr, |
186 | | bool index_pred_existing_row = true); |
187 | | |
188 | | class QLReadOperation : public DocExprExecutor { |
189 | | public: |
190 | | QLReadOperation( |
191 | | const QLReadRequestPB& request, |
192 | | const TransactionOperationContext& txn_op_context) |
193 | 3.93M | : request_(request), txn_op_context_(txn_op_context) {} |
194 | | |
195 | | CHECKED_STATUS Execute(const YQLStorageIf& ql_storage, |
196 | | CoarseTimePoint deadline, |
197 | | const ReadHybridTime& read_time, |
198 | | const Schema& schema, |
199 | | const Schema& projection, |
200 | | QLResultSet* result_set, |
201 | | HybridTime* restart_read_ht); |
202 | | |
203 | | CHECKED_STATUS PopulateResultSet(const std::unique_ptr<QLScanSpec>& spec, |
204 | | const QLTableRow& table_row, |
205 | | QLResultSet *result_set); |
206 | | |
207 | | CHECKED_STATUS EvalAggregate(const QLTableRow& table_row); |
208 | | CHECKED_STATUS PopulateAggregate(const QLTableRow& table_row, QLResultSet *resultset); |
209 | | |
210 | | CHECKED_STATUS AddRowToResult(const std::unique_ptr<QLScanSpec>& spec, |
211 | | const QLTableRow& row, |
212 | | const size_t row_count_limit, |
213 | | const size_t offset, |
214 | | QLResultSet* resultset, |
215 | | int* match_count, |
216 | | size_t* num_rows_skipped); |
217 | | |
218 | | CHECKED_STATUS GetIntents(const Schema& schema, KeyValueWriteBatchPB* out); |
219 | | |
220 | 3.93M | QLResponsePB& response() { return response_; } |
221 | | |
222 | | private: |
223 | | |
224 | | // Checks whether we have processed enough rows for a page and sets the appropriate paging |
225 | | // state in the response object. |
226 | | CHECKED_STATUS SetPagingStateIfNecessary(const YQLRowwiseIteratorIf* iter, |
227 | | const QLResultSet* resultset, |
228 | | const size_t row_count_limit, |
229 | | const size_t num_rows_skipped, |
230 | | const ReadHybridTime& read_time); |
231 | | |
232 | | const QLReadRequestPB& request_; |
233 | | const TransactionOperationContext txn_op_context_; |
234 | | QLResponsePB response_; |
235 | | }; |
236 | | |
237 | | } // namespace docdb |
238 | | } // namespace yb |
239 | | |
240 | | #endif // YB_DOCDB_CQL_OPERATION_H |