From 5e855138f1c8f035439f8acb20379d36d91d6155 Mon Sep 17 00:00:00 2001 From: lobty Date: Tue, 19 Aug 2025 17:07:04 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=88=86=E5=B8=83=E5=BC=8FDB=E3=80=91?= =?UTF-8?q?=E3=80=90RDB=E3=80=91=E6=81=A2=E5=A4=8D=E6=90=9C=E7=B4=A2extend?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E4=B8=B2=E7=9A=84=E5=BC=82=E5=B8=B8=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lobty --- ...ver_relational_storage_extend_executor.cpp | 4 +- frameworks/libs/distributeddb/test/BUILD.gn | 6 + .../unittest/common/common/rdb_general_ut.cpp | 12 ++ .../unittest/common/common/rdb_general_ut.h | 2 + .../rdb/distributeddb_rdb_upgrade_test.cpp | 148 ++++++++++++++++++ 5 files changed, 170 insertions(+), 2 deletions(-) create mode 100644 frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index be39206cd46..dad090304ca 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -2049,7 +2049,7 @@ void SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLog(const Tracke return; } std::string sql = "SELECT COUNT(1) FROM " + DBCommon::GetLogTableName(trackerSchema.tableName) + - " WHERE json_type(extend_field) IS NOT 'object' AND data_key != -1"; + " WHERE (json_valid(extend_field) = 0 OR json_type(extend_field) IS NOT 'object') AND data_key != -1"; if (!SQLiteRelationalUtils::ExecuteCheckSql(dbHandle_, sql).second) { return; } @@ -2083,7 +2083,7 @@ int SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLogInner(const Tr }); actions.emplace_back([this, &trackerSchema]() { return UpdateExtendField(trackerSchema.tableName, trackerSchema.extendColNames, - " AND json_type(log.extend_field) IS NOT 'object'"); + " AND (json_valid(log.extend_field) = 0 OR json_type(log.extend_field) IS NOT 'object')"); }); actions.emplace_back([this]() { return ClearAllTempSyncTrigger(); diff --git a/frameworks/libs/distributeddb/test/BUILD.gn b/frameworks/libs/distributeddb/test/BUILD.gn index fc3cc7e1352..de3c086fd81 100644 --- a/frameworks/libs/distributeddb/test/BUILD.gn +++ b/frameworks/libs/distributeddb/test/BUILD.gn @@ -920,6 +920,11 @@ distributeddb_unittest("DistributedDBRDBDropTableTest") { [ "unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp" ] } +distributeddb_unittest("DistributedDBRDBUpgradeTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp" ] +} + config("tokenizer_config_unittest") { visibility = [ ":*" ] include_dirs = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include" ] @@ -1204,6 +1209,7 @@ group("unittest") { ":DistributedDBRDBKnowledgeClientTest", ":DistributedDBRDBKnowledgeTest", ":DistributedDBRDBMultiUserSyncTest", + ":DistributedDBRDBUpgradeTest", ":DistributedDBRelationalCloudSyncableStorageTest", ":DistributedDBRelationalEncryptedDbTest", ":DistributedDBRelationalGetDataTest", diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp index 9c498c8d838..831e0a330cc 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp @@ -15,6 +15,7 @@ #include "rdb_general_ut.h" #include "rdb_data_generator.h" #include "runtime_config.h" +#include "sqlite_relational_utils.h" #include "virtual_cloud_data_translate.h" using namespace DistributedDBUnitTest; @@ -581,4 +582,15 @@ void RDBGeneralUt::RemoteQuery(const StoreInfo &from, const StoreInfo &to, const EXPECT_EQ(store->RemoteQuery(toDevice, condition, DBConstant::MAX_TIMEOUT, resultSet), expectRet); EXPECT_NE(resultSet, nullptr); } + +int RDBGeneralUt::PutMetaData(const StoreInfo &store, const Key &key, const Value &value) +{ + auto db = GetSqliteHandle(store); + if (db == nullptr) { + LOGE("[RDBGeneralUt] Get null sqlite when put meta data userId[%s] appId[%s] storeId[%s]", + store.userId.c_str(), store.appId.c_str(), store.storeId.c_str()); + return -E_INTERNAL_ERROR; + } + return SQLiteRelationalUtils::PutKvData(db, false, key, value); +} } \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h index b492d725ee7..6eebce0a31a 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h +++ b/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h @@ -96,6 +96,8 @@ protected: void RemoteQuery(const StoreInfo &from, const StoreInfo &to, const std::string &sql, DBStatus expectRet); + int PutMetaData(const StoreInfo &store, const Key &key, const Value &value); + mutable std::mutex storeMutex_; std::map stores_; std::map sqliteDb_; diff --git a/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp new file mode 100644 index 00000000000..f3c51b4034b --- /dev/null +++ b/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2025 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 "rdb_general_ut.h" +#include "sqlite_relational_utils.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +class DistributedDBRDBUpgradeTest : public RDBGeneralUt { +public: + void SetUp() override; + void TearDown() override; +protected: + void InitUpgradeDelegate(); + void InitNoJsonTrackerSchema(); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; +}; + +void DistributedDBRDBUpgradeTest::SetUp() +{ + RDBGeneralUt::SetUp(); +} + +void DistributedDBRDBUpgradeTest::TearDown() +{ + RDBGeneralUt::TearDown(); +} + +void DistributedDBRDBUpgradeTest::InitUpgradeDelegate() +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + const std::vector filedInfo = { + {{"id", TYPE_INDEX, true, false}, true}, {{"name1", TYPE_INDEX, false, true}, false}, + {{"name2", TYPE_INDEX, false, true}, false} + }; + UtDateBaseSchemaInfo schemaInfo = { + .tablesInfo = {{.name = DEVICE_SYNC_TABLE, .fieldInfo = filedInfo}} + }; + RDBGeneralUt::SetSchemaInfo(info1, schemaInfo); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); +} + +void DistributedDBRDBUpgradeTest::InitNoJsonTrackerSchema() +{ + std::string keyStr = "relational_tracker_schema"; + Key key(keyStr.begin(), keyStr.end()); + std::string schemaStr = R"({"SCHEMA_TYPE":"TRACKER","TABLES":[ + {"NAME": "DEVICE_SYNC_TABLE", "EXTEND_NAME": "id", + "TRACKER_NAMES": ["id", "name1", "name2"], "TRACKER_ACTION": false}]})"; + Value value(schemaStr.begin(), schemaStr.end()); + ASSERT_EQ(PutMetaData(GetStoreInfo1(), key, value), E_OK); +} + +/** + * @tc.name: UpgradeTracker001 + * @tc.desc: Test rdb upgrade extend field from no json to json. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log, low version schema. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=1"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitNoJsonTrackerSchema()); + EXPECT_EQ(CloseDelegate(info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + /** + * @tc.steps: step3. Set tracker table and create distributed table. + * @tc.expected: step3. Ok + */ + auto store = GetDelegate(info1); + ASSERT_NE(store, nullptr); + EXPECT_EQ(CreateDistributedTable(info1, DEVICE_SYNC_TABLE), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step4. Check log extend field. + * @tc.expected: step4. Ok + */ + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_type(extend_field) = 'object'"), 1); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} + +/** + * @tc.name: UpgradeTracker002 + * @tc.desc: Test rdb upgrade extend field is no json format. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log update extend_field to empty str. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=''"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 1); + /** + * @tc.steps: step3. Set tracker again and check log. + * @tc.expected: step3. Ok + */ + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} +} \ No newline at end of file -- Gitee