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 auto manager = LogTableManagerFactory::GetTableManager(mode, tableInfo.GetTableSyncType());
131 errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, "");
132 if (errCode != E_OK) {
133 LOGE("[Relational][Upgrade] recreate distributed trigger failed. err:%d", errCode);
134 return errCode;
135 }
136 trackerTables.erase(table.first);
137 }
138 // Need to upgrade non-distributed trigger
139 auto manager = std::make_unique<SimpleTrackerLogTableManager>();
140 for (const auto &table: trackerTables) {
141 TableInfo tableInfo;
142 int ret = SQLiteRelationalUtils::AnalysisTrackerTable(db_, table.second.GetTrackerTable(), tableInfo);
143 if (ret == -E_NOT_FOUND) {
144 LOGI("[Relational][Upgrade] table may has been deleted, skip upgrade tracker trigger.");
145 continue;
146 }
147 if (ret != E_OK) {
148 LOGE("[Relational][Upgrade] analysis tracker table schema failed %d.", ret);
149 return ret;
150 }
151 ret = manager->AddRelationalLogTableTrigger(db_, tableInfo, "");
152 if (ret != E_OK) {
153 LOGE("[Relational][Upgrade] recreate trigger failed. err:%d", ret);
154 return ret;
155 }
156 }
157 LOGI("[Relational][UpgradeLogTable] recreate trigger success, ver:%s to ver:%s", logTableVersion.c_str(),
158 DBConstant::LOG_TABLE_VERSION_CURRENT);
159 return E_OK;
160 }
161
UpgradeLogTable(const std::string & logTableVersion,const RelationalSchemaObject & schemaObj,const RelationalSchemaObject & trackerSchemaObj)162 int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTableVersion,
163 const RelationalSchemaObject &schemaObj, const RelationalSchemaObject &trackerSchemaObj)
164 {
165 TableInfoMap trackerTables = trackerSchemaObj.GetTrackerTables();
166 for (const auto &table : schemaObj.GetTables()) {
167 int errCode = UpgradeLogBaseOnVersion(logTableVersion, table.first);
168 if (errCode != E_OK) {
169 LOGE("[Relational][UpgradeLogTable] upgrade distributed log table failed. err:%d", errCode);
170 return errCode;
171 }
172 trackerTables.erase(table.first);
173 }
174 // Need to upgrade non-distributed log table
175 for (const auto &table: trackerTables) {
176 int errCode = UpgradeLogBaseOnVersion(logTableVersion, table.first);
177 if (errCode != E_OK) {
178 LOGE("[Relational][UpgradeLogTable] upgrade tracker log table failed. err:%d", errCode);
179 return errCode;
180 }
181 }
182 LOGI("[Relational][UpgradeLogTable] success, ver:%s to ver:%s", logTableVersion.c_str(),
183 DBConstant::LOG_TABLE_VERSION_CURRENT);
184 return E_OK;
185 }
186
UpgradeLogBaseOnVersion(const std::string & oldVersion,const std::string & tableName)187 int SqliteRelationalDatabaseUpgrader::UpgradeLogBaseOnVersion(const std::string &oldVersion,
188 const std::string &tableName)
189 {
190 std::string logName = DBCommon::GetLogTableName(tableName);
191 TableInfo tableInfo;
192 tableInfo.SetTableName(logName);
193 int errCode = SQLiteUtils::AnalysisSchemaFieldDefine(db_, logName, tableInfo);
194 if (errCode == E_OK && tableInfo.Empty()) {
195 LOGI("[Relational][UpgradeLogTable] table may has been deleted, skip upgrade log table.");
196 return E_OK;
197 }
198 if (errCode != E_OK) {
199 return errCode;
200 }
201 std::vector<std::string> addColSqlVec;
202 if (oldVersion < DBConstant::LOG_TABLE_VERSION_3) {
203 SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "cloud_gid", "text" } }, addColSqlVec);
204 }
205 if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_1) {
206 SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "extend_field", "blob" },
207 { "cursor", "int" }, { "version", "text" } }, addColSqlVec);
208 }
209 if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_3) {
210 SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "sharing_resource", "text" } }, addColSqlVec);
211 }
212 if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_5) {
213 SQLiteRelationalUtils::AddUpgradeSqlToList(tableInfo, { { "status", "int default 0" } }, addColSqlVec);
214 }
215 if (oldVersion < DBConstant::LOG_TABLE_VERSION_5_8) {
216 addColSqlVec.push_back(CloudStorageUtils::GetCursorUpgradeSql(tableName));
217 }
218 for (size_t i = 0; i < addColSqlVec.size(); ++i) {
219 errCode = SQLiteUtils::ExecuteRawSQL(db_, addColSqlVec[i]);
220 if (errCode != E_OK) {
221 LOGE("[Relational][UpgradeLogTable] add column failed. err:%d, index:%zu, curVer:%s, maxVer:%s", errCode,
222 i, oldVersion.c_str(), DBConstant::LOG_TABLE_VERSION_CURRENT);
223 return errCode;
224 }
225 }
226 return errCode;
227 }
228
GetParseSchema(RelationalSchemaObject & schemaObj,RelationalSchemaObject & trackerSchemaObj)229 int SqliteRelationalDatabaseUpgrader::GetParseSchema(RelationalSchemaObject &schemaObj,
230 RelationalSchemaObject &trackerSchemaObj)
231 {
232 // get schema from meta
233 std::string schemaDefine;
234 int errCode = SQLiteUtils::GetRelationalSchema(db_, schemaDefine);
235 if (errCode != E_OK && errCode != -E_NOT_FOUND) {
236 LOGE("[Relational][UpgradeTrigger] Get relational schema from meta return. err:%d", errCode);
237 return errCode;
238 }
239 if (errCode == -E_NOT_FOUND || schemaDefine.empty()) {
240 LOGI("[Relational][UpgradeTrigger] relational schema is empty:%d.", errCode);
241 } else {
242 errCode = schemaObj.ParseFromSchemaString(schemaDefine);
243 if (errCode != E_OK) {
244 LOGE("[Relational][UpgradeTrigger] Parse to relational schema failed. err:%d", errCode);
245 return errCode;
246 }
247 }
248
249 std::string trackerSchemaDefine;
250 errCode = SQLiteUtils::GetRelationalSchema(db_, trackerSchemaDefine, DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY);
251 if (errCode != E_OK && errCode != -E_NOT_FOUND) {
252 LOGE("[Relational][UpgradeTrigger] Get tracker schema from meta return. err:%d", errCode);
253 return errCode;
254 }
255 if (errCode == -E_NOT_FOUND || trackerSchemaDefine.empty()) {
256 LOGI("[Relational][UpgradeTrigger] tracker schema is empty:%d", errCode);
257 } else {
258 errCode = trackerSchemaObj.ParseFromTrackerSchemaString(trackerSchemaDefine);
259 if (errCode != E_OK) {
260 LOGE("[Relational][UpgradeTrigger] Parse to tracker schema failed. err:%d", errCode);
261 return errCode;
262 }
263 }
264 return E_OK;
265 }
266 } // namespace DistributedDB
267