1 /*
2  * Copyright (c) 2022 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 #include <gtest/gtest.h>
17 
18 #include <string>
19 
20 #include "common.h"
21 #include "rdb_errno.h"
22 #include "rdb_helper.h"
23 #include "rdb_open_callback.h"
24 
25 using namespace testing::ext;
26 using namespace OHOS::NativeRdb;
27 
28 static const std::string DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db";
29 static const char CREATE_TABLE_SQL[] =
30     "CREATE TABLE IF NOT EXISTS test "
31     "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)";
32 
33 class TransactionTest : public testing::Test {
34 public:
35     static void SetUpTestCase();
36     static void TearDownTestCase();
37     void SetUp() override;
38     void TearDown() override;
39 
40     static inline std::shared_ptr<RdbStore> store_;
41 
42     class TransactionTestOpenCallback : public RdbOpenCallback {
43     public:
44         int OnCreate(RdbStore &store) override;
45         int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
46     };
47 };
48 
49 
OnCreate(RdbStore & store)50 int TransactionTest::TransactionTestOpenCallback::OnCreate(RdbStore &store)
51 {
52     auto [ret, value] = store.Execute(CREATE_TABLE_SQL);
53     return ret;
54 }
55 
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)56 int TransactionTest::TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
57 {
58     return E_OK;
59 }
60 
SetUpTestCase()61 void TransactionTest::SetUpTestCase()
62 {
63     int errCode = E_OK;
64     RdbHelper::DeleteRdbStore(DATABASE_NAME);
65     RdbStoreConfig config(DATABASE_NAME);
66     TransactionTestOpenCallback helper;
67     TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode);
68     EXPECT_NE(TransactionTest::store_, nullptr);
69     EXPECT_EQ(errCode, E_OK);
70 }
71 
TearDownTestCase()72 void TransactionTest::TearDownTestCase()
73 {
74     store_ = nullptr;
75     RdbHelper::DeleteRdbStore(DATABASE_NAME);
76 }
77 
SetUp()78 void TransactionTest::SetUp()
79 {
80     store_->Execute("DELETE FROM test");
81 }
82 
TearDown()83 void TransactionTest::TearDown()
84 {
85 }
86 
87 /**
88  * @tc.name: RdbStore_Transaction_001
89  * @tc.desc: createTransaction and commit
90  * @tc.type: FUNC
91  */
92 HWTEST_F(TransactionTest, RdbStore_Transaction_001, TestSize.Level1)
93 {
94     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
95 
96     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
97     ASSERT_EQ(ret, E_OK);
98     ASSERT_NE(transaction, nullptr);
99 
100     auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
101     ASSERT_EQ(result.first, E_OK);
102     ASSERT_EQ(1, result.second);
103 
104     result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
105     ASSERT_EQ(result.first, E_OK);
106     ASSERT_EQ(2, result.second);
107 
108     result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
109     ASSERT_EQ(result.first, E_SQLITE_BUSY);
110 
111     auto resultSet = transaction->QueryByStep("SELECT * FROM test");
112     ASSERT_NE(resultSet, nullptr);
113     int32_t rowCount{};
114     ret = resultSet->GetRowCount(rowCount);
115     ASSERT_EQ(ret, E_OK);
116     ASSERT_EQ(rowCount, 2);
117 
118     ret = transaction->Commit();
119     ASSERT_EQ(ret, E_OK);
120 
121     ValueObject value;
122     ret = resultSet->Get(0, value);
123     ASSERT_EQ(ret, E_ALREADY_CLOSED);
124 
125     result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
126     ASSERT_EQ(result.first, E_OK);
127     ASSERT_EQ(3, result.second);
128 
129     result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
130     ASSERT_EQ(result.first, E_ALREADY_CLOSED);
131 
132     resultSet = store->QueryByStep("SELECT * FROM test");
133     ASSERT_NE(resultSet, nullptr);
134     resultSet->GetRowCount(rowCount);
135     EXPECT_EQ(rowCount, 3);
136 }
137 
138 /**
139  * @tc.name: RdbStore_Transaction_002
140  * @tc.desc: createTransaction and rollback
141  * @tc.type: FUNC
142  */
143 HWTEST_F(TransactionTest, RdbStore_Transaction_002, TestSize.Level1)
144 {
145     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
146 
147     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
148     ASSERT_EQ(ret, E_OK);
149     ASSERT_NE(transaction, nullptr);
150 
151     auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
152     ASSERT_EQ(result.first, E_OK);
153     ASSERT_EQ(1, result.second);
154 
155     result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
156     ASSERT_EQ(result.first, E_OK);
157     ASSERT_EQ(2, result.second);
158 
159     ret = transaction->Rollback();
160     ASSERT_EQ(ret, E_OK);
161 
162     auto resultSet = store->QueryByStep("SELECT * FROM test");
163     ASSERT_NE(resultSet, nullptr);
164     int32_t rowCount{};
165     ret = resultSet->GetRowCount(rowCount);
166     ASSERT_EQ(ret, E_OK);
167     ASSERT_EQ(rowCount, 0);
168 
169     result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
170     ASSERT_EQ(result.first, E_OK);
171     ASSERT_EQ(3, result.second);
172 
173     result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
174     ASSERT_EQ(result.first, E_ALREADY_CLOSED);
175 
176     resultSet = store->QueryByStep("SELECT * FROM test");
177     ASSERT_NE(resultSet, nullptr);
178     ret = resultSet->GetRowCount(rowCount);
179     EXPECT_EQ(ret, E_OK);
180     EXPECT_EQ(rowCount, 1);
181 }
182 
183 /**
184  * @tc.name: RdbStore_Transaction_003
185  * @tc.desc: batchInsert
186  * @tc.type: FUNC
187  */
188 HWTEST_F(TransactionTest, RdbStore_Transaction_003, TestSize.Level1)
189 {
190     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
191 
192     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
193     ASSERT_EQ(ret, E_OK);
194     ASSERT_NE(transaction, nullptr);
195 
196     Transaction::Rows rows {
197         UTUtils::SetRowData(UTUtils::g_rowData[0]),
198         UTUtils::SetRowData(UTUtils::g_rowData[1]),
199         UTUtils::SetRowData(UTUtils::g_rowData[2]),
200     };
201     auto result = transaction->BatchInsert("test", rows);
202     ASSERT_EQ(result.first, E_OK);
203     ASSERT_EQ(result.second, 3);
204 
205     ret = transaction->Commit();
206     ASSERT_EQ(ret, E_OK);
207 
208     auto resultSet = store->QueryByStep("SELECT * FROM test");
209     ASSERT_NE(resultSet, nullptr);
210     int32_t rowCount{};
211     ret = resultSet->GetRowCount(rowCount);
212     EXPECT_EQ(ret, E_OK);
213     EXPECT_EQ(rowCount, 3);
214 }
215 
216 /**
217  * @tc.name: RdbStore_Transaction_004
218  * @tc.desc: batchInsert
219  * @tc.type: FUNC
220  */
221 HWTEST_F(TransactionTest, RdbStore_Transaction_004, TestSize.Level1)
222 {
223     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
224 
225     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
226     ASSERT_EQ(ret, E_OK);
227     ASSERT_NE(transaction, nullptr);
228 
229     Transaction::RefRows rows;
230     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
231     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
232     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
233 
234     auto result = transaction->BatchInsert("test", rows);
235     ASSERT_EQ(result.first, E_OK);
236     ASSERT_EQ(result.second, 3);
237 
238     ret = transaction->Commit();
239     ASSERT_EQ(ret, E_OK);
240 
241     auto resultSet = store->QueryByStep("SELECT * FROM test");
242     ASSERT_NE(resultSet, nullptr);
243     int32_t rowCount{};
244     ret = resultSet->GetRowCount(rowCount);
245     EXPECT_EQ(ret, E_OK);
246     EXPECT_EQ(rowCount, 3);
247 }
248 
249 /**
250  * @tc.name: RdbStore_Transaction_005
251  * @tc.desc: Update
252  * @tc.type: FUNC
253  */
254 HWTEST_F(TransactionTest, RdbStore_Transaction_005, TestSize.Level1)
255 {
256     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
257 
258     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
259     ASSERT_EQ(ret, E_OK);
260     ASSERT_NE(transaction, nullptr);
261 
262     auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
263     ASSERT_EQ(result.first, E_OK);
264     ASSERT_EQ(result.second, 1);
265 
266     result = transaction->Update("test", UTUtils::SetRowData(UTUtils::g_rowData[1]), "id=1");
267     ASSERT_EQ(result.first, E_OK);
268     ASSERT_EQ(result.second, 1);
269 
270     auto resultSet = transaction->QueryByStep("SELECT * FROM test");
271     ASSERT_NE(resultSet, nullptr);
272     int32_t rowCount{};
273     ret = resultSet->GetRowCount(rowCount);
274     ASSERT_EQ(ret, E_OK);
275     ASSERT_EQ(rowCount, 1);
276     ret = resultSet->GoToFirstRow();
277     ASSERT_EQ(ret, E_OK);
278     int32_t columnIndex{};
279     ret = resultSet->GetColumnIndex("id", columnIndex);
280     ASSERT_EQ(ret, E_OK);
281     int32_t id{};
282     ret = resultSet->GetInt(columnIndex, id);
283     ASSERT_EQ(ret, E_OK);
284     ASSERT_EQ(id, 2);
285 
286     AbsRdbPredicates predicates("test");
287     predicates.EqualTo("id", ValueObject(2));
288     result = transaction->Update(UTUtils::SetRowData(UTUtils::g_rowData[2]), predicates);
289     ASSERT_EQ(result.first, E_OK);
290     ASSERT_EQ(result.second, 1);
291 
292     ret = transaction->Commit();
293     ASSERT_EQ(ret, E_OK);
294 
295     resultSet = store->QueryByStep("SELECT * FROM test");
296     ASSERT_NE(resultSet, nullptr);
297     ret = resultSet->GetRowCount(rowCount);
298     ASSERT_EQ(ret, E_OK);
299     ASSERT_EQ(rowCount, 1);
300     ret = resultSet->GoToFirstRow();
301     ASSERT_EQ(ret, E_OK);
302     resultSet->GetColumnIndex("id", columnIndex);
303     ret = resultSet->GetInt(columnIndex, id);
304     EXPECT_EQ(ret, E_OK);
305     EXPECT_EQ(id, 3);
306 }
307 
308 /**
309  * @tc.name: RdbStore_Transaction_006
310  * @tc.desc: Delete
311  * @tc.type: FUNC
312  */
313 HWTEST_F(TransactionTest, RdbStore_Transaction_006, TestSize.Level1)
314 {
315     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
316 
317     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
318     ASSERT_EQ(ret, E_OK);
319     ASSERT_NE(transaction, nullptr);
320 
321     Transaction::RefRows rows;
322     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
323     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
324     rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
325 
326     auto result = transaction->BatchInsert("test", rows);
327     ASSERT_EQ(result.first, E_OK);
328     ASSERT_EQ(result.second, 3);
329 
330     result = transaction->Delete("test", "id=1");
331     ASSERT_EQ(result.first, E_OK);
332     ASSERT_EQ(result.second, 1);
333 
334     AbsRdbPredicates predicates("test");
335     predicates.EqualTo("id", ValueObject(2));
336     result = transaction->Delete(predicates);
337     ASSERT_EQ(result.first, E_OK);
338     ASSERT_EQ(result.second, 1);
339 
340     ret = transaction->Commit();
341     ASSERT_EQ(ret, E_OK);
342 
343     auto resultSet = store->QueryByStep("SELECT * FROM test");
344     ASSERT_NE(resultSet, nullptr);
345     int32_t rowCount{};
346     ret = resultSet->GetRowCount(rowCount);
347     ASSERT_EQ(ret, E_OK);
348     ASSERT_EQ(rowCount, 1);
349     ret = resultSet->GoToFirstRow();
350     ASSERT_EQ(ret, E_OK);
351     int32_t columnIndex{};
352     resultSet->GetColumnIndex("id", columnIndex);
353     int32_t id{};
354     ret = resultSet->GetInt(columnIndex, id);
355     EXPECT_EQ(ret, E_OK);
356     EXPECT_EQ(id, 3);
357 }
358 
359 /**
360  * @tc.name: RdbStore_Transaction_007
361  * @tc.desc: Execute
362  * @tc.type: FUNC
363  */
364 HWTEST_F(TransactionTest, RdbStore_Transaction_007, TestSize.Level1)
365 {
366     std::shared_ptr<RdbStore> &store = TransactionTest::store_;
367 
368     auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
369     ASSERT_EQ(ret, E_OK);
370     ASSERT_NE(transaction, nullptr);
371 
372     auto res = transaction->Execute(
373         "CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
374     ASSERT_EQ(res.first, E_OK);
375     Transaction::Row row;
376     row.Put("id", 1);
377     row.Put("name", "Jim");
378     auto result = transaction->Insert("test1", row);
379     ASSERT_EQ(result.first, E_OK);
380     ASSERT_EQ(result.second, 1);
381 
382     ret = transaction->Commit();
383     ASSERT_EQ(ret, E_OK);
384 
385     auto resultSet = store->QueryByStep("SELECT * FROM test1");
386     ASSERT_NE(resultSet, nullptr);
387     int32_t rowCount{};
388     ret = resultSet->GetRowCount(rowCount);
389     EXPECT_EQ(ret, E_OK);
390     EXPECT_EQ(rowCount, 1);
391 }
392