* Copyright (c) 2024 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_migrate_mgr.h"
#include "app_domain_verify_hilog.h"
#include "app_domain_verify_hisysevent.h"
#include "rdb_errno.h"
#include "rdb_store.h"
namespace OHOS::AppDomainVerify {
constexpr int INNER_VERSION_UNKNOWN = 0;
constexpr int INNER_VERSION_1_0 = 1;
constexpr int INNER_VERSION_1_0_COL_CNT = 2;
constexpr int RDB_VERSION_1 = 1;
int RdbMigrateMgr::Upgrade(NativeRdb::RdbStore& rdbStore, int currVersion, int targetVersion)
{
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "currVersion:%{public}d to targetVersion:%{public}d",
currVersion, targetVersion);
int ret = NativeRdb::E_OK;
if (currVersion < RDB_VERSION_1) {
APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "unlikely branch");
return -1;
}
for (int i = currVersion - RDB_VERSION_1;
i < targetVersion - RDB_VERSION_1 && i < static_cast<int>(upgradeFuncs_.size()); i++) {
ret = (this->*upgradeFuncs_[i])(rdbStore);
if (ret != 0) {
APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE,
"upgrade failed currVersion:%{public}d to targetVersion:%{public}d, i:%{public}d", currVersion,
targetVersion, i);
break;
}
}
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called, end");
return ret;
}
RdbMigrateMgr::RdbMigrateMgr(const AppDomainVerifyRdbConfig& appDomainVerifyRdbConfig)
{
appDomainVerifyRdbConfig_ = appDomainVerifyRdbConfig;
upgradeFuncs_ = {
&RdbMigrateMgr::UpgradeFromV1ToV2,
&RdbMigrateMgr::UpgradeFromV2ToV3,
&RdbMigrateMgr::UpgradeFromV3ToV4,
};
}
int RdbMigrateMgr::QueryInnerVersion(NativeRdb::RdbStore& rdbStore)
{
NativeRdb::AbsRdbPredicates absRdbPredicates(appDomainVerifyRdbConfig_.tableName);
std::vector<std::string> columns = {};
auto absSharedResultSet = rdbStore.Query(absRdbPredicates, columns);
if (absSharedResultSet == nullptr) {
APP_DOMAIN_VERIFY_HILOGE(
APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "QueryInnerVersion query absSharedResultSet failed");
return INNER_VERSION_UNKNOWN;
}
int innerVersion = INNER_VERSION_UNKNOWN;
int count = -1;
absSharedResultSet->GetColumnCount(count);
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore GetColumnCount %{public}d", count);
if (count == INNER_VERSION_1_0_COL_CNT) {
innerVersion = INNER_VERSION_1_0;
}
absSharedResultSet->Close();
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore innerVersion %{public}d", innerVersion);
return innerVersion;
}
int RdbMigrateMgr::UpgradeFromV1ToV2(NativeRdb::RdbStore& rdbStore)
{
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
int innerVersion = QueryInnerVersion(rdbStore);
if (innerVersion != INNER_VERSION_1_0) {
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdbStore no need upgrade in UpgradeFromV1ToV2");
return 0;
}
const std::string migrateSqls[] = { R"(drop table IF EXISTS temp_table;)", R"(drop table IF EXISTS final_table;)",
R"(CREATE TEMPORARY TABLE temp_table AS
SELECT
verified_domain.KEY,
json_extract(verified_domain.VALUE, '$.appIdentifier') as appid,
json_extract(verified_domain.VALUE, '$.hostVerifyStatusMap') as map
FROM
verified_domain;)",
R"(CREATE TABLE final_table AS
SELECT
temp_table.KEY as BUNDLE_NAME,
temp_table.appid as APP_IDENTIFIER,
json_each.key AS DOMAIN,
json_each.value AS VERIFY_STATUES
FROM
temp_table,
json_each(temp_table.map);)",
R"(drop table IF EXISTS verified_domain;)",
R"(CREATE TABLE IF NOT EXISTS verified_domain (ID INTEGER PRIMARY KEY AUTOINCREMENT, BUNDLE_NAME TEXT NOT NULL,
APP_IDENTIFIER TEXT,
DOMAIN TEXT NOT NULL, VERIFY_STATUES INTEGER);)",
R"(INSERT INTO verified_domain (BUNDLE_NAME,APP_IDENTIFIER,DOMAIN,VERIFY_STATUES) select * from final_table;)",
R"(drop table IF EXISTS final_table;)" };
int ret = 0;
for (const auto& sql : migrateSqls) {
ret = rdbStore.ExecuteSql(sql);
if (ret != NativeRdb::E_OK) {
APP_DOMAIN_VERIFY_HILOGE(
APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "execute sql %{public}s failed.", sql.c_str());
UNIVERSAL_ERROR_EVENT(UPDATE_DB_FAULT);
auto dropTableSql = R"(drop table IF EXISTS verified_domain;)";
ret = rdbStore.ExecuteSql(dropTableSql);
APP_DOMAIN_VERIFY_HILOGE(
APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "UpgradeFromV1_0 executeSql failed, ret: %{public}d", ret);
break;
}
}
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
return ret;
}
int RdbMigrateMgr::UpgradeFromV2ToV3(NativeRdb::RdbStore& rdbStore)
{
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
const std::string migrateSqls[] = {
R"(ALTER TABLE verified_domain ADD COLUMN VERIFY_TIME TEXT NOT NULL DEFAULT '';)",
R"(ALTER TABLE verified_domain ADD COLUMN VERIFY_COUNT INTERGER NULL DEFAULT 0;)",
};
int ret = ExecSqlWithTrans(rdbStore, [&](NativeRdb::RdbStore& rdbStore) -> bool {
for (const auto& sql : migrateSqls) {
auto ret = rdbStore.ExecuteSql(sql);
if (ret != NativeRdb::E_OK) {
APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE,
"UpgradeFromV2ToV3 executeSql failed, ret: %{public}d, reason: exec %{public}s fail.", ret,
sql.c_str());
return false;
}
}
return true;
});
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called end, ret:%{public}d", ret);
return ret;
}
int RdbMigrateMgr::UpgradeFromV3ToV4(NativeRdb::RdbStore& rdbStore)
{
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
const std::string migrateSqls[] = {
R"(ALTER TABLE verified_domain ADD COLUMN VERIFY_PRIORITY INTERGER NOT NULL DEFAULT -1000;)",
};
int ret = ExecSqlWithTrans(rdbStore, [&](NativeRdb::RdbStore& rdbStore) -> bool {
for (const auto& sql : migrateSqls) {
auto ret = rdbStore.ExecuteSql(sql);
if (ret != NativeRdb::E_OK) {
APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE,
"UpgradeFromV3ToV4 executeSql failed, ret: %{public}d, reason: exec %{public}s fail.", ret,
sql.c_str());
return false;
}
}
return true;
});
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called end, ret:%{public}d", ret);
return ret;
}
int RdbMigrateMgr::ExecSqlWithTrans(NativeRdb::RdbStore& rdbStore, const TransFunc& func)
{
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "called");
auto ret = rdbStore.BeginTransaction();
if (ret != NativeRdb::E_OK) {
return ret;
}
if (func(rdbStore)) {
return rdbStore.Commit();
}
APP_DOMAIN_VERIFY_HILOGI(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb exec roll back");
ret = rdbStore.RollBack();
if (ret != NativeRdb::E_OK) {
APP_DOMAIN_VERIFY_HILOGE(APP_DOMAIN_VERIFY_MGR_MODULE_SERVICE, "rdb exec roll back fail.");
return ret;
}
return NativeRdb::E_ERROR;
}
}