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
OnCreate(RdbStore & store)49 int TransactionTest::TransactionTestOpenCallback::OnCreate(RdbStore &store)
50 {
51 auto [ret, value] = store.Execute(CREATE_TABLE_SQL);
52 return ret;
53 }
54
OnUpgrade(RdbStore & store,int oldVersion,int newVersion)55 int TransactionTest::TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
56 {
57 return E_OK;
58 }
59
SetUpTestCase()60 void TransactionTest::SetUpTestCase()
61 {
62 int errCode = E_OK;
63 RdbHelper::DeleteRdbStore(DATABASE_NAME);
64 RdbStoreConfig config(DATABASE_NAME);
65 TransactionTestOpenCallback helper;
66 TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode);
67 EXPECT_NE(TransactionTest::store_, nullptr);
68 EXPECT_EQ(errCode, E_OK);
69 }
70
TearDownTestCase()71 void TransactionTest::TearDownTestCase()
72 {
73 store_ = nullptr;
74 RdbHelper::DeleteRdbStore(DATABASE_NAME);
75 }
76
SetUp()77 void TransactionTest::SetUp()
78 {
79 store_->Execute("DELETE FROM test");
80 }
81
TearDown()82 void TransactionTest::TearDown()
83 {
84 }
85
86 /**
87 * @tc.name: RdbStore_Transaction_001
88 * @tc.desc: createTransaction and commit
89 * @tc.type: FUNC
90 */
91 HWTEST_F(TransactionTest, RdbStore_Transaction_001, TestSize.Level1)
92 {
93 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
94
95 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
96 ASSERT_EQ(ret, E_OK);
97 ASSERT_NE(transaction, nullptr);
98
99 auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
100 ASSERT_EQ(result.first, E_OK);
101 ASSERT_EQ(1, result.second);
102
103 result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
104 ASSERT_EQ(result.first, E_OK);
105 ASSERT_EQ(2, result.second);
106
107 result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
108 ASSERT_EQ(result.first, E_SQLITE_BUSY);
109
110 auto resultSet = transaction->QueryByStep("SELECT * FROM test");
111 ASSERT_NE(resultSet, nullptr);
112 int32_t rowCount{};
113 ret = resultSet->GetRowCount(rowCount);
114 ASSERT_EQ(ret, E_OK);
115 ASSERT_EQ(rowCount, 2);
116
117 ret = transaction->Commit();
118 ASSERT_EQ(ret, E_OK);
119
120 ValueObject value;
121 ret = resultSet->Get(0, value);
122 ASSERT_EQ(ret, E_ALREADY_CLOSED);
123
124 result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
125 ASSERT_EQ(result.first, E_OK);
126 ASSERT_EQ(3, result.second);
127
128 result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
129 ASSERT_EQ(result.first, E_ALREADY_CLOSED);
130
131 resultSet = store->QueryByStep("SELECT * FROM test");
132 ASSERT_NE(resultSet, nullptr);
133 resultSet->GetRowCount(rowCount);
134 EXPECT_EQ(rowCount, 3);
135 }
136
137 /**
138 * @tc.name: RdbStore_Transaction_002
139 * @tc.desc: createTransaction and rollback
140 * @tc.type: FUNC
141 */
142 HWTEST_F(TransactionTest, RdbStore_Transaction_002, TestSize.Level1)
143 {
144 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
145
146 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
147 ASSERT_EQ(ret, E_OK);
148 ASSERT_NE(transaction, nullptr);
149
150 auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
151 ASSERT_EQ(result.first, E_OK);
152 ASSERT_EQ(1, result.second);
153
154 result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1]));
155 ASSERT_EQ(result.first, E_OK);
156 ASSERT_EQ(2, result.second);
157
158 ret = transaction->Rollback();
159 ASSERT_EQ(ret, E_OK);
160
161 auto resultSet = store->QueryByStep("SELECT * FROM test");
162 ASSERT_NE(resultSet, nullptr);
163 int32_t rowCount{};
164 ret = resultSet->GetRowCount(rowCount);
165 ASSERT_EQ(ret, E_OK);
166 ASSERT_EQ(rowCount, 0);
167
168 result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION);
169 ASSERT_EQ(result.first, E_OK);
170 ASSERT_EQ(3, result.second);
171
172 result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
173 ASSERT_EQ(result.first, E_ALREADY_CLOSED);
174
175 resultSet = store->QueryByStep("SELECT * FROM test");
176 ASSERT_NE(resultSet, nullptr);
177 ret = resultSet->GetRowCount(rowCount);
178 EXPECT_EQ(ret, E_OK);
179 EXPECT_EQ(rowCount, 1);
180 }
181
182 /**
183 * @tc.name: RdbStore_Transaction_003
184 * @tc.desc: batchInsert
185 * @tc.type: FUNC
186 */
187 HWTEST_F(TransactionTest, RdbStore_Transaction_003, TestSize.Level1)
188 {
189 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
190
191 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
192 ASSERT_EQ(ret, E_OK);
193 ASSERT_NE(transaction, nullptr);
194
195 Transaction::Rows rows{
196 UTUtils::SetRowData(UTUtils::g_rowData[0]),
197 UTUtils::SetRowData(UTUtils::g_rowData[1]),
198 UTUtils::SetRowData(UTUtils::g_rowData[2]),
199 };
200 auto result = transaction->BatchInsert("test", rows);
201 ASSERT_EQ(result.first, E_OK);
202 ASSERT_EQ(result.second, 3);
203
204 ret = transaction->Commit();
205 ASSERT_EQ(ret, E_OK);
206
207 auto resultSet = store->QueryByStep("SELECT * FROM test");
208 ASSERT_NE(resultSet, nullptr);
209 int32_t rowCount{};
210 ret = resultSet->GetRowCount(rowCount);
211 EXPECT_EQ(ret, E_OK);
212 EXPECT_EQ(rowCount, 3);
213 }
214
215 /**
216 * @tc.name: RdbStore_Transaction_004
217 * @tc.desc: batchInsert
218 * @tc.type: FUNC
219 */
220 HWTEST_F(TransactionTest, RdbStore_Transaction_004, TestSize.Level1)
221 {
222 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
223
224 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
225 ASSERT_EQ(ret, E_OK);
226 ASSERT_NE(transaction, nullptr);
227
228 Transaction::RefRows rows;
229 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
230 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
231 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
232
233 auto result = transaction->BatchInsert("test", rows);
234 ASSERT_EQ(result.first, E_OK);
235 ASSERT_EQ(result.second, 3);
236
237 ret = transaction->Commit();
238 ASSERT_EQ(ret, E_OK);
239
240 auto resultSet = store->QueryByStep("SELECT * FROM test");
241 ASSERT_NE(resultSet, nullptr);
242 int32_t rowCount{};
243 ret = resultSet->GetRowCount(rowCount);
244 EXPECT_EQ(ret, E_OK);
245 EXPECT_EQ(rowCount, 3);
246 }
247
248 /**
249 * @tc.name: RdbStore_Transaction_005
250 * @tc.desc: Update
251 * @tc.type: FUNC
252 */
253 HWTEST_F(TransactionTest, RdbStore_Transaction_005, TestSize.Level1)
254 {
255 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
256
257 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
258 ASSERT_EQ(ret, E_OK);
259 ASSERT_NE(transaction, nullptr);
260
261 auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]));
262 ASSERT_EQ(result.first, E_OK);
263 ASSERT_EQ(result.second, 1);
264
265 result = transaction->Update("test", UTUtils::SetRowData(UTUtils::g_rowData[1]), "id=1");
266 ASSERT_EQ(result.first, E_OK);
267 ASSERT_EQ(result.second, 1);
268
269 auto resultSet = transaction->QueryByStep("SELECT * FROM test");
270 ASSERT_NE(resultSet, nullptr);
271 int32_t rowCount{};
272 ret = resultSet->GetRowCount(rowCount);
273 ASSERT_EQ(ret, E_OK);
274 ASSERT_EQ(rowCount, 1);
275 ret = resultSet->GoToFirstRow();
276 ASSERT_EQ(ret, E_OK);
277 int32_t columnIndex{};
278 ret = resultSet->GetColumnIndex("id", columnIndex);
279 ASSERT_EQ(ret, E_OK);
280 int32_t id{};
281 ret = resultSet->GetInt(columnIndex, id);
282 ASSERT_EQ(ret, E_OK);
283 ASSERT_EQ(id, 2);
284
285 AbsRdbPredicates predicates("test");
286 predicates.EqualTo("id", ValueObject(2));
287 result = transaction->Update(UTUtils::SetRowData(UTUtils::g_rowData[2]), predicates);
288 ASSERT_EQ(result.first, E_OK);
289 ASSERT_EQ(result.second, 1);
290
291 ret = transaction->Commit();
292 ASSERT_EQ(ret, E_OK);
293
294 resultSet = store->QueryByStep("SELECT * FROM test");
295 ASSERT_NE(resultSet, nullptr);
296 ret = resultSet->GetRowCount(rowCount);
297 ASSERT_EQ(ret, E_OK);
298 ASSERT_EQ(rowCount, 1);
299 ret = resultSet->GoToFirstRow();
300 ASSERT_EQ(ret, E_OK);
301 resultSet->GetColumnIndex("id", columnIndex);
302 ret = resultSet->GetInt(columnIndex, id);
303 EXPECT_EQ(ret, E_OK);
304 EXPECT_EQ(id, 3);
305 }
306
307 /**
308 * @tc.name: RdbStore_Transaction_006
309 * @tc.desc: Delete
310 * @tc.type: FUNC
311 */
312 HWTEST_F(TransactionTest, RdbStore_Transaction_006, TestSize.Level1)
313 {
314 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
315
316 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
317 ASSERT_EQ(ret, E_OK);
318 ASSERT_NE(transaction, nullptr);
319
320 Transaction::RefRows rows;
321 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[0]));
322 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[1]));
323 rows.Put(UTUtils::SetRowData(UTUtils::g_rowData[2]));
324
325 auto result = transaction->BatchInsert("test", rows);
326 ASSERT_EQ(result.first, E_OK);
327 ASSERT_EQ(result.second, 3);
328
329 result = transaction->Delete("test", "id=1");
330 ASSERT_EQ(result.first, E_OK);
331 ASSERT_EQ(result.second, 1);
332
333 AbsRdbPredicates predicates("test");
334 predicates.EqualTo("id", ValueObject(2));
335 result = transaction->Delete(predicates);
336 ASSERT_EQ(result.first, E_OK);
337 ASSERT_EQ(result.second, 1);
338
339 ret = transaction->Commit();
340 ASSERT_EQ(ret, E_OK);
341
342 auto resultSet = store->QueryByStep("SELECT * FROM test");
343 ASSERT_NE(resultSet, nullptr);
344 int32_t rowCount{};
345 ret = resultSet->GetRowCount(rowCount);
346 ASSERT_EQ(ret, E_OK);
347 ASSERT_EQ(rowCount, 1);
348 ret = resultSet->GoToFirstRow();
349 ASSERT_EQ(ret, E_OK);
350 int32_t columnIndex{};
351 resultSet->GetColumnIndex("id", columnIndex);
352 int32_t id{};
353 ret = resultSet->GetInt(columnIndex, id);
354 EXPECT_EQ(ret, E_OK);
355 EXPECT_EQ(id, 3);
356 }
357
358 /**
359 * @tc.name: RdbStore_Transaction_007
360 * @tc.desc: Execute
361 * @tc.type: FUNC
362 */
363 HWTEST_F(TransactionTest, RdbStore_Transaction_007, TestSize.Level1)
364 {
365 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
366
367 store->Execute("DROP TABLE IF EXISTS test1");
368 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
369 ASSERT_EQ(res.first, E_OK);
370 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
371 ASSERT_EQ(ret, E_OK);
372 ASSERT_NE(transaction, nullptr);
373
374 Transaction::Row row;
375 row.Put("id", 1);
376 row.Put("name", "Jim");
377 auto result = transaction->Insert("test1", row);
378 ASSERT_EQ(result.first, E_OK);
379 ASSERT_EQ(result.second, 1);
380
381 ret = transaction->Commit();
382 ASSERT_EQ(ret, E_OK);
383
384 auto resultSet = store->QueryByStep("SELECT * FROM test1");
385 ASSERT_NE(resultSet, nullptr);
386 int32_t rowCount{};
387 ret = resultSet->GetRowCount(rowCount);
388 EXPECT_EQ(ret, E_OK);
389 EXPECT_EQ(rowCount, 1);
390 }
391
392 /**
393 * @tc.name: RdbStore_Transaction_008
394 * @tc.desc: Insert with ConflictResolution::ON_CONFLICT_ROLLBACK
395 * @tc.type: FUNC
396 */
397 HWTEST_F(TransactionTest, RdbStore_Transaction_008, TestSize.Level1)
398 {
399 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
400 store->Execute("DROP TABLE IF EXISTS test1");
401 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
402 ASSERT_EQ(res.first, E_OK);
403 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
404 ASSERT_EQ(ret, E_OK);
405 ASSERT_NE(transaction, nullptr);
406
407 Transaction::Row row;
408 row.Put("id", 1);
409 row.Put("name", "Jim");
410 auto result = transaction->Insert("test1", row);
411 ASSERT_EQ(result.first, E_OK);
412 ASSERT_EQ(result.second, 1);
413
414 result = transaction->Insert("test1", row, ConflictResolution::ON_CONFLICT_ROLLBACK);
415 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
416 ASSERT_EQ(result.second, -1);
417 ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR);
418
419 auto resultSet = store->QueryByStep("SELECT * FROM test1");
420 ASSERT_NE(resultSet, nullptr);
421 int32_t rowCount{};
422 ret = resultSet->GetRowCount(rowCount);
423 EXPECT_EQ(ret, E_OK);
424 EXPECT_EQ(rowCount, 0);
425 }
426
427 /**
428 * @tc.name: RdbStore_Transaction_009
429 * @tc.desc: Update with ConflictResolution::ON_CONFLICT_ROLLBACK
430 * @tc.type: FUNC
431 */
432 HWTEST_F(TransactionTest, RdbStore_Transaction_009, TestSize.Level1)
433 {
434 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
435 store->Execute("DROP TABLE IF EXISTS test1");
436 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
437 ASSERT_EQ(res.first, E_OK);
438 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
439 ASSERT_EQ(ret, E_OK);
440 ASSERT_NE(transaction, nullptr);
441
442 Transaction::Row row;
443 row.Put("id", 1);
444 row.Put("name", "Jim");
445 auto result = transaction->Insert("test1", row);
446 ASSERT_EQ(result.first, E_OK);
447 ASSERT_EQ(result.second, 1);
448
449 row.Put("name", ValueObject());
450 result = transaction->Update(
451 "test1", row, "id = ?", std::vector<ValueObject>{ "1" }, ConflictResolution::ON_CONFLICT_ROLLBACK);
452 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
453 ASSERT_EQ(result.second, 0);
454 ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR);
455
456 auto resultSet = store->QueryByStep("SELECT * FROM test1");
457 ASSERT_NE(resultSet, nullptr);
458 int32_t rowCount{};
459 ret = resultSet->GetRowCount(rowCount);
460 EXPECT_EQ(ret, E_OK);
461 EXPECT_EQ(rowCount, 0);
462 }
463
464 /**
465 * @tc.name: RdbStore_Transaction_010
466 * @tc.desc: Update with ConflictResolution::ON_CONFLICT_ROLLBACK
467 * @tc.type: FUNC
468 */
469 HWTEST_F(TransactionTest, RdbStore_Transaction_010, TestSize.Level1)
470 {
471 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
472 store->Execute("DROP TABLE IF EXISTS test1");
473 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
474 ASSERT_EQ(res.first, E_OK);
475 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
476 ASSERT_EQ(ret, E_OK);
477 ASSERT_NE(transaction, nullptr);
478
479 Transaction::Row row;
480 row.Put("id", 1);
481 row.Put("name", "Jim");
482 auto result = transaction->Insert("test1", row);
483 ASSERT_EQ(result.first, E_OK);
484 ASSERT_EQ(result.second, 1);
485
486 row.Put("name", ValueObject());
487 AbsRdbPredicates predicates("test1");
488 predicates.EqualTo("id", 1);
489 result = transaction->Update(row, predicates, ConflictResolution::ON_CONFLICT_ROLLBACK);
490 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
491 ASSERT_EQ(result.second, 0);
492 ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR);
493
494 auto resultSet = store->QueryByStep("SELECT * FROM test1");
495 ASSERT_NE(resultSet, nullptr);
496 int32_t rowCount{};
497 ret = resultSet->GetRowCount(rowCount);
498 EXPECT_EQ(ret, E_OK);
499 EXPECT_EQ(rowCount, 0);
500 }
501
502 /**
503 * @tc.name: RdbStore_Transaction_011
504 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_ROLLBACK
505 * @tc.type: FUNC
506 */
507 HWTEST_F(TransactionTest, RdbStore_Transaction_011, TestSize.Level1)
508 {
509 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
510 store->Execute("DROP TABLE IF EXISTS test1");
511 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
512 ASSERT_EQ(res.first, E_OK);
513 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
514 ASSERT_EQ(ret, E_OK);
515 ASSERT_NE(transaction, nullptr);
516
517 ValuesBuckets rows;
518 for (int i = 0; i < 5; i++) {
519 Transaction::Row row;
520 row.Put("id", i);
521 row.Put("name", "Jim");
522 rows.Put(row);
523 }
524 Transaction::Row row;
525 row.Put("id", 2);
526 row.Put("name", "Jim");
527 auto result = transaction->Insert("test1", row);
528 ASSERT_EQ(result.first, E_OK);
529 ASSERT_EQ(result.second, 2);
530 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK);
531 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
532 ASSERT_EQ(result.second, 0);
533 ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR);
534
535 auto resultSet = store->QueryByStep("SELECT * FROM test1");
536 ASSERT_NE(resultSet, nullptr);
537 int32_t rowCount{};
538 ret = resultSet->GetRowCount(rowCount);
539 EXPECT_EQ(ret, E_OK);
540 EXPECT_EQ(rowCount, 0);
541 }
542
543 /**
544 * @tc.name: RdbStore_Transaction_012
545 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_ABORT
546 * @tc.type: FUNC
547 */
548 HWTEST_F(TransactionTest, RdbStore_Transaction_012, TestSize.Level1)
549 {
550 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
551 store->Execute("DROP TABLE IF EXISTS test1");
552 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
553 ASSERT_EQ(res.first, E_OK);
554 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
555 ASSERT_EQ(ret, E_OK);
556 ASSERT_NE(transaction, nullptr);
557
558 ValuesBuckets rows;
559 for (int i = 0; i < 5; i++) {
560 Transaction::Row row;
561 row.Put("id", i);
562 row.Put("name", "Jim");
563 rows.Put(row);
564 }
565 Transaction::Row row;
566 row.Put("id", 2);
567 row.Put("name", "Jim");
568 auto result = transaction->Insert("test1", row);
569 ASSERT_EQ(result.first, E_OK);
570 ASSERT_EQ(result.second, 2);
571 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT);
572 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
573 ASSERT_EQ(result.second, 0);
574 ASSERT_EQ(transaction->Commit(), E_OK);
575
576 auto resultSet = store->QueryByStep("SELECT * FROM test1");
577 ASSERT_NE(resultSet, nullptr);
578 int32_t rowCount{};
579 ret = resultSet->GetRowCount(rowCount);
580 EXPECT_EQ(ret, E_OK);
581 EXPECT_EQ(rowCount, 1);
582 }
583
584 /**
585 * @tc.name: RdbStore_Transaction_013
586 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_FAIL
587 * @tc.type: FUNC
588 */
589 HWTEST_F(TransactionTest, RdbStore_Transaction_013, TestSize.Level1)
590 {
591 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
592 store->Execute("DROP TABLE IF EXISTS test1");
593 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
594 ASSERT_EQ(res.first, E_OK);
595 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
596 ASSERT_EQ(ret, E_OK);
597 ASSERT_NE(transaction, nullptr);
598
599 ValuesBuckets rows;
600 for (int i = 0; i < 5; i++) {
601 Transaction::Row row;
602 row.Put("id", i);
603 row.Put("name", "Jim");
604 rows.Put(row);
605 }
606 Transaction::Row row;
607 row.Put("id", 2);
608 row.Put("name", "Jim");
609 auto result = transaction->Insert("test1", row);
610 ASSERT_EQ(result.first, E_OK);
611 ASSERT_EQ(result.second, 2);
612 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL);
613 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
614 ASSERT_EQ(result.second, 2);
615 ASSERT_EQ(transaction->Commit(), E_OK);
616
617 auto resultSet = store->QueryByStep("SELECT * FROM test1");
618 ASSERT_NE(resultSet, nullptr);
619 int32_t rowCount{};
620 ret = resultSet->GetRowCount(rowCount);
621 EXPECT_EQ(ret, E_OK);
622 EXPECT_EQ(rowCount, 3);
623 }
624
625 /**
626 * @tc.name: RdbStore_Transaction_014
627 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_IGNORE
628 * @tc.type: FUNC
629 */
630 HWTEST_F(TransactionTest, RdbStore_Transaction_014, TestSize.Level1)
631 {
632 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
633 store->Execute("DROP TABLE IF EXISTS test1");
634 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
635 ASSERT_EQ(res.first, E_OK);
636 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
637 ASSERT_EQ(ret, E_OK);
638 ASSERT_NE(transaction, nullptr);
639
640 ValuesBuckets rows;
641 for (int i = 0; i < 5; i++) {
642 Transaction::Row row;
643 row.Put("id", i);
644 row.Put("name", "Jim_batchInsert");
645 rows.Put(row);
646 }
647 Transaction::Row row;
648 row.Put("id", 2);
649 row.Put("name", "Jim_insert");
650 auto result = transaction->Insert("test1", row);
651 ASSERT_EQ(result.first, E_OK);
652 ASSERT_EQ(result.second, 2);
653 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE);
654 ASSERT_EQ(result.first, E_OK);
655 ASSERT_EQ(result.second, 4);
656 ASSERT_EQ(transaction->Commit(), E_OK);
657
658 auto resultSet = store->QueryByStep("SELECT * FROM test1");
659 ASSERT_NE(resultSet, nullptr);
660 int32_t rowCount{};
661 ret = resultSet->GetRowCount(rowCount);
662 EXPECT_EQ(ret, E_OK);
663 EXPECT_EQ(rowCount, 5);
664 resultSet = store->QueryByStep("SELECT * FROM test1 where id = 2");
665 ASSERT_NE(resultSet, nullptr);
666 ASSERT_EQ(resultSet->GoToFirstRow(), E_OK);
667 int columnIndex = -1;
668 ASSERT_EQ(resultSet->GetColumnIndex("name", columnIndex), E_OK);
669 std::string name;
670 EXPECT_EQ(resultSet->GetString(columnIndex, name), E_OK);
671 EXPECT_EQ(name, "Jim_insert");
672 }
673
674 /**
675 * @tc.name: RdbStore_Transaction_015
676 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_REPLACE
677 * @tc.type: FUNC
678 */
679 HWTEST_F(TransactionTest, RdbStore_Transaction_015, TestSize.Level1)
680 {
681 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
682 store->Execute("DROP TABLE IF EXISTS test1");
683 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
684 ASSERT_EQ(res.first, E_OK);
685 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
686 ASSERT_EQ(ret, E_OK);
687 ASSERT_NE(transaction, nullptr);
688
689 ValuesBuckets rows;
690 for (int i = 0; i < 5; i++) {
691 Transaction::Row row;
692 row.Put("id", i);
693 row.Put("name", "Jim_batchInsert");
694 rows.Put(row);
695 }
696 Transaction::Row row;
697 row.Put("id", 2);
698 row.Put("name", "Jim_insert");
699 auto result = transaction->Insert("test1", row);
700 ASSERT_EQ(result.first, E_OK);
701 ASSERT_EQ(result.second, 2);
702 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE);
703 ASSERT_EQ(result.first, E_OK);
704 ASSERT_EQ(result.second, 5);
705 ASSERT_EQ(transaction->Commit(), E_OK);
706
707 auto resultSet = store->QueryByStep("SELECT * FROM test1");
708 ASSERT_NE(resultSet, nullptr);
709 int32_t rowCount{};
710 ret = resultSet->GetRowCount(rowCount);
711 EXPECT_EQ(ret, E_OK);
712 EXPECT_EQ(rowCount, 5);
713 resultSet = store->QueryByStep("SELECT * FROM test1 where id = 2");
714 ASSERT_NE(resultSet, nullptr);
715 ASSERT_EQ(resultSet->GoToFirstRow(), E_OK);
716 int columnIndex = -1;
717 ASSERT_EQ(resultSet->GetColumnIndex("name", columnIndex), E_OK);
718 std::string name;
719 EXPECT_EQ(resultSet->GetString(columnIndex, name), E_OK);
720 EXPECT_EQ(name, "Jim_batchInsert");
721 }
722
723 /**
724 * @tc.name: RdbStore_Transaction_016
725 * @tc.desc: BatchInsert with ConflictResolution::ON_CONFLICT_REPLACE and failed
726 * @tc.type: FUNC
727 */
728 HWTEST_F(TransactionTest, RdbStore_Transaction_016, TestSize.Level1)
729 {
730 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
731 store->Execute("DROP TABLE IF EXISTS test1");
732 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
733 ASSERT_EQ(res.first, E_OK);
734 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
735 ASSERT_EQ(ret, E_OK);
736 ASSERT_NE(transaction, nullptr);
737
738 ValuesBuckets rows;
739 for (int i = 0; i < 5; i++) {
740 Transaction::Row row;
741 row.Put("id", i);
742 row.Put("name", i == 2 ? ValueObject() : "Jim_batchInsert");
743 rows.Put(row);
744 }
745 Transaction::Row row;
746 row.Put("id", 2);
747 row.Put("name", "Jim_insert");
748 auto result = transaction->Insert("test1", row);
749 ASSERT_EQ(result.first, E_OK);
750 ASSERT_EQ(result.second, 2);
751 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE);
752 // ON_CONFLICT_REPLACE is equivalent to ON_CONFLICT_ABORT after failure
753 ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT);
754 ASSERT_EQ(result.second, 0);
755 ASSERT_EQ(transaction->Commit(), E_OK);
756
757 auto resultSet = store->QueryByStep("SELECT * FROM test1");
758 ASSERT_NE(resultSet, nullptr);
759 ASSERT_EQ(resultSet->GoToFirstRow(), E_OK);
760 int columnIndex = -1;
761 ASSERT_EQ(resultSet->GetColumnIndex("name", columnIndex), E_OK);
762 std::string name;
763 EXPECT_EQ(resultSet->GetString(columnIndex, name), E_OK);
764 EXPECT_EQ(name, "Jim_insert");
765 }
766
767 /**
768 * @tc.name: RdbStore_Transaction_017
769 * @tc.desc: BatchInsert when busy
770 * @tc.type: FUNC
771 */
772 HWTEST_F(TransactionTest, RdbStore_Transaction_017, TestSize.Level1)
773 {
774 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
775 store->Execute("DROP TABLE IF EXISTS test1");
776 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
777 ASSERT_EQ(res.first, E_OK);
778 auto [ret1, transaction1] = store->CreateTransaction(Transaction::EXCLUSIVE);
779 ASSERT_EQ(ret1, E_OK);
780 ASSERT_NE(transaction1, nullptr);
781
782 auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED);
783 ASSERT_EQ(ret, E_OK);
784 ASSERT_NE(transaction, nullptr);
785
786 ValuesBuckets rows;
787 for (int i = 0; i < 5; i++) {
788 Transaction::Row row;
789 row.Put("id", i);
790 row.Put("name", "Jim_batchInsert");
791 rows.Put(row);
792 }
793 auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE);
794 ASSERT_EQ(result.first, E_SQLITE_BUSY);
795 ASSERT_EQ(result.second, -1);
796
797 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK);
798 ASSERT_EQ(result.first, E_SQLITE_BUSY);
799 ASSERT_EQ(result.second, -1);
800
801 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT);
802 ASSERT_EQ(result.first, E_SQLITE_BUSY);
803 ASSERT_EQ(result.second, -1);
804
805 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL);
806 ASSERT_EQ(result.first, E_SQLITE_BUSY);
807 ASSERT_EQ(result.second, -1);
808
809 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE);
810 ASSERT_EQ(result.first, E_SQLITE_BUSY);
811 ASSERT_EQ(result.second, -1);
812
813 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE);
814 ASSERT_EQ(result.first, E_SQLITE_BUSY);
815 ASSERT_EQ(result.second, -1);
816 }
817
818 /**
819 * @tc.name: RdbStore_Transaction_018
820 * @tc.desc: BatchInsert when over limit rows
821 * @tc.type: FUNC
822 */
823 HWTEST_F(TransactionTest, RdbStore_Transaction_018, TestSize.Level1)
824 {
825 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
826 store->Execute("DROP TABLE IF EXISTS test1");
827 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
828 ASSERT_EQ(res.first, E_OK);
829
830 auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED);
831 ASSERT_EQ(ret, E_OK);
832 ASSERT_NE(transaction, nullptr);
833
834 //sqlite default max param number
835 int32_t maxNumber = 32766;
836 int32_t maxRows = maxNumber / 2 + 1;
837 ValuesBuckets rows;
838 for (int32_t i = 0; i < maxRows; i++) {
839 Transaction::Row row;
840 row.Put("id", i);
841 row.Put("name", "Jim_batchInsert");
842 rows.Put(row);
843 }
844 auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE);
845 ASSERT_EQ(result.first, E_INVALID_ARGS);
846 ASSERT_EQ(result.second, -1);
847
848 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK);
849 ASSERT_EQ(result.first, E_INVALID_ARGS);
850 ASSERT_EQ(result.second, -1);
851
852 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT);
853 ASSERT_EQ(result.first, E_INVALID_ARGS);
854 ASSERT_EQ(result.second, -1);
855
856 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL);
857 ASSERT_EQ(result.first, E_INVALID_ARGS);
858 ASSERT_EQ(result.second, -1);
859
860 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE);
861 ASSERT_EQ(result.first, E_INVALID_ARGS);
862 ASSERT_EQ(result.second, -1);
863
864 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE);
865 ASSERT_EQ(result.first, E_INVALID_ARGS);
866 ASSERT_EQ(result.second, -1);
867 }
868
869 /**
870 * @tc.name: RdbStore_Transaction_019
871 * @tc.desc: Normal BatchInsertWithConflictResolution
872 * @tc.type: FUNC
873 */
874 HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1)
875 {
876 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
877 store->Execute("DROP TABLE IF EXISTS test1");
878 auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
879 ASSERT_EQ(res.first, E_OK);
880 auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE);
881 ASSERT_EQ(ret, E_OK);
882 ASSERT_NE(transaction, nullptr);
883
884 ValuesBuckets rows;
885 auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE);
886 ASSERT_EQ(result.first, E_OK);
887 ASSERT_EQ(result.second, 0);
888 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK);
889 ASSERT_EQ(result.first, E_OK);
890 ASSERT_EQ(result.second, 0);
891 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT);
892 ASSERT_EQ(result.first, E_OK);
893 ASSERT_EQ(result.second, 0);
894 for (int i = 0; i < 2; i++) {
895 Transaction::Row row;
896 row.Put("name", "Jim_batchInsert");
897 rows.Put(row);
898 }
899 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL);
900 ASSERT_EQ(result.first, E_OK);
901 ASSERT_EQ(result.second, 2);
902 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE);
903 ASSERT_EQ(result.first, E_OK);
904 ASSERT_EQ(result.second, 2);
905 result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE);
906 ASSERT_EQ(result.first, E_OK);
907 ASSERT_EQ(result.second, 2);
908
909 ASSERT_EQ(transaction->Commit(), E_OK);
910 auto resultSet = store->QueryByStep("SELECT * FROM test1");
911 ASSERT_NE(resultSet, nullptr);
912 int32_t rowCount{};
913 ret = resultSet->GetRowCount(rowCount);
914 EXPECT_EQ(ret, E_OK);
915 EXPECT_EQ(rowCount, 6);
916 }
917
918 /**
919 * @tc.name: RdbStore_Transaction_020
920 * @tc.desc: After executing the ddl statement, the transaction links cached in the history need to be cleared.
921 * Continuing to use the old connections will result in errors due to changes in the table structure.
922 * @tc.type: FUNC
923 */
924 HWTEST_F(TransactionTest, RdbStore_Transaction_020, TestSize.Level1)
925 {
926 std::shared_ptr<RdbStore> &store = TransactionTest::store_;
927
928 auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED);
929 ASSERT_EQ(ret, E_OK);
930 ASSERT_NE(transaction, nullptr);
931
932 Transaction::Row row;
933 row.Put("id", 1);
934 row.Put("name", "Jim");
935 auto result = transaction->Insert("test", row);
936 ASSERT_EQ(result.first, E_OK);
937 ASSERT_EQ(result.second, 1);
938
939 ret = transaction->Commit();
940 ASSERT_EQ(ret, E_OK);
941 transaction = nullptr;
942
943 store->Execute("DROP TABLE IF EXISTS test1");
944 auto res = store->Execute(
945 "CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
946 ASSERT_EQ(res.first, E_OK);
947 // After creating the table, the links will be cleared, and creating a new transaction will create a new connection,
948 // ensuring that the transaction operation does not report errors.
949 std::tie(ret, transaction) = store->CreateTransaction(Transaction::DEFERRED);
950 ASSERT_EQ(ret, E_OK);
951 ASSERT_NE(transaction, nullptr);
952
953 auto resultSet = transaction->QueryByStep("SELECT * FROM test");
954 ASSERT_NE(resultSet, nullptr);
955 int32_t rowCount{};
956 ret = resultSet->GetRowCount(rowCount);
957 EXPECT_EQ(ret, E_OK);
958 EXPECT_EQ(rowCount, 1);
959 }
960