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 * opitons)55 int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *opitons)
56 {
57 if (!IsValidRdbTransOptions(opitons)) {
58 return RDB_E_INVALID_ARGS;
59 }
60 delete opitons;
61 return RDB_OK;
62 }
63
OH_RdbTransOption_SetType(OH_RDB_TransOptions * opitons,OH_RDB_TransType type)64 int OH_RdbTransOption_SetType(OH_RDB_TransOptions *opitons, OH_RDB_TransType type)
65 {
66 if (!IsValidRdbTransOptions(opitons) || 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 opitons->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] =
142 trans->trans_->BatchInsertWithConflictResolution(table, datas, Utils::ConvertConflictResolution(resolution));
143 *changes = count;
144 if (errCode != E_OK) {
145 LOG_ERROR("batch insert fail, errCode=%{public}d count=%{public}" PRId64, errCode, count);
146 }
147 return ConvertorErrorCode::GetInterfaceCode(errCode);
148 }
149
OH_RdbTrans_Update(OH_Rdb_Transaction * trans,const OH_VBucket * row,const OH_Predicates * predicates,int64_t * changes)150 int OH_RdbTrans_Update(OH_Rdb_Transaction *trans, const OH_VBucket *row, const OH_Predicates *predicates,
151 int64_t *changes)
152 {
153 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
154 auto rdbValuesBucket = RelationalValuesBucket::GetSelf(const_cast<OH_VBucket *>(row));
155 if (!IsValidRdbTrans(trans) || rdbValuesBucket == nullptr || rdbPredicate == nullptr || changes == nullptr) {
156 return RDB_E_INVALID_ARGS;
157 }
158 auto [errCode, count] = trans->trans_->Update(rdbValuesBucket->Get(), rdbPredicate->Get());
159 *changes = count;
160 if (errCode != E_OK) {
161 LOG_ERROR("update fail, errCode=%{public}d count=%{public}d", errCode, count);
162 }
163 return ConvertorErrorCode::GetInterfaceCode(errCode);
164 }
165
OH_RdbTrans_Delete(OH_Rdb_Transaction * trans,const OH_Predicates * predicates,int64_t * changes)166 int OH_RdbTrans_Delete(OH_Rdb_Transaction *trans, const OH_Predicates *predicates, int64_t *changes)
167 {
168 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
169 if (!IsValidRdbTrans(trans) || rdbPredicate == nullptr || changes == nullptr) {
170 return RDB_E_INVALID_ARGS;
171 }
172
173 auto [errCode, count] = trans->trans_->Delete(rdbPredicate->Get());
174 *changes = count;
175 if (errCode != E_OK) {
176 LOG_ERROR("delete fail, errCode=%{public}d count=%{public}d", errCode, count);
177 }
178 return ConvertorErrorCode::GetInterfaceCode(errCode);
179 }
180
OH_RdbTrans_Query(OH_Rdb_Transaction * trans,const OH_Predicates * predicates,const char * columns[],int len)181 OH_Cursor *OH_RdbTrans_Query(OH_Rdb_Transaction *trans, const OH_Predicates *predicates, const char *columns[], int len)
182 {
183 auto rdbPredicate = RelationalPredicate::GetSelf(const_cast<OH_Predicates *>(predicates));
184 if (!IsValidRdbTrans(trans) || rdbPredicate == nullptr) {
185 return nullptr;
186 }
187 std::vector<std::string> fields;
188 if (columns != nullptr && len > 0) {
189 for (int i = 0; i < len; i++) {
190 fields.emplace_back(columns[i]);
191 }
192 }
193 auto resultSet = trans->trans_->QueryByStep(rdbPredicate->Get(), fields);
194 if (resultSet == nullptr) {
195 LOG_ERROR("resultSet is null.");
196 return nullptr;
197 }
198 return new (std::nothrow) RelationalCursor(std::move(resultSet));
199 }
200
OH_RdbTrans_QuerySql(OH_Rdb_Transaction * trans,const char * sql,const OH_Data_Values * args)201 OH_Cursor *OH_RdbTrans_QuerySql(OH_Rdb_Transaction *trans, const char *sql, const OH_Data_Values *args)
202 {
203 if (!IsValidRdbTrans(trans) || sql == nullptr || (args != nullptr && !args->IsValid())) {
204 return nullptr;
205 }
206 std::vector<ValueObject> datas;
207 if (args != nullptr) {
208 for (auto arg : args->values_) {
209 if (!arg.IsValid()) {
210 continue;
211 }
212 datas.push_back(arg.value_);
213 }
214 }
215 auto resultSet = trans->trans_->QueryByStep(sql, datas);
216 if (resultSet == nullptr) {
217 LOG_ERROR("resultSet is null.");
218 return nullptr;
219 }
220 return new (std::nothrow) RelationalCursor(std::move(resultSet));
221 }
222
OH_RdbTrans_Execute(OH_Rdb_Transaction * trans,const char * sql,const OH_Data_Values * args,OH_Data_Value ** result)223 int OH_RdbTrans_Execute(OH_Rdb_Transaction *trans, const char *sql, const OH_Data_Values *args, OH_Data_Value **result)
224 {
225 if (!IsValidRdbTrans(trans) || sql == nullptr || (args != nullptr && !args->IsValid())) {
226 return RDB_E_INVALID_ARGS;
227 }
228 std::vector<ValueObject> datas;
229 if (args != nullptr) {
230 for (auto arg : args->values_) {
231 if (!arg.IsValid()) {
232 continue;
233 }
234 datas.push_back(arg.value_);
235 }
236 }
237 auto [errCode, valueObj] = trans->trans_->Execute(sql, datas);
238 if (errCode != OHOS::NativeRdb::E_OK) {
239 LOG_ERROR("execute fail, errCode=%{public}d", errCode);
240 return ConvertorErrorCode::GetInterfaceCode(errCode);
241 }
242 if (result != nullptr) {
243 OH_Data_Value *value = OH_Value_Create();
244 if (value == nullptr) {
245 return RDB_E_ERROR;
246 }
247 value->value_ = valueObj;
248 *result = value;
249 }
250 return RDB_OK;
251 }
252
OH_RdbTrans_Destroy(OH_Rdb_Transaction * trans)253 int OH_RdbTrans_Destroy(OH_Rdb_Transaction *trans)
254 {
255 if (!IsValidRdbTrans(trans)) {
256 LOG_ERROR("invalid trans");
257 return RDB_E_INVALID_ARGS;
258 }
259 trans->trans_ = nullptr;
260 delete trans;
261 return RDB_OK;
262 }
263
IsValid() const264 bool OH_Rdb_Transaction::IsValid() const
265 {
266 if (trans_ == nullptr) {
267 return false;
268 }
269 return id == OH_RDB_TRANS_ID;
270 }
271
IsValid() const272 bool OH_RDB_TransOptions::IsValid() const
273 {
274 if (type_ < RDB_TRANS_DEFERRED || type_ >= RDB_TRANS_BUTT) {
275 LOG_ERROR("invalid type=%{public}d", type_);
276 return false;
277 }
278 return id == OH_TRANS_OPTION_ID;
279 }