• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "sqlite_relational_database_upgrader.h"
17 
18 #include "cloud/cloud_storage_utils.h"
19 #include "db_common.h"
20 #include "db_constant.h"
21 #include "db_errno.h"
22 #include "log_table_manager_factory.h"
23 #include "relational_schema_object.h"
24 #include "simple_tracker_log_table_manager.h"
25 #include "sqlite_relational_utils.h"
26 
27 namespace DistributedDB {
SqliteRelationalDatabaseUpgrader(sqlite3 * db)28 SqliteRelationalDatabaseUpgrader::SqliteRelationalDatabaseUpgrader(sqlite3 *db)
29     : db_(db)
30 {}
31 
~SqliteRelationalDatabaseUpgrader()32 SqliteRelationalDatabaseUpgrader::~SqliteRelationalDatabaseUpgrader() {}
33 
Upgrade()34 int SqliteRelationalDatabaseUpgrader::Upgrade()
35 {
36     // read version first, if not newest, start transaction
37     std::string logTableVersion;
38     int errCode = SQLiteUtils::GetLogTableVersion(db_, logTableVersion);
39     if (errCode != E_OK) {
40         LOGW("[Relational][Upgrade] Get log table version return. %d", errCode);
41         return (errCode == -E_NOT_FOUND) ? E_OK : errCode;
42     }
43     if (IsNewestVersion(logTableVersion)) {
44         return E_OK;
45     }
46 
47     errCode = BeginUpgrade();
48     if (errCode != E_OK) {
49         LOGE("[Relational][Upgrade] Begin upgrade failed. err=%d", errCode);
50         return errCode;
51     }
52 
53     errCode = ExecuteUpgrade();
54     if (errCode != E_OK) {
55         LOGE("[Relational][Upgrade] Execute upgrade failed. err=%d", errCode);
56         (void)EndUpgrade(false);
57         return errCode;
58     }
59 
60     errCode = EndUpgrade(true);
61     if (errCode != E_OK) {
62         LOGE("[Relational][Upgrade] End upgrade failed. err=%d", errCode);
63     }
64     return errCode;
65 }
66 
BeginUpgrade()67 int SqliteRelationalDatabaseUpgrader::BeginUpgrade()
68 {
69     return SQLiteUtils::BeginTransaction(db_, TransactType::IMMEDIATE);
70 }
71 
ExecuteUpgrade()72 int SqliteRelationalDatabaseUpgrader::ExecuteUpgrade()
73 {
74     std::string logTableVersion;
75     int errCode = SQLiteUtils::GetLogTableVersion(db_, logTableVersion);
76     if (errCode != E_OK) {
77         LOGW("[Relational][Upgrade] Get log table version return %d", errCode);
78         return (errCode == -E_NOT_FOUND) ? E_OK : errCode;
79     }
80 
81     if (IsNewestVersion(logTableVersion)) {
82         LOGD("[Relational][UpgradeTrigger] No need upgrade.");
83         return E_OK;
84     }
85 
86     RelationalSchemaObject schemaObj;
87     RelationalSchemaObject trackerSchemaObj;
88     errCode = GetParseSchema(schemaObj, trackerSchemaObj);
89     if (errCode != E_OK) {
90         return errCode;
91     }
92 
93     errCode = UpgradeLogTable(logTableVersion, schemaObj, trackerSchemaObj);
94     if (errCode != E_OK) {
95         LOGE("[Relational][Upgrade] Upgrade log table failed, err = %d.", errCode);
96         return errCode;
97     }
98 
99     return UpgradeTrigger(logTableVersion, schemaObj, trackerSchemaObj);
100 }
101 
EndUpgrade(bool isSuccess)102 int SqliteRelationalDatabaseUpgrader::EndUpgrade(bool isSuccess)
103 {
104     if (isSuccess) {
105         return SQLiteUtils::CommitTransaction(db_);
106     }
107 
108     return SQLiteUtils::RollbackTransaction(db_);
109 }
110 
IsNewestVersion(const std::string & logTableVersion)111 bool SqliteRelationalDatabaseUpgrader::IsNewestVersion(const std::string &logTableVersion)
112 {
113     return logTableVersion == DBConstant::LOG_TABLE_VERSION_CURRENT;
114 }
115 
UpgradeTrigger(const std::string & logTableVersion,const RelationalSchemaObject & schemaObj,const RelationalSchemaObject & trackerSchemaObj)116 int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTableVersion,
117     const RelationalSchemaObject &schemaObj, const RelationalSchemaObject &trackerSchemaObj)
118 {
119     DistributedTableMode mode = schemaObj.GetTableMode();
120     TableInfoMap trackerTables = trackerSchemaObj.GetTrackerTables();
121     for (const auto &table : schemaObj.GetTables()) {
122         bool isExists = false;
123         int errCode = SQLiteUtils::CheckTableExists(db_, table.first, isExists);
124         if (errCode == E_OK && !isExists) {
125             LOGI("[Relational][UpgradeLogTable] table may has been deleted, skip upgrade distributed trigger.");
126             continue;
127         }
128         TableInfo tableInfo = table.second;
129         tableInfo.SetTrackerTable(trackerSchemaObj.GetTrackerTable(table.first));
130         tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.first));
131         auto manager = LogTableManagerFactory::GetTableManager(tableInfo, mode, tableInfo.GetTableSyncType());
132         errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, "");
133         if (errCode != E_OK) {
134             LOGE("[Relational][Upgrade] recreate distributed trigger failed. err:%d", errCode);
135             return errCode;
136         }
137         trackerTables.erase(table.first);
138     }
139     // Need to upgrade non-distributed trigger
140     auto manager = std::make_unique<SimpleTrackerLogTableManager>();
141     for (const auto &table: trackerTables) {
142         TableInfo tableInfo;
143         int ret = SQLiteRelationalUtils::AnalysisTrackerTable(db_, table.second.GetTrackerTable(), tableInfo);
144         if (ret == -E_NOT_FOUND) {
145             LOGI("[Relational][Upgrade] table may has been deleted, skip upgrade tracker trigger.");
146             continue;
147         }
148         if (ret != E_OK) {
149             LOGE("[Relational][Upgrade] analysis tracker table schema failed %d.", ret);
150             return ret;
151         }
152         ret = manager->AddRelationalLogTableTrigger(db_, tableInfo, "");
153         if (ret != E_OK) {
154             LOGE("[Relational][Upgrade] recreate trigger failed. err:%d", ret);
155             return ret;
156         }
157     }
158     LOGI("[Relational][UpgradeLogTable] recreate trigger success, ver:%s to ver:%s", logTableVersion.c_str(),
159         DBConstant::LOG_TABLE_VERSION_CURRENT);
160     return E_OK;
161 }
162 
UpgradeLogTable(const std::string & logTableVersion,const RelationalSchemaObject & schemaObj,const RelationalSchemaObject & trackerSchemaObj)163 int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTableVersion,
164     const RelationalSchemaObject &schemaObj, const RelationalSchemaObject &trackerSchemaObj)
165 {
166     TableInfoMap trackerTables = trackerSchemaObj.GetTrackerTables();
167     for (const auto &table : schemaObj.GetTables()) {
168         int errCode = UpgradeLogBaseOnVersion(logTableVersion, table.first);
169         if (errCode != E_OK) {
170             LOGE("[Relational][UpgradeLogTable] upgrade distributed log table failed. err:%d", errCode);
171             return errCode;
172         }
173         trackerTables.erase(table.first);
174     }
175     // Need to upgrade non-distributed log table
176     for (const auto &table: trackerTables) {
177         int errCode = UpgradeLogBaseOnVersion(logTableVersion, table.first);
178         if (errCode != E_OK) {
179             LOGE("[Relational][UpgradeLogTable] upgrade tracker log table failed. err:%d", errCode);
180             return errCode;
181         }
182     }
183     LOGI("[Relational][UpgradeLogTable] success, ver:%s to ver:%s", logTableVersion.c_str(),
184         DBConstant::LOG_TABLE_VERSION_CURRENT);
185     return E_OK;
186 }
187 
UpgradeLogBaseOnVersion(const std::string & oldVersion,const std::string & tableName)188 int SqliteRelationalDatabaseUpgrader::UpgradeLogBaseOnVersion(const std::string &oldVersion,
189     const std::string &tableName)
190 {
191     std::string logName = DBCommon::GetLogTableName(tableName);
192     TableInfo tableInfo;
193     tableInfo.SetTableName(logName);
194     int errCode = SQLiteUtils::AnalysisSchemaFieldDefine(db_, logName, tableInfo);
195     if (errCode == E_OK && tableInfo.Empty()) {
196         LOGI("[Relational][UpgradeLogTable] table may has been deleted, skip upgrade log table.");
197         return E_OK;
198     }
199     if (errCode != E_OK) {
200         return errCode;
201     }
202     std::vector<std::string> addColSqlVec;
203     if (oldVersion < DBConstant::LOG_TABLE_VERSION_3) {
204         SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "cloud_gid", "text" } }, addColSqlVec);
205     }
206     if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_1) {
207         SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "extend_field", "blob" },
208             { "cursor", "int" }, { "version", "text" } }, addColSqlVec);
209     }
210     if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_3) {
211         SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "sharing_resource", "text" } }, addColSqlVec);
212     }
213     if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_5) {
214         SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "status", "int default 0" } }, addColSqlVec);
215     }
216     if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_8) {
217         addColSqlVec.push_back(CloudStorageUtils::GetCursorUpgradeSql(tableName));
218     }
219     for (size_t i = 0; i < addColSqlVec.size(); ++i) {
220         errCode = SQLiteUtils::ExecuteRawSQL(db_, addColSqlVec[i]);
221         if (errCode != E_OK) {
222             LOGE("[Relational][UpgradeLogTable] add column failed. err:%d, index:%zu, curVer:%s, maxVer:%s", errCode,
223                  i, oldVersion.c_str(), DBConstant::LOG_TABLE_VERSION_CURRENT);
224             return errCode;
225         }
226     }
227     return errCode;
228 }
229 
GetParseSchema(RelationalSchemaObject & schemaObj,RelationalSchemaObject & trackerSchemaObj)230 int SqliteRelationalDatabaseUpgrader::GetParseSchema(RelationalSchemaObject &schemaObj,
231     RelationalSchemaObject &trackerSchemaObj)
232 {
233     // get schema from meta
234     std::string schemaDefine;
235     int errCode = SQLiteUtils::GetRelationalSchema(db_, schemaDefine);
236     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
237         LOGE("[Relational][UpgradeTrigger] Get relational schema from meta return. err:%d", errCode);
238         return errCode;
239     }
240     if (errCode == -E_NOT_FOUND || schemaDefine.empty()) {
241         LOGI("[Relational][UpgradeTrigger] relational schema is empty:%d.", errCode);
242     } else {
243         errCode = schemaObj.ParseFromSchemaString(schemaDefine);
244         if (errCode != E_OK) {
245             LOGE("[Relational][UpgradeTrigger] Parse to relational schema failed. err:%d", errCode);
246             return errCode;
247         }
248     }
249 
250     std::string trackerSchemaDefine;
251     errCode = SQLiteUtils::GetRelationalSchema(db_, trackerSchemaDefine, DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY);
252     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
253         LOGE("[Relational][UpgradeTrigger] Get tracker schema from meta return. err:%d", errCode);
254         return errCode;
255     }
256     if (errCode == -E_NOT_FOUND || trackerSchemaDefine.empty()) {
257         LOGI("[Relational][UpgradeTrigger] tracker schema is empty:%d", errCode);
258     } else {
259         errCode = trackerSchemaObj.ParseFromTrackerSchemaString(trackerSchemaDefine);
260         if (errCode != E_OK) {
261             LOGE("[Relational][UpgradeTrigger] Parse to tracker schema failed. err:%d", errCode);
262             return errCode;
263         }
264     }
265     return E_OK;
266 }
267 } // namespace DistributedDB
268