1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * 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
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #define LOG_TAG "RdbTransaction"
17
18 #include "oh_rdb_transaction.h"
19 #include "oh_data_define.h"
20 #include "oh_data_utils.h"
21 #include "relational_values_bucket.h"
22 #include "relational_store_error_code.h"
23 #include "convertor_error_code.h"
24 #include "relational_predicates.h"
25 #include "relational_cursor.h"
26 #include "logger.h"
27
28 using namespace OHOS::RdbNdk;
29 using namespace OHOS::NativeRdb;
30
IsValidRdbTransOptions(const OH_RDB_TransOptions * options)31 static bool IsValidRdbTransOptions(const OH_RDB_TransOptions *options)
32 {
33 if (options == nullptr) {
34 LOG_ERROR("options is null");
35 return false;
36 }
37 bool ret = options->IsValid();
38 if (!ret) {
39 LOG_ERROR("invalid transaction options object.");
40 }
41 return ret;
42 }
43
OH_RdbTrans_CreateOptions(void)44 OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(void)
45 {
46 OH_RDB_TransOptions *value = new (std::nothrow) OH_RDB_TransOptions;
47 if (value == nullptr) {
48 LOG_ERROR("new OH_RDB_TransOptions failed.");
49 return nullptr;
50 }
51 value->type_ = RDB_TRANS_DEFERRED;
52 return value;
53 }
54
OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions * options)55 int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *options)
56 {
57 if (!IsValidRdbTransOptions(options)) {
58 return RDB_E_INVALID_ARGS;
59 }
60 delete options;
61 return RDB_OK;
62 }
63
OH_RdbTransOption_SetType(OH_RDB_TransOptions * options,OH_RDB_TransType type)64 int OH_RdbTransOption_SetType(OH_RDB_TransOptions *options, OH_RDB_TransType type)
65 {
66 if (!IsValidRdbTransOptions(options) || type < RDB_TRANS_DEFERRED || type >= RDB_TRANS_BUTT) {
67 LOG_ERROR("invalid options, type=%{public}d.", type);
68 return RDB_E_INVALID_ARGS;
69 }
70 options->type_ = type;
71 return RDB_OK;
72 }
73
IsValidRdbTrans(const OH_Rdb_Transaction * trans)74 static bool IsValidRdbTrans(const OH_Rdb_Transaction *trans)
75 {
76 if (trans == nullptr || trans->trans_ == nullptr) {
77 LOG_ERROR("trans param has null data");
78 return false;
79 }
80 bool ret = trans->IsValid();
81 if (!ret) {
82 LOG_ERROR("invalid transaction object.");
83 }
84 return ret;
85 }
86
OH_RdbTrans_Commit(OH_Rdb_Transaction * trans)87 int OH_RdbTrans_Commit(OH_Rdb_Transaction *trans)
88 {
89 if (!IsValidRdbTrans(trans)) {
90 return RDB_E_INVALID_ARGS;
91 }
92 auto errCode = trans->trans_->Commit();
93 if (errCode != E_OK) {
94 LOG_ERROR("commit fail, errCode=%{public}d", errCode);
95 }
96 return ConvertorErrorCode::GetInterfaceCode(errCode);
97 }
98
OH_RdbTrans_Rollback(OH_Rdb_Transaction * trans)99 int OH_RdbTrans_Rollback(OH_Rdb_Transaction *trans)
100 {
101 if (!IsValidRdbTrans(trans)) {
102 return RDB_E_INVALID_ARGS;
103 }
104 auto errCode = trans->trans_->Rollback();
105 if (errCode != E_OK) {
106 LOG_ERROR("commit fail, errCode=%{public}d", errCode);
107 }
108 return ConvertorErrorCode::GetInterfaceCode(errCode);
109 }
110
OH_RdbTrans_Insert(OH_Rdb_Transaction * trans,const char * table,const OH_VBucket * row,int64_t * rowId)111 int OH_RdbTrans_Insert(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, int64_t *rowId)
112 {
113 auto valuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(row));
114 if (!IsValidRdbTrans(trans) || table == nullptr || valuesBucket == nullptr || rowId == nullptr) {
115 return RDB_E_INVALID_ARGS;
116 }
117
118 auto [errCode, id] = trans->trans_->Insert(table, valuesBucket->Get());
119 *rowId = id;
120 if (errCode != E_OK) {
121 LOG_ERROR("insert fail, errCode=%{public}d id=%{public}" PRId64, errCode, id);
122 }
123 return ConvertorErrorCode::GetInterfaceCode(errCode);
124 }
125
OH_RdbTrans_BatchInsert(OH_Rdb_Transaction * trans,const char * table,const OH_Data_VBuckets * rows,Rdb_ConflictResolution resolution,int64_t * changes)126 int OH_RdbTrans_BatchInsert(OH_Rdb_Transaction *trans, const char *table, const OH_Data_VBuckets *rows,
127 Rdb_ConflictResolution resolution, int64_t *changes)
128 {
129 if (!IsValidRdbTrans(trans) || table == nullptr || rows == nullptr || !rows->IsValid() || changes == nullptr ||
130 resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) {
131 return RDB_E_INVALID_ARGS;
132 }
133 ValuesBuckets datas;
134 for (size_t i = 0; i < rows->rows_.size(); i++) {
135 auto valuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(rows->rows_[i]));
136 if (valuesBucket == nullptr) {
137 continue;
138 }
139 datas.Put(valuesBucket->Get());
140 }
141 auto [errCode, count] = trans->trans_->BatchInsert(table, datas, Utils::ConvertConflictResolution(resolution));
142 *changes = count;
143 if (errCode != E_OK) {
144 LOG_ERROR("batch insert fail, errCode=%{public}d count=%{public}" PRId64, errCode, count);
145 }
146 return ConvertorErrorCode::GetInterfaceCode(errCode);
147 }
148
OH_RdbTrans_Update(OH_Rdb_Transaction * trans,const OH_VBucket * row,const OH_Predicates * predicates,int64_t * changes)149 int OH_RdbTrans_Update(OH_Rdb_Transaction *trans, const OH_VBucket *row, const OH_Predicates *predicates,
150 int64_t *changes)
151 {
152 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
153 auto rdbValuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(row));
154 if (!IsValidRdbTrans(trans) || rdbValuesBucket == nullptr || rdbPredicate == nullptr || changes == nullptr) {
155 return RDB_E_INVALID_ARGS;
156 }
157 auto [errCode, count] = trans->trans_->Update(rdbValuesBucket->Get(), rdbPredicate->Get());
158 *changes = count;
159 if (errCode != E_OK) {
160 LOG_ERROR("update fail, errCode=%{public}d count=%{public}d", errCode, count);
161 }
162 return ConvertorErrorCode::GetInterfaceCode(errCode);
163 }
164
OH_RdbTrans_Delete(OH_Rdb_Transaction * trans,const OH_Predicates * predicates,int64_t * changes)165 int OH_RdbTrans_Delete(OH_Rdb_Transaction *trans, const OH_Predicates *predicates, int64_t *changes)
166 {
167 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
168 if (!IsValidRdbTrans(trans) || rdbPredicate == nullptr || changes == nullptr) {
169 return RDB_E_INVALID_ARGS;
170 }
171
172 auto [errCode, count] = trans->trans_->Delete(rdbPredicate->Get());
173 *changes = count;
174 if (errCode != E_OK) {
175 LOG_ERROR("delete fail, errCode=%{public}d count=%{public}d", errCode, count);
176 }
177 return ConvertorErrorCode::GetInterfaceCode(errCode);
178 }
179
OH_RdbTrans_Query(OH_Rdb_Transaction * trans,const OH_Predicates * predicates,const char * columns[],int len)180 OH_Cursor *OH_RdbTrans_Query(OH_Rdb_Transaction *trans, const OH_Predicates *predicates, const char *columns[], int len)
181 {
182 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
183 if (!IsValidRdbTrans(trans) || rdbPredicate == nullptr) {
184 return nullptr;
185 }
186 std::vector<std::string> fields;
187 if (columns != nullptr && len > 0) {
188 for (int i = 0; i < len; i++) {
189 fields.emplace_back(columns[i]);
190 }
191 }
192 auto resultSet = trans->trans_->QueryByStep(rdbPredicate->Get(), fields);
193 if (resultSet == nullptr) {
194 LOG_ERROR("resultSet is null.");
195 return nullptr;
196 }
197 return new (std::nothrow) RelationalCursor(std::move(resultSet));
198 }
199
OH_RdbTrans_QuerySql(OH_Rdb_Transaction * trans,const char * sql,const OH_Data_Values * args)200 OH_Cursor *OH_RdbTrans_QuerySql(OH_Rdb_Transaction *trans, const char *sql, const OH_Data_Values *args)
201 {
202 if (!IsValidRdbTrans(trans) || sql == nullptr || (args != nullptr && !args->IsValid())) {
203 return nullptr;
204 }
205 std::vector<ValueObject> datas;
206 if (args != nullptr) {
207 for (auto arg : args->values_) {
208 if (!arg.IsValid()) {
209 continue;
210 }
211 datas.push_back(arg.value_);
212 }
213 }
214 auto resultSet = trans->trans_->QueryByStep(sql, datas);
215 if (resultSet == nullptr) {
216 LOG_ERROR("resultSet is null.");
217 return nullptr;
218 }
219 return new (std::nothrow) RelationalCursor(std::move(resultSet));
220 }
221
OH_RdbTrans_Execute(OH_Rdb_Transaction * trans,const char * sql,const OH_Data_Values * args,OH_Data_Value ** result)222 int OH_RdbTrans_Execute(OH_Rdb_Transaction *trans, const char *sql, const OH_Data_Values *args, OH_Data_Value **result)
223 {
224 if (!IsValidRdbTrans(trans) || sql == nullptr || (args != nullptr && !args->IsValid())) {
225 return RDB_E_INVALID_ARGS;
226 }
227 std::vector<ValueObject> datas;
228 if (args != nullptr) {
229 for (auto arg : args->values_) {
230 if (!arg.IsValid()) {
231 continue;
232 }
233 datas.push_back(arg.value_);
234 }
235 }
236 auto [errCode, valueObj] = trans->trans_->Execute(sql, datas);
237 if (errCode != OHOS::NativeRdb::E_OK) {
238 LOG_ERROR("execute fail, errCode=%{public}d", errCode);
239 return ConvertorErrorCode::GetInterfaceCode(errCode);
240 }
241 if (result != nullptr) {
242 OH_Data_Value *value = OH_Value_Create();
243 if (value == nullptr) {
244 return RDB_E_ERROR;
245 }
246 value->value_ = valueObj;
247 *result = value;
248 }
249 return RDB_OK;
250 }
251
OH_RdbTrans_Destroy(OH_Rdb_Transaction * trans)252 int OH_RdbTrans_Destroy(OH_Rdb_Transaction *trans)
253 {
254 if (!IsValidRdbTrans(trans)) {
255 LOG_ERROR("invalid trans");
256 return RDB_E_INVALID_ARGS;
257 }
258 trans->trans_ = nullptr;
259 delete trans;
260 return RDB_OK;
261 }
262
IsValid() const263 bool OH_Rdb_Transaction::IsValid() const
264 {
265 if (trans_ == nullptr) {
266 return false;
267 }
268 return id == OH_RDB_TRANS_ID;
269 }
270
IsValid() const271 bool OH_RDB_TransOptions::IsValid() const
272 {
273 if (type_ < RDB_TRANS_DEFERRED || type_ >= RDB_TRANS_BUTT) {
274 LOG_ERROR("invalid type=%{public}d", type_);
275 return false;
276 }
277 return id == OH_TRANS_OPTION_ID;
278 }
279
OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction * trans,const char * table,const OH_VBucket * row,Rdb_ConflictResolution resolution,int64_t * rowId)280 int OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row,
281 Rdb_ConflictResolution resolution, int64_t *rowId)
282 {
283 auto valuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(row));
284 if (!IsValidRdbTrans(trans) || table == nullptr || valuesBucket == nullptr || rowId == nullptr ||
285 resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) {
286 return RDB_E_INVALID_ARGS;
287 }
288
289 auto [err, id] = trans->trans_->Insert(table, valuesBucket->Get(), Utils::ConvertConflictResolution(resolution));
290 *rowId = id;
291 if (err != E_OK) {
292 LOG_ERROR("insert with conflict resolution fail,errCode=%{public}x,resolution=%{public}d,id=%{public}" PRId64,
293 err, resolution, id);
294 }
295 return ConvertorErrorCode::GetInterfaceCode(err);
296 }
297
OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction * trans,const OH_VBucket * row,const OH_Predicates * predicates,Rdb_ConflictResolution resolution,int64_t * changes)298 int OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction *trans, const OH_VBucket *row,
299 const OH_Predicates *predicates, Rdb_ConflictResolution resolution, int64_t *changes)
300 {
301 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
302 auto rdbValuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(row));
303 if (!IsValidRdbTrans(trans) || rdbValuesBucket == nullptr || rdbPredicate == nullptr || changes == nullptr ||
304 resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) {
305 return RDB_E_INVALID_ARGS;
306 }
307 auto [err, count] = trans->trans_->Update(rdbValuesBucket->Get(), rdbPredicate->Get(),
308 Utils::ConvertConflictResolution(resolution));
309 *changes = count;
310 if (err != E_OK) {
311 LOG_ERROR("update with conflict resolution fail, errCode=%{public}x,resolution=%{public}d,count=%{public}d",
312 err, resolution, count);
313 }
314 return ConvertorErrorCode::GetInterfaceCode(err);
315 }