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