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