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 "TransactionImpl"
17
18 #include "transaction_impl.h"
19 #include "logger.h"
20 #include "rdb_errno.h"
21 #include "rdb_store.h"
22 #include "trans_db.h"
23
24 using namespace OHOS::Rdb;
25 namespace OHOS::NativeRdb {
26
27 __attribute__((used))
28 const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create);
29
TransactionImpl(std::shared_ptr<Connection> connection,const std::string & name)30 TransactionImpl::TransactionImpl(std::shared_ptr<Connection> connection, const std::string &name)
31 : name_(name), connection_(std::move(connection))
32 {
33 LOG_INFO("constructor name=%{public}s", name_.c_str());
34 }
35
~TransactionImpl()36 TransactionImpl::~TransactionImpl()
37 {
38 LOG_INFO("destructor name=%{public}s", name_.c_str());
39 CloseInner();
40 }
41
Create(int32_t type,std::shared_ptr<Connection> connection,const std::string & name)42 std::pair<int32_t, std::shared_ptr<Transaction>> TransactionImpl::Create(
43 int32_t type, std::shared_ptr<Connection> connection, const std::string &name)
44 {
45 auto trans = std::make_shared<TransactionImpl>(std::move(connection), name);
46 if (trans == nullptr) {
47 return { E_ERROR, nullptr };
48 }
49 auto errorCode = trans->Begin(type);
50 if (errorCode != E_OK) {
51 LOG_ERROR("transaction begin failed, errorCode=%{public}d", errorCode);
52 return { errorCode, nullptr };
53 }
54 return { E_OK, trans };
55 }
56
GetBeginSql(int32_t type)57 std::string TransactionImpl::GetBeginSql(int32_t type)
58 {
59 if (type < TransactionType::DEFERRED || type >= static_cast<int32_t>(TransactionType::TRANS_BUTT)) {
60 LOG_ERROR("invalid type=%{public}d", type);
61 return {};
62 }
63 return BEGIN_SQLS[type];
64 }
65
Begin(int32_t type)66 int32_t TransactionImpl::Begin(int32_t type)
67 {
68 LOG_INFO("type=%{public}d", static_cast<int32_t>(type));
69 std::lock_guard lock(mutex_);
70 store_ = std::make_shared<TransDB>(connection_, name_);
71 if (store_ == nullptr) {
72 return E_ERROR;
73 }
74 auto beginSql = GetBeginSql(type);
75 if (beginSql.empty()) {
76 CloseInner();
77 return E_INVALID_ARGS;
78 }
79 auto [errorCode, statement] = connection_->CreateStatement(beginSql, connection_);
80 if (errorCode != E_OK) {
81 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
82 CloseInner();
83 return errorCode;
84 }
85 errorCode = statement->Execute();
86 if (errorCode != E_OK) {
87 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
88 CloseInner();
89 return errorCode;
90 }
91 return E_OK;
92 }
93
Commit()94 int32_t TransactionImpl::Commit()
95 {
96 std::lock_guard lock(mutex_);
97 if (connection_ == nullptr) {
98 LOG_ERROR("connection already closed");
99 return E_ALREADY_CLOSED;
100 }
101
102 auto [errorCode, statement] = connection_->CreateStatement(COMMIT_SQL, connection_);
103 if (errorCode != E_OK) {
104 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
105 CloseInner();
106 return errorCode;
107 }
108
109 errorCode = statement->Execute();
110 CloseInner();
111 if (errorCode != E_OK) {
112 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
113 return errorCode;
114 }
115 return E_OK;
116 }
117
Rollback()118 int32_t TransactionImpl::Rollback()
119 {
120 std::lock_guard lock(mutex_);
121 if (connection_ == nullptr) {
122 LOG_ERROR("connection already closed");
123 return E_ALREADY_CLOSED;
124 }
125
126 auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_SQL, connection_);
127 if (errorCode != E_OK) {
128 LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode);
129 CloseInner();
130 return errorCode;
131 }
132
133 errorCode = statement->Execute();
134 CloseInner();
135 if (errorCode != E_OK) {
136 LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode);
137 return errorCode;
138 }
139 return E_OK;
140 }
141
CloseInner()142 int32_t TransactionImpl::CloseInner()
143 {
144 std::lock_guard lock(mutex_);
145 store_ = nullptr;
146 connection_ = nullptr;
147 for (auto &resultSet : resultSets_) {
148 auto sp = resultSet.lock();
149 if (sp != nullptr) {
150 sp->Close();
151 }
152 }
153 return E_OK;
154 }
155
Close()156 int32_t TransactionImpl::Close()
157 {
158 return CloseInner();
159 }
160
GetStore()161 std::shared_ptr<RdbStore> TransactionImpl::GetStore()
162 {
163 std::lock_guard lock(mutex_);
164 return store_;
165 }
166
Insert(const std::string & table,const Row & row,Resolution resolution)167 std::pair<int, int64_t> TransactionImpl::Insert(const std::string &table, const Row &row, Resolution resolution)
168 {
169 auto store = GetStore();
170 if (store == nullptr) {
171 LOG_ERROR("transaction already close");
172 return { E_ALREADY_CLOSED, -1 };
173 }
174 return store->Insert(table, row, resolution);
175 }
176
BatchInsert(const std::string & table,const Rows & rows)177 std::pair<int32_t, int64_t> TransactionImpl::BatchInsert(const std::string &table, const Rows &rows)
178 {
179 auto store = GetStore();
180 if (store == nullptr) {
181 LOG_ERROR("transaction already close");
182 return { E_ALREADY_CLOSED, -1 };
183 }
184 int64_t insertRows{};
185 auto errorCode = store->BatchInsert(insertRows, table, rows);
186 return { errorCode, insertRows };
187 }
188
BatchInsert(const std::string & table,const RefRows & rows)189 std::pair<int, int64_t> TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows)
190 {
191 auto store = GetStore();
192 if (store == nullptr) {
193 LOG_ERROR("transaction already close");
194 return { E_ALREADY_CLOSED, -1 };
195 }
196 return store->BatchInsert(table, rows);
197 }
198
Update(const std::string & table,const Row & row,const std::string & where,const Values & args,Resolution resolution)199 std::pair<int, int> TransactionImpl::Update(const std::string &table, const Row &row, const std::string &where,
200 const Values &args, Resolution resolution)
201 {
202 auto store = GetStore();
203 if (store == nullptr) {
204 LOG_ERROR("transaction already close");
205 return { E_ALREADY_CLOSED, -1 };
206 }
207 return store->Update(table, row, where, args, resolution);
208 }
209
Update(const Row & row,const AbsRdbPredicates & predicates,Resolution resolution)210 std::pair<int32_t, int32_t> TransactionImpl::Update(const Row &row, const AbsRdbPredicates &predicates,
211 Resolution resolution)
212 {
213 auto store = GetStore();
214 if (store == nullptr) {
215 LOG_ERROR("transaction already close");
216 return { E_ALREADY_CLOSED, -1 };
217 }
218 return store->Update(predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs(),
219 resolution);
220 }
221
Delete(const std::string & table,const std::string & whereClause,const Values & args)222 std::pair<int32_t, int32_t> TransactionImpl::Delete(const std::string &table, const std::string &whereClause,
223 const Values &args)
224 {
225 auto store = GetStore();
226 if (store == nullptr) {
227 LOG_ERROR("transaction already close");
228 return { E_ALREADY_CLOSED, -1 };
229 }
230 int deletedRows{};
231 auto errorCode = store->Delete(deletedRows, table, whereClause, args);
232 return { errorCode, deletedRows };
233 }
234
Delete(const AbsRdbPredicates & predicates)235 std::pair<int32_t, int32_t> TransactionImpl::Delete(const AbsRdbPredicates &predicates)
236 {
237 auto store = GetStore();
238 if (store == nullptr) {
239 LOG_ERROR("transaction already close");
240 return { E_ALREADY_CLOSED, -1 };
241 }
242 int deletedRows{};
243 auto errorCode = store->Delete(deletedRows, predicates);
244 return { errorCode, deletedRows };
245 }
246
AddResultSet(std::weak_ptr<ResultSet> resultSet)247 void TransactionImpl::AddResultSet(std::weak_ptr<ResultSet> resultSet)
248 {
249 std::lock_guard lock(mutex_);
250 resultSets_.push_back(std::move(resultSet));
251 }
252
QueryByStep(const std::string & sql,const Values & args,bool preCount)253 std::shared_ptr<ResultSet> TransactionImpl::QueryByStep(const std::string &sql, const Values &args, bool preCount)
254 {
255 auto store = GetStore();
256 if (store == nullptr) {
257 LOG_ERROR("transaction already close");
258 return nullptr;
259 }
260 auto resultSet = store->QueryByStep(sql, args);
261 if (resultSet != nullptr) {
262 AddResultSet(resultSet);
263 }
264 return resultSet;
265 }
266
QueryByStep(const AbsRdbPredicates & predicates,const Fields & columns,bool preCount)267 std::shared_ptr<ResultSet> TransactionImpl::QueryByStep(const AbsRdbPredicates &predicates,
268 const Fields &columns, bool preCount)
269 {
270 auto store = GetStore();
271 if (store == nullptr) {
272 LOG_ERROR("transaction already close");
273 return nullptr;
274 }
275 auto resultSet = store->QueryByStep(predicates, columns);
276 if (resultSet != nullptr) {
277 AddResultSet(resultSet);
278 }
279 return resultSet;
280 }
281
Execute(const std::string & sql,const Values & args)282 std::pair<int32_t, ValueObject> TransactionImpl::Execute(const std::string &sql, const Values &args)
283 {
284 auto store = GetStore();
285 if (store == nullptr) {
286 LOG_ERROR("transaction already close");
287 return { E_ALREADY_CLOSED, ValueObject() };
288 }
289 return store->Execute(sql, args);
290 }
291 }
292