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