1 /*
2  * Copyright (C) 2024 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 #include "db_upgrade_utils.h"
16 
17 #include <string>
18 #include <vector>
19 
20 #include "rdb_store.h"
21 #include "media_log.h"
22 #include "result_set_utils.h"
23 
24 namespace OHOS::Media {
25 namespace DataTransfer {
26 /**
27  * @brief Check table exists or not.
28  */
IsTableExists(NativeRdb::RdbStore & store,const std::string & tableName)29 bool DbUpgradeUtils::IsTableExists(NativeRdb::RdbStore &store, const std::string &tableName)
30 {
31     std::string querySql = this->SQL_SQLITE_MASTER_QUERY;
32     std::vector<NativeRdb::ValueObject> bindArgs = {tableName};
33     auto resultSet = store.QuerySql(querySql, bindArgs);
34     if (resultSet == nullptr) {
35         MEDIA_WARN_LOG("Query resultSql is null. tableName: %{public}s is not exists.", tableName.c_str());
36         return false;
37     }
38     int rowCount = 0;
39     bool isExists = !resultSet->GetRowCount(rowCount) && rowCount > 0;
40     MEDIA_INFO_LOG("Media_Restore: tableName=%{public}s, isExists:%{public}d", tableName.c_str(), isExists);
41     return isExists;
42 }
43 
44 /**
45  * @brief Check table column exists or not.
46  */
IsColumnExists(NativeRdb::RdbStore & store,const std::string & tableName,const std::string & columnName)47 bool DbUpgradeUtils::IsColumnExists(
48     NativeRdb::RdbStore &store, const std::string &tableName, const std::string &columnName)
49 {
50     std::string querySql = this->SQL_PRAGMA_TABLE_INFO_QUERY;
51     std::vector<NativeRdb::ValueObject> bindArgs = {tableName, columnName};
52     auto resultSet = store.QuerySql(querySql, bindArgs);
53     if (resultSet == nullptr) {
54         MEDIA_WARN_LOG("Query resultSql is null. tableName: %{public}s, columnName: %{public}s is not exists.",
55             tableName.c_str(),
56             columnName.c_str());
57         return false;
58     }
59     int rowCount = 0;
60     bool isExists = !resultSet->GetRowCount(rowCount) && rowCount > 0;
61     MEDIA_INFO_LOG("Media_Restore: tableName=%{public}s, columnName=%{public}s, isExists:%{public}d",
62         tableName.c_str(),
63         columnName.c_str(),
64         isExists);
65     return isExists;
66 }
67 
GetAllTriggers(NativeRdb::RdbStore & store,const std::string & tableName)68 std::vector<std::string> DbUpgradeUtils::GetAllTriggers(NativeRdb::RdbStore &store, const std::string &tableName)
69 {
70     std::string querySql = this->SQL_SQLITE_MASTER_QUERY_TRIGGER;
71     std::vector<NativeRdb::ValueObject> bindArgs = {tableName};
72     auto resultSet = store.QuerySql(querySql, bindArgs);
73     std::vector<std::string> result;
74     if (resultSet == nullptr) {
75         MEDIA_WARN_LOG("Query resultSql is null. tableName: %{public}s does not have any triggers.", tableName.c_str());
76         return result;
77     }
78     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
79         std::string triggerName = GetStringVal("name", resultSet);
80         result.emplace_back(triggerName);
81     }
82     return result;
83 }
84 
DropAllTriggers(NativeRdb::RdbStore & store,const std::string & tableName)85 int32_t DbUpgradeUtils::DropAllTriggers(NativeRdb::RdbStore &store, const std::string &tableName)
86 {
87     const std::vector<std::string> triggerNames = this->GetAllTriggers(store, tableName);
88     std::string prefix = "DROP TRIGGER IF EXISTS ";
89     for (auto &triggerName : triggerNames) {
90         std::string deleteTriggerSql = prefix + triggerName + ";";
91         int32_t ret = store.ExecuteSql(deleteTriggerSql);
92         if (ret != NativeRdb::E_OK) {
93             MEDIA_ERR_LOG("Media_Restore: Drop trigger failed, triggerName=%{public}s", triggerName.c_str());
94         }
95     }
96     return NativeRdb::E_OK;
97 }
GetAllUniqueIndex(NativeRdb::RdbStore & store,const std::string & tableName)98 std::vector<std::string> DbUpgradeUtils::GetAllUniqueIndex(NativeRdb::RdbStore &store, const std::string &tableName)
99 {
100     std::string querySql = this->SQL_SQLITE_MASTER_QUERY_UNIQUE_INDEX;
101     std::vector<NativeRdb::ValueObject> bindArgs = {tableName};
102     auto resultSet = store.QuerySql(querySql, bindArgs);
103     std::vector<std::string> result;
104     if (resultSet == nullptr) {
105         MEDIA_WARN_LOG("resultSet is null. tableName: %{public}s does not have any unique index.", tableName.c_str());
106         return result;
107     }
108     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
109         std::string uniqueIndexName = GetStringVal("name", resultSet);
110         result.emplace_back(uniqueIndexName);
111     }
112     return result;
113 }
114 
DropAllUniqueIndex(NativeRdb::RdbStore & store,const std::string & tableName)115 int32_t DbUpgradeUtils::DropAllUniqueIndex(NativeRdb::RdbStore &store, const std::string &tableName)
116 {
117     const std::vector<std::string> uniqueIndexNames = this->GetAllUniqueIndex(store, tableName);
118     std::string prefix = "DROP INDEX IF EXISTS ";
119     for (auto &indexName : uniqueIndexNames) {
120         std::string deleteIndexSql = prefix + indexName + ";";
121         int32_t ret = store.ExecuteSql(deleteIndexSql);
122         if (ret != NativeRdb::E_OK) {
123             MEDIA_ERR_LOG("Media_Restore: Drop trigger failed, indexName=%{public}s", indexName.c_str());
124         }
125     }
126     return NativeRdb::E_OK;
127 }
128 }  // namespace DataTransfer
129 }  // namespace OHOS::Media