• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }