* 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 "rdb_test_common.h"
#include "rdb_errno.h"
#include "rdb_helper.h"
#include "values_bucket.h"
using namespace testing::ext;
using namespace OHOS::NativeRdb;
namespace Test {
class QueryWithCrudTest : public testing::Test {
public:
static void SetUpTestCase(void);
static void TearDownTestCase(void);
void SetUp(void);
void TearDown(void);
void InsertData(int rowCount, int size);
static std::shared_ptr<RdbStore> rdbStore_;
static constexpr const char *DATABASE_PATH = "/data/test/queryWithCrud_test.db";
static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY AUTOINCREMENT, "
"name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)";
static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS test";
const double SALARY = 100.5;
class RdbCallback : public RdbOpenCallback {
public:
int OnCreate(RdbStore &store) override
{
return E_OK;
}
int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override
{
return E_OK;
}
};
};
std::shared_ptr<RdbStore> QueryWithCrudTest::rdbStore_;
void QueryWithCrudTest::SetUpTestCase(void)
{
int errCode = E_OK;
RdbCallback callback;
RdbStoreConfig config(DATABASE_PATH);
RdbHelper::DeleteRdbStore(DATABASE_PATH);
rdbStore_ = RdbHelper::GetRdbStore(config, 1, callback, errCode);
ASSERT_NE(rdbStore_, nullptr);
}
void QueryWithCrudTest::TearDownTestCase(void)
{
rdbStore_ = nullptr;
RdbHelper::DeleteRdbStore(DATABASE_PATH);
}
void QueryWithCrudTest::SetUp(void)
{
rdbStore_->ExecuteSql(DROP_TABLE);
rdbStore_->ExecuteSql(CREATE_TABLE);
}
void QueryWithCrudTest::TearDown(void)
{
rdbStore_->ExecuteSql(DROP_TABLE);
}
void QueryWithCrudTest::InsertData(int rowCount, int size)
{
EXPECT_GT(rowCount, 0);
EXPECT_GT(size, 0);
int64_t id;
ValuesBucket values;
std::vector<uint8_t> u8(size, 1);
std::vector<ValuesBucket> valuesBuckets;
for (int i = 0; i < rowCount; i++) {
values.Put("name", "zhangsan" + std::to_string(i));
values.Put("age", i);
values.Put("salary", SALARY);
values.Put("blobType", u8);
valuesBuckets.push_back(values);
}
auto ret = rdbStore_->BatchInsert(id, "test", valuesBuckets);
EXPECT_EQ(ret, E_OK);
EXPECT_EQ(id, rowCount);
}
* @tc.name: QueryWithDelete_001
* @tc.desc: 10 records with a total of less than 2M data,
* delete 3 records, rowCount equals 7 records.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_001, TestSize.Level1)
{
InsertData(10, 1);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 5, 7);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 3);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 7);
}
* @tc.name: QueryWithDelete_002
* @tc.desc: 10 pieces of 1M data, delete 3 pieces, rowCount equals 7 pieces.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_002, TestSize.Level1)
{
InsertData(10, 1024 * 1024);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 5, 7);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 3);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 7);
}
* @tc.name: QueryWithDelete_003
* @tc.desc: Single data exceeding 2M can return an error normally
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_003, TestSize.Level1)
{
InsertData(2, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.EqualTo("age", 1);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 1);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ERROR);
}
* @tc.name: QueryWithDelete_004
* @tc.desc: 2 pieces of single 2M data, delete 2 pieces, rowCount equals 0.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_004, TestSize.Level1)
{
InsertData(2, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 0, 1);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 2);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 0);
}
* @tc.name: QueryWithDelete_005
* @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M,
* delete 9 pieces of data less than 1M, expect an error.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_005, TestSize.Level1)
{
InsertData(9, 2);
InsertData(1, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("id", 1, 9);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 9);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ERROR);
}
* @tc.name: QueryWithDelete_006
* @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M,
* delete data greater than 2M, rowCount is 9.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_006, TestSize.Level1)
{
InsertData(9, 2);
InsertData(1, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.EqualTo("id", 10);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 1);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 9);
}
* @tc.name: QueryWithDelete_007
* @tc.desc: 10 records with a total of less than 2M data,
* delete 10 records, rowCount equals 0 records.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithDelete_007, TestSize.Level1)
{
InsertData(10, 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 10);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 0);
}
* @tc.name: QueryWithInsert_001
* @tc.desc: 10 pieces of data with a total size less than 2M, delete 3 pieces,
* insert 1 piece of data with a single size less than 1M, rowCount is equal to 8.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithInsert_001, TestSize.Level1)
{
InsertData(10, 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 5, 7);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 3);
EXPECT_EQ(res, E_OK);
InsertData(1, 2);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 8);
}
* @tc.name: QueryWithInsert_002
* @tc.desc: 10 pieces of data with a total size less than 2M, delete 4 pieces,
* insert 3 pieces of data with a single size less than 2M, rowCount is equal to 9.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithInsert_002, TestSize.Level1)
{
InsertData(10, 1024 * 1024);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 1, 4);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 4);
EXPECT_EQ(res, E_OK);
InsertData(3, 2);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 9);
}
* @tc.name: QueryWithInsert_003
* @tc.desc: 3 pieces of data larger than 2M, delete 2 pieces,
* insert 1 piece of data smaller than 1M, expect an error.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithInsert_003, TestSize.Level1)
{
InsertData(3, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 0, 1);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 2);
EXPECT_EQ(res, E_OK);
InsertData(1, 2);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ERROR);
}
* @tc.name: QueryWithInsert_004
* @tc.desc: 2 pieces of data larger than 2M, delete 2 pieces,
* insert 1 piece of data smaller than 1M, rowCount is equal to 1.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithInsert_004, TestSize.Level1)
{
InsertData(2, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 2);
EXPECT_EQ(res, E_OK);
InsertData(1, 2);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 1);
}
* @tc.name: QueryWithInsert_005
* @tc.desc: 10 pieces of data with a total of less than 2M, delete 6 pieces,
* insert 1 pieces of data with a single value greater than 2M, expect an error.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithInsert_005, TestSize.Level1)
{
InsertData(10, 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
predicates.Between("age", 0, 5);
int deletedRows;
auto res = rdbStore_->Delete(deletedRows, predicates);
EXPECT_EQ(deletedRows, 6);
EXPECT_EQ(res, E_OK);
InsertData(1, 1024 * 1024 * 2);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ERROR);
}
* @tc.name: QueryWithUpdate_001
* @tc.desc: 10 records with a total of less than 2M data, updated 3 records, rowCount is 10.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithUpdate_001, TestSize.Level1)
{
InsertData(10, 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
int updatedRows;
ValuesBucket values;
std::vector<uint8_t> u8(2, 1);
predicates.Between("age", 0, 2);
values.Put("name", "zhangsan30");
values.Put("age", 30);
values.Put("salary", SALARY);
values.Put("blobType", u8);
auto res = rdbStore_->Update(updatedRows, values, predicates);
EXPECT_EQ(updatedRows, 3);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 10);
}
* @tc.name: QueryWithUpdate_002
* @tc.desc: 10 pieces of single data less than 1M, update 3 pieces, rowCount is 10.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithUpdate_002, TestSize.Level1)
{
InsertData(10, 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
int updatedRows;
ValuesBucket values;
std::vector<uint8_t> bigU8(1024 * 1024 * 2, 1);
predicates.Between("age", 0, 2);
values.Put("name", "zhangsan30");
values.Put("age", 30);
values.Put("salary", SALARY);
values.Put("blobType", bigU8);
auto res = rdbStore_->Update(updatedRows, values, predicates);
EXPECT_EQ(updatedRows, 3);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ERROR);
}
* @tc.name: QueryWithUpdate_003
* @tc.desc: 2 pieces of data larger than 2M, update 2 pieces of data smaller than 1M,
* rowCount is 2.
* @tc.type: FUNC
*/
HWTEST_F(QueryWithCrudTest, QueryWithUpdate_003, TestSize.Level1)
{
InsertData(2, 1024 * 1024 * 2);
AbsRdbPredicates predicates("test");
auto resultSet = rdbStore_->Query(predicates);
ASSERT_NE(resultSet, nullptr);
int updatedRows;
ValuesBucket values;
std::vector<uint8_t> u8(2, 1);
predicates.Between("age", 0, 1);
values.Put("name", "zhangsan30");
values.Put("age", 30);
values.Put("salary", SALARY);
values.Put("blobType", u8);
auto res = rdbStore_->Update(updatedRows, values, predicates);
EXPECT_EQ(updatedRows, 2);
EXPECT_EQ(res, E_OK);
int errCode = E_OK;
while ((errCode = resultSet->GoToNextRow()) == E_OK) {
}
EXPECT_EQ(errCode, E_ROW_OUT_RANGE);
int count;
resultSet->GetRowCount(count);
EXPECT_EQ(count, 2);
}
}