* Copyright (c) 2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <string>
#include "rdb_test_common.h"
#include "rdb_common.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
#include "rdb_open_callback.h"
#include "sqlite_sql_builder.h"
using namespace testing::ext;
using namespace OHOS::NativeRdb;
namespace OHOS::RdbStoreUpdateTest {
struct RdbTestParam {
std::shared_ptr<RdbStore> store;
operator std::shared_ptr<RdbStore>()
{
return store;
}
};
static RdbTestParam g_store;
static RdbTestParam g_memDb;
class RdbStoreUpdateTest : public testing::TestWithParam<RdbTestParam *> {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
static void ExpectValue(const std::shared_ptr<OHOS::NativeRdb::ResultSet> &resultSet, const RdbRowData &expect);
void SetUp();
void TearDown();
std::shared_ptr<RdbStore> store_;
static const std::string DATABASE_NAME;
};
const std::string RdbStoreUpdateTest::DATABASE_NAME = RDB_TEST_PATH + "update_test.db";
class UpdateTestOpenCallback : public RdbOpenCallback {
public:
int OnCreate(RdbStore &store) override;
int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override;
};
constexpr const char *CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test ("
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name TEXT UNIQUE, "
"age INTEGER, "
"salary REAL, "
"blobType BLOB, "
"assetType ASSET, "
"assetsType ASSETS)";
int UpdateTestOpenCallback::OnCreate(RdbStore &store)
{
return store.ExecuteSql(CREATE_TABLE_TEST);
}
int UpdateTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion)
{
return E_OK;
}
void RdbStoreUpdateTest::SetUpTestCase(void)
{
int errCode = E_OK;
RdbHelper::DeleteRdbStore(DATABASE_NAME);
RdbStoreConfig config(RdbStoreUpdateTest::DATABASE_NAME);
UpdateTestOpenCallback helper;
g_store.store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
ASSERT_NE(g_store.store, nullptr);
config.SetStorageMode(StorageMode::MODE_MEMORY);
g_memDb.store = RdbHelper::GetRdbStore(config, 1, helper, errCode);
ASSERT_NE(g_memDb.store, nullptr);
}
void RdbStoreUpdateTest::TearDownTestCase(void)
{
RdbStoreConfig config(RdbStoreUpdateTest::DATABASE_NAME);
RdbHelper::DeleteRdbStore(config);
config.SetStorageMode(StorageMode::MODE_MEMORY);
RdbHelper::DeleteRdbStore(config);
}
void RdbStoreUpdateTest::SetUp(void)
{
store_ = *GetParam();
ASSERT_NE(store_, nullptr);
store_->ExecuteSql("DELETE FROM test");
}
void RdbStoreUpdateTest::TearDown(void)
{
RdbHelper::ClearCache();
}
* @tc.name: RdbStore_Update_001
* @tc.desc: test RdbStore update, select id and update one row
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
values.Clear();
values.PutInt("id", 2);
values.PutString("name", std::string("lisi"));
values.PutInt("age", 20);
values.PutDouble("salary", 200.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
ret = store_->Update(changedRows, "test", values, "id = ?", std::vector<std::string>{ "1" });
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToFirstRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "lisi", 20, 200.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_002
* @tc.desc: test RdbStore update, no select and update all rows
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1)
{
int64_t id;
ValuesBucket values;
int changedRows;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.Clear();
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
ret = store_->Update(changedRows, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 300.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "lisi", 19, 300.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_003
* @tc.desc: test RdbStore update
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1)
{
int changedRows;
ValuesBucket values;
values.PutInt("id", 1);
values.PutString("name", std::string("zhangsan"));
values.PutInt("age", 18);
values.PutDouble("salary", 100.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
int ret = store_->Update(changedRows, "", values, "", std::vector<std::string>());
EXPECT_EQ(ret, E_EMPTY_TABLE_NAME);
ret = store_->Update(changedRows, "wrongTable", values, "", std::vector<std::string>());
EXPECT_EQ(ret, E_SQLITE_ERROR);
}
* @tc.name: RdbStore_Update_004
* @tc.desc: test RdbStore insert
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1)
{
int changedRows;
ValuesBucket emptyBucket;
int ret = store_->Update(changedRows, "test", emptyBucket);
EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET);
ValuesBucket values;
values.PutInt("id", 1);
values.PutString("name", std::string("zhangsan"));
values.PutInt("age", 18);
values.PutDouble("wrongColumn", 100.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 1, 2, 3 });
ret = store_->Update(changedRows, "test", values, "", std::vector<std::string>());
EXPECT_EQ(ret, E_SQLITE_ERROR);
}
* @tc.name: RdbStore_Update_005
* @tc.desc: test RdbStore insert
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_005, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Update(changedRows, "test", values, "id = ?", std::vector<std::string>{ "1" });
EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET);
}
* @tc.name: RdbStore_Update_006
* @tc.desc: test RdbStore insert
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
values.Clear();
values.PutString("id", "2");
values.PutString("name", std::string("lisi"));
values.PutInt("age", 20);
values.PutDouble("salary", 200.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Update(changedRows, "test", values, "id = ?", std::vector<std::string>{ "1" });
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToFirstRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "lisi", 20, 200.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_007
* @tc.desc: test RdbStore update asset
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_007, TestSize.Level1)
{
ValuesBucket values;
AssetValue value{ .version = 1, .name = "123", .uri = "your test path", .createTime = "13", .modifyTime = "13" };
int changedRows;
int64_t id;
values.PutNull("assetType");
int ret = store_->Insert(id, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(3, id);
values.Clear();
values.Put("assetType", value);
ret = store_->Update(changedRows, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToFirstRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ .id = 3,
.asset{ .version = 1,
.status = AssetValue::STATUS_INSERT,
.name = "123",
.uri = "your test path",
.createTime = "13",
.modifyTime = "13" } });
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_008
* @tc.desc: test RdbStore update asset
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1)
{
ValuesBucket values;
AssetValue valueDef{
.version = 0,
.name = "123",
.uri = "my test path",
.createTime = "12",
.modifyTime = "12",
};
AssetValue value{ .version = 2, .name = "456", .uri = "your test path", .createTime = "15", .modifyTime = "15" };
int changedRows;
int64_t id;
values.Put("assetType", valueDef);
int ret = store_->Insert(id, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(4, id);
values.Clear();
values.Put("assetType", value);
ret = store_->Update(changedRows, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToFirstRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet,
RdbRowData{ .id = 4,
.asset{ .version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12" } });
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_009
* @tc.desc: test RdbStore update asset
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1)
{
ValuesBucket values;
AssetValue valueDef{ .version = 0,
.status = AssetValue::STATUS_NORMAL,
.name = "123",
.uri = "my test path",
.createTime = "12",
.modifyTime = "12",
.size = "543",
.hash = "321" };
AssetValue value{ .name = "123" };
value.status = AssetValue::STATUS_DELETE;
int changedRows;
int64_t id;
values.Put("assetType", valueDef);
int ret = store_->Insert(id, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(5, id);
values.Clear();
values.Put("assetType", value);
ret = store_->Update(changedRows, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToFirstRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ .id = 5,
.asset{ .version = 0,
.status = AssetValue::Status::STATUS_DELETE,
.name = "123",
.uri = "my test path",
.createTime = "12",
.modifyTime = "",
.size = "",
.hash = "" } });
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_Update_010
* @tc.desc: test RdbStore update assets
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1)
{
ValuesBucket values;
std::vector<AssetValue> assetsDef{
{ .version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12" }
};
AssetValue value1{ .version = 1, .name = "123", .uri = "your test path", .createTime = "13", .modifyTime = "13" };
AssetValue value2{ .version = 2, .name = "123", .uri = "your test path", .createTime = "14", .modifyTime = "14" };
AssetValue value3{ .version = 3, .name = "456", .uri = "your test path", .createTime = "15", .modifyTime = "15" };
auto assets = ValueObject::Assets({ value1, value2, value3 });
int changedRows;
int64_t id;
values.Put("assetsType", assetsDef);
int ret = store_->Insert(id, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(6, id);
values.Clear();
values.Put("assetsType", assets);
ret = store_->Update(changedRows, "test", values);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_001
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutInt("id", 3);
values.PutString("name", std::string("wangjing"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 7, 8, 9 });
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = 19");
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 3, "wangjing", 20, 300.5, std::vector<uint8_t>{ 7, 8, 9 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_002
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutInt("id", 3);
values.PutString("name", std::string("zhangsan"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 7, 8, 9 });
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "19" },
ConflictResolution::ON_CONFLICT_NONE);
EXPECT_EQ(ret, E_SQLITE_CONSTRAINT);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "lisi", 19, 200.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_003
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutInt("id", 3);
values.PutString("name", std::string("wangjing"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 7, 8, 9 });
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "19" },
ConflictResolution::ON_CONFLICT_ROLLBACK);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 3, "wangjing", 20, 300.5, std::vector<uint8_t>{ 7, 8, 9 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_004
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutInt("id", 3);
values.PutString("name", std::string("zhangsan"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 7, 8, 9 });
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "19" },
ConflictResolution::ON_CONFLICT_ROLLBACK);
EXPECT_EQ(ret, E_SQLITE_CONSTRAINT);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "lisi", 19, 200.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_005
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutInt("id", 3);
values.PutString("name", std::string("wangjing"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 7, 8, 9 });
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "19" },
ConflictResolution::ON_CONFLICT_REPLACE);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, changedRows);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 1, "zhangsan", 18, 100.5, std::vector<uint8_t>{ 1, 2, 3 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 3, "wangjing", 20, 300.5, std::vector<uint8_t>{ 7, 8, 9 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_006
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize.Level1)
{
ValuesBucket values;
int changedRows;
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[1]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(2, id);
values.PutString("name", std::string("zhangsan"));
values.PutInt("age", 20);
values.PutDouble("salary", 300.5);
ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector<std::string>{ "19" },
ConflictResolution::ON_CONFLICT_REPLACE);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(changedRows, 1);
std::shared_ptr<ResultSet> resultSet = store_->QuerySql("SELECT * FROM test");
EXPECT_NE(resultSet, nullptr);
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_OK);
RdbStoreUpdateTest::ExpectValue(resultSet, RdbRowData{ 2, "zhangsan", 20, 300.5, std::vector<uint8_t>{ 4, 5, 6 } });
ret = resultSet->GoToNextRow();
EXPECT_EQ(ret, E_ROW_OUT_RANGE);
ret = resultSet->Close();
EXPECT_EQ(ret, E_OK);
}
* @tc.name: RdbStore_UpdateWithConflictResolution_007
* @tc.desc: test RdbStore UpdateWithConflictResolution
* @tc.type: FUNC
*/
HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize.Level1)
{
int changedRows = 0;
int64_t id = -1;
ValuesBucket values;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
values.PutInt("id", 2);
values.PutInt("age", 19);
ret = store_->UpdateWithConflictResolution(
changedRows, "test", values, "age = ?", std::vector<std::string>{ "18" }, static_cast<ConflictResolution>(6));
EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret);
EXPECT_EQ(0, changedRows);
values.Clear();
values.PutInt("id", 2);
values.PutInt("age", 19);
ret = store_->UpdateWithConflictResolution(
changedRows, "test", values, "age = ?", std::vector<std::string>{ "18" }, static_cast<ConflictResolution>(-1));
EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret);
EXPECT_EQ(0, changedRows);
}
void RdbStoreUpdateTest::ExpectValue(
const std::shared_ptr<OHOS::NativeRdb::ResultSet> &resultSet, const RdbRowData &expect)
{
EXPECT_NE(nullptr, resultSet);
int columnIndex;
int intVal;
int ret;
if (expect.id != -1) {
ret = resultSet->GetColumnIndex("id", columnIndex);
EXPECT_EQ(ret, E_OK);
ret = resultSet->GetInt(columnIndex, intVal);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(expect.id, intVal);
}
if (expect.name != "") {
std::string strVal;
ret = resultSet->GetColumnIndex("name", columnIndex);
EXPECT_EQ(ret, E_OK);
ret = resultSet->GetString(columnIndex, strVal);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(expect.name, strVal);
}
if (expect.age != -1) {
ret = resultSet->GetColumnIndex("age", columnIndex);
EXPECT_EQ(ret, E_OK);
ret = resultSet->GetInt(columnIndex, intVal);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(expect.age, intVal);
}
if (expect.salary != -1) {
double dVal;
ret = resultSet->GetColumnIndex("salary", columnIndex);
EXPECT_EQ(ret, E_OK);
ret = resultSet->GetDouble(columnIndex, dVal);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(expect.salary, dVal);
}
if (expect.blobType.size() != 0) {
std::vector<uint8_t> blob;
ret = resultSet->GetColumnIndex("blobType", columnIndex);
EXPECT_EQ(ret, E_OK);
ret = resultSet->GetBlob(columnIndex, blob);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(expect.blobType.size(), static_cast<int>(blob.size()));
for (int i = 0; i < expect.blobType.size(); i++) {
EXPECT_EQ(expect.blobType[i], blob[i]);
}
}
}
* @tc.name: OverLimitWithUpdate_001
* @tc.desc: over limit
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, OverLimitWithUpdate_001, TestSize.Level1)
{
std::shared_ptr<RdbStore> store = *GetParam();
auto [code, maxPageCount] = store->Execute("PRAGMA max_page_count;");
auto recover = std::shared_ptr<const char>("recover", [defPageCount = maxPageCount, store](const char *) {
store->Execute("PRAGMA max_page_count = " + static_cast<std::string>(defPageCount) + ";");
});
std::tie(code, maxPageCount) = store->Execute("PRAGMA max_page_count = 256;");
int64_t id = -1;
int ret = store->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
ASSERT_EQ(ret, E_OK);
ValuesBucket row;
row.PutInt("id", id);
row.Put("name", std::string(1024 * 1024, 'e'));
row.PutInt("age", 20);
row.PutDouble("salary", 200.5);
row.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
int changedRows;
auto result = store->Update(changedRows, "test", row);
ASSERT_EQ(result, E_SQLITE_FULL);
}
* @tc.name: UpdateWithReturning_001
* @tc.desc: normal test
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_001, TestSize.Level1)
{
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ValuesBucket values;
values.PutInt("id", 2);
values.PutString("name", std::string("lisi"));
values.PutInt("age", 20);
values.PutDouble("salary", 200.5);
values.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
AbsRdbPredicates predicates("test");
auto [status, result] = store_->Update(values, predicates, { "id" });
EXPECT_EQ(status, E_OK);
EXPECT_EQ(result.changed, 1);
int rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
ASSERT_EQ(rowCount, 1);
int columnIndex = -1;
ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK);
int val = -1;
ASSERT_EQ(result.results->GetInt(columnIndex, val), E_OK);
}
* @tc.name: UpdateWithReturning_002
* @tc.desc: abnormal test, update with conflict ignore and partial Success
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_002, TestSize.Level1)
{
ValuesBuckets rows;
for (int i = 0; i < 5; i++) {
ValuesBucket row;
row.Put("id", i);
row.Put("name", "Jim_" + std::to_string(i));
rows.Put(row);
}
auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE);
ASSERT_EQ(status, E_OK);
ASSERT_EQ(result.changed, 5);
int rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(0, rowCount);
ValuesBucket row;
row.PutString("name", "Jim_3");
row.PutInt("age", 20);
row.PutDouble("salary", 200.5);
row.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
AbsRdbPredicates predicates("test");
predicates.In("id", { 1, 2, 3 });
std::tie(status, result) = store_->Update(row, predicates, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE);
EXPECT_EQ(status, E_OK);
EXPECT_EQ(result.changed, 1);
rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(1, rowCount);
int columnIndex = -1;
ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK);
std::string val;
ASSERT_EQ(result.results->GetString(columnIndex, val), E_OK);
ASSERT_EQ(val, "Jim_3");
}
* @tc.name: UpdateWithReturning_003
* @tc.desc: abnormal test, update with conflict abort and failed
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_003, TestSize.Level1)
{
ValuesBuckets rows;
for (int i = 0; i < 5; i++) {
ValuesBucket row;
row.Put("id", i);
row.Put("name", "Jim_" + std::to_string(i));
rows.Put(row);
}
auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE);
ASSERT_EQ(status, E_OK);
ASSERT_EQ(result.changed, 5);
int rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(0, rowCount);
ValuesBucket row;
row.PutString("name", "Jim_3");
row.PutInt("age", 20);
row.PutDouble("salary", 200.5);
row.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
AbsRdbPredicates predicates("test");
predicates.In("id", { 1, 2, 3 });
std::tie(status, result) = store_->Update(row, predicates, { "blobType" }, ConflictResolution::ON_CONFLICT_ABORT);
EXPECT_EQ(status, E_SQLITE_CONSTRAINT);
EXPECT_EQ(result.changed, 0);
rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(0, rowCount);
}
* @tc.name: UpdateWithReturning_004
* @tc.desc: abnormal test, update over returning limit
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_004, TestSize.Level1)
{
ValuesBuckets rows;
for (int i = 0; i < 1124; i++) {
ValuesBucket row;
row.Put("id", i);
row.Put("name", "Jim_" + std::to_string(i));
rows.Put(row);
}
auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE);
ASSERT_EQ(status, E_OK);
ASSERT_EQ(result.changed, 1124);
int rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(0, rowCount);
ValuesBucket row;
row.PutInt("age", 20);
row.PutDouble("salary", 200.5);
row.PutBlob("blobType", std::vector<uint8_t>{ 4, 5, 6 });
AbsRdbPredicates predicates("test");
std::tie(status, result) = store_->Update(row, predicates, { "age" }, ConflictResolution::ON_CONFLICT_REPLACE);
EXPECT_EQ(status, E_OK);
EXPECT_EQ(result.changed, 1124);
rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(rowCount, 1024);
}
* @tc.name: UpdateWithReturning_005
* @tc.desc: abnormal test, update with returning no exist field
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_005, TestSize.Level1)
{
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ValuesBucket values;
values.PutString("name", std::string("lisi"));
values.PutInt("age", 20);
AbsRdbPredicates predicates("test");
predicates.EqualTo("id", 10000);
auto [status, result] = store_->Update(values, predicates, { "noExist" });
EXPECT_EQ(status, E_SQLITE_ERROR);
EXPECT_EQ(result.changed, -1);
EXPECT_EQ(result.results, nullptr);
}
* @tc.name: UpdateWithReturning_006
* @tc.desc: abnormal test, update 0 rows
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_006, TestSize.Level1)
{
int64_t id;
int ret = store_->Insert(id, "test", RdbTestUtils::SetRowData(RdbTestUtils::g_rowData[0]));
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(1, id);
ValuesBucket values;
values.PutString("name", std::string("lisi"));
values.PutInt("age", 20);
AbsRdbPredicates predicates("test");
predicates.EqualTo("id", 10000);
auto [status, result] = store_->Update(values, predicates, { "id" });
EXPECT_EQ(status, E_OK);
EXPECT_EQ(result.changed, 0);
int rowCount = -1;
ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK);
EXPECT_EQ(0, rowCount);
}
* @tc.name: UpdateWithReturning_007
* @tc.desc: abnormal test, update 0 rows
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_007, TestSize.Level1)
{
store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);");
ValuesBuckets rows;
ValuesBucket row;
row.Put("title", "fts5");
row.Put("content", "test virtual tables");
rows.Put(std::move(row));
auto [status, result] =
store_->BatchInsert("articles", rows, { "title" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE);
EXPECT_EQ(status, E_OK);
EXPECT_EQ(result.changed, 1);
ASSERT_NE(result.results, nullptr);
AbsRdbPredicates predicates("test");
predicates.EqualTo("title", "fts5");
ValuesBucket values;
values.PutString("title", "fts5 updated");
std::tie(status, result) = store_->Update(values, predicates, { "title" });
EXPECT_EQ(status, E_SQLITE_ERROR);
EXPECT_EQ(result.changed, -1);
EXPECT_EQ(result.results, nullptr);
store_->Execute("Drop TABLE articles");
}
* @tc.name: UpdateWithReturning_008
* @tc.desc: normal test. create trigger before update, delete data in trigger, then update data
* @tc.type: FUNC
* @tc.require:
* @tc.author:
*/
HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_008, TestSize.Level1)
{
auto [code, result1] = store_->Execute(
"CREATE TRIGGER before_update BEFORE UPDATE ON test"
" BEGIN DELETE FROM test WHERE name = 'wang'; END");
EXPECT_EQ(code, E_OK);
ValuesBuckets rows;
ValuesBucket row;
row.Put("id", 200);
row.Put("name", "wang");
rows.Put(std::move(row));
row.Put("id", 201);
row.Put("name", "zhang");
rows.Put(std::move(row));
auto [insertStatus, insertResult] =
store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE);
EXPECT_EQ(insertStatus, E_OK);
EXPECT_EQ(insertResult.changed, 2);
auto predicates = AbsRdbPredicates("test");
predicates.EqualTo("name", "zhang");
ValuesBucket values;
values.PutString("name", "liu");
auto [status, res] =
store_->Update(values, predicates, { "name" });
EXPECT_EQ(status, E_OK);
EXPECT_EQ(res.changed, 1);
int rowCount = -1;
ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK);
ASSERT_EQ(rowCount, 1);
int columnIndex = -1;
ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK);
std::string value;
ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK);
EXPECT_EQ(value, "liu");
auto resultSet = store_->QuerySql("select name from test where id = 200");
rowCount = -1;
resultSet->GetRowCount(rowCount);
ASSERT_EQ(rowCount, 0);
store_->Execute("DROP TRIGGER IF EXISTS before_update");
}
INSTANTIATE_TEST_SUITE_P(UpdateTest, RdbStoreUpdateTest, testing::Values(&g_store, &g_memDb));
}