1 /*
2 * Copyright (c) 2021 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_single_ver_database_upgrader.h"
17 #include "db_errno.h"
18 #include "log_print.h"
19 #include "version.h"
20 #include "db_constant.h"
21 #include "platform_specific.h"
22 #include "param_check_utils.h"
23 #include "runtime_context.h"
24
25 namespace DistributedDB {
26 namespace {
27 const std::string CREATE_LOCAL_TABLE_SQL =
28 "CREATE TABLE IF NOT EXISTS local_data(" \
29 "key BLOB PRIMARY KEY," \
30 "value BLOB," \
31 "timestamp INT," \
32 "hash_key BLOB);";
33
34 const std::string CREATE_SYNC_TABLE_SQL =
35 "CREATE TABLE IF NOT EXISTS sync_data(" \
36 "key BLOB NOT NULL," \
37 "value BLOB," \
38 "timestamp INT NOT NULL," \
39 "flag INT NOT NULL," \
40 "device BLOB," \
41 "ori_device BLOB," \
42 "hash_key BLOB PRIMARY KEY NOT NULL," \
43 "w_timestamp INT);";
44
45 const std::string CREATE_META_TABLE_SQL =
46 "CREATE TABLE IF NOT EXISTS meta_data(" \
47 "key BLOB PRIMARY KEY NOT NULL," \
48 "value BLOB);";
49
50 const std::string CREATE_SINGLE_META_TABLE_SQL =
51 "CREATE TABLE IF NOT EXISTS meta.meta_data(" \
52 "key BLOB PRIMARY KEY NOT NULL," \
53 "value BLOB);";
54
55 const std::string CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX =
56 "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);";
57
58 const std::string CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX =
59 "CREATE INDEX IF NOT EXISTS time_index ON sync_data (timestamp);";
60
61 const std::string CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX =
62 "CREATE INDEX IF NOT EXISTS dev_index ON sync_data (device);";
63
64 const std::string CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX =
65 "CREATE INDEX IF NOT EXISTS local_hashkey_index ON local_data (hash_key);";
66
67 const std::string DROP_META_TABLE_SQL = "DROP TABLE IF EXISTS main.meta_data;";
68 const std::string COPY_META_TABLE_SQL = "INSERT OR REPLACE INTO meta.meta_data SELECT * FROM meta_data "
69 "where (SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='main.meta_data') > 0;";
70 }
71
SQLiteSingleVerDatabaseUpgrader(sqlite3 * db,const SecurityOption & secopt,bool isMemDb)72 SQLiteSingleVerDatabaseUpgrader::SQLiteSingleVerDatabaseUpgrader(sqlite3 *db,
73 const SecurityOption &secopt, bool isMemDb)
74 : db_(db),
75 secOpt_(secopt),
76 isMemDB_(isMemDb),
77 isMetaUpgrade_(false)
78 {
79 }
80
~SQLiteSingleVerDatabaseUpgrader()81 SQLiteSingleVerDatabaseUpgrader::~SQLiteSingleVerDatabaseUpgrader()
82 {
83 db_ = nullptr;
84 }
85
TransferDatabasePath(const std::string & parentDir,const OpenDbProperties & option)86 int SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(const std::string &parentDir,
87 const OpenDbProperties &option)
88 {
89 std::string dbFilePath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION;
90 std::string upgradeLockFile = parentDir + "/" + DBConstant::UPGRADE_POSTFIX;
91
92 if (OS::CheckPathExistence(upgradeLockFile)) {
93 return MoveDatabaseToNewDir(parentDir, upgradeLockFile);
94 }
95 if (OS::CheckPathExistence(dbFilePath)) {
96 int currentVersion = 0;
97 int errCode = GetDbVersion(dbFilePath, option, currentVersion);
98 if (errCode != E_OK) {
99 LOGE("[SQLiteSinVerUp] Get version of old database failed");
100 return errCode;
101 }
102 if (currentVersion == 0) {
103 LOGI("The database file has not been initialized, maybe invalid database");
104 if (OS::RemoveFile(dbFilePath) != E_OK) {
105 LOGE("[SQLiteSinVerUp] Remove the uninitialized database failed, errno[%d]", errno);
106 return -E_SYSTEM_API_FAIL;
107 }
108 }
109 if (currentVersion >= SINGLE_VER_STORE_VERSION_V1 && currentVersion <= SINGLE_VER_STORE_VERSION_V2) {
110 LOGI("[SQLiteSinVerUp] Old version[%d] database exists.", currentVersion);
111 if (OS::CreateFileByFileName(upgradeLockFile) != E_OK) {
112 return -E_SYSTEM_API_FAIL;
113 }
114 return MoveDatabaseToNewDir(parentDir, upgradeLockFile);
115 }
116 }
117 return E_OK;
118 }
119
BeginUpgrade()120 int SQLiteSingleVerDatabaseUpgrader::BeginUpgrade()
121 {
122 return SQLiteUtils::BeginTransaction(db_, TransactType::IMMEDIATE);
123 }
124
EndUpgrade(bool isSuccess)125 int SQLiteSingleVerDatabaseUpgrader::EndUpgrade(bool isSuccess)
126 {
127 if (isSuccess) {
128 return SQLiteUtils::CommitTransaction(db_);
129 } else {
130 int errCode = SQLiteUtils::RollbackTransaction(db_);
131 std::string secOptUpgradeFile = subDir_ + "/" + DBConstant::SET_SECOPT_POSTFIX;
132 if (errCode == E_OK && OS::CheckPathExistence(secOptUpgradeFile) &&
133 (OS::RemoveFile(secOptUpgradeFile) != E_OK)) {
134 LOGW("[EndUpgrade] Delete secure upgrade file failed");
135 return -E_SYSTEM_API_FAIL;
136 }
137 return errCode;
138 }
139 }
140
GetDatabaseVersion(int & version) const141 int SQLiteSingleVerDatabaseUpgrader::GetDatabaseVersion(int &version) const
142 {
143 return SQLiteUtils::GetVersion(db_, version);
144 }
145
SetDatabaseVersion(int version)146 int SQLiteSingleVerDatabaseUpgrader::SetDatabaseVersion(int version)
147 {
148 return SQLiteUtils::SetUserVer(db_, version);
149 }
150
SetUpgradeSqls(int version,std::vector<std::string> & sqls,bool & isCreateUpgradeFile) const151 void SQLiteSingleVerDatabaseUpgrader::SetUpgradeSqls(int version, std::vector<std::string> &sqls,
152 bool &isCreateUpgradeFile) const
153 {
154 if (version == 0) { // no write version.
155 if ((!isMemDB_) && ParamCheckUtils::IsS3SECEOpt(secOpt_)) {
156 sqls = {
157 CREATE_LOCAL_TABLE_SQL,
158 CREATE_SINGLE_META_TABLE_SQL,
159 CREATE_SYNC_TABLE_SQL,
160 CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX,
161 CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX,
162 CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX,
163 CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX
164 };
165 } else {
166 sqls = {
167 CREATE_LOCAL_TABLE_SQL,
168 CREATE_META_TABLE_SQL,
169 CREATE_SYNC_TABLE_SQL,
170 CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX,
171 CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX,
172 CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX,
173 CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX
174 };
175 }
176 } else {
177 if (version <= SINGLE_VER_STORE_VERSION_V1) {
178 sqls = {
179 "DROP INDEX key_index;",
180 "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);",
181 "ALTER TABLE sync_data ADD w_timestamp INT;",
182 "UPDATE sync_data SET w_timestamp=timestamp;",
183 "ALTER TABLE local_data ADD timestamp INT;",
184 "ALTER TABLE local_data ADD hash_key BLOB;",
185 "UPDATE local_data SET hash_key=calc_hash_key(key), timestamp=0;",
186 "CREATE INDEX IF NOT EXISTS local_hashkey_index ON local_data (hash_key);"
187 };
188 }
189 if ((version <= SINGLE_VER_STORE_VERSION_V2 && ParamCheckUtils::IsS3SECEOpt(secOpt_)) ||
190 (version == SINGLE_VER_STORE_VERSION_CURRENT && isMetaUpgrade_ == true)) {
191 sqls.push_back(CREATE_SINGLE_META_TABLE_SQL);
192 sqls.push_back(COPY_META_TABLE_SQL);
193 sqls.push_back(DROP_META_TABLE_SQL);
194 isCreateUpgradeFile = true;
195 }
196 }
197 }
198
UpgradeFromDatabaseVersion(int version)199 int SQLiteSingleVerDatabaseUpgrader::UpgradeFromDatabaseVersion(int version)
200 {
201 std::vector<std::string> sqls;
202 bool isCreateUpgradeFile = false;
203 LOGI("[SqlSingleUp] metaSplit[%d], secLabel[%d], secFlag[%d]",
204 isMetaUpgrade_, secOpt_.securityLabel, secOpt_.securityFlag);
205 SetUpgradeSqls(version, sqls, isCreateUpgradeFile);
206 for (const auto &item : sqls) {
207 int errCode = SQLiteUtils::ExecuteRawSQL(db_, item);
208 if (errCode != E_OK) {
209 LOGE("[SqlSingleUp][UpFrom] Execute upgrade sql failed:%d", errCode);
210 return errCode;
211 }
212 }
213 if (isCreateUpgradeFile) {
214 std::string secOptUpgradeFile = subDir_ + "/" + DBConstant::SET_SECOPT_POSTFIX;
215 if (!OS::CheckPathExistence(secOptUpgradeFile) && (OS::CreateFileByFileName(secOptUpgradeFile) != E_OK)) {
216 LOGE("[SqlSingleUp][UpFrom] Create s3sece flag file failed");
217 return -E_SYSTEM_API_FAIL;
218 }
219 LOGD("[SqlSingleUp][UpFrom] Create s3sece mark file success");
220 }
221 return E_OK;
222 }
223
GetDbVersion(const std::string & dbPath,const OpenDbProperties & option,int & version)224 int SQLiteSingleVerDatabaseUpgrader::GetDbVersion(const std::string &dbPath, const OpenDbProperties &option,
225 int &version)
226 {
227 OpenDbProperties optionTmp(option);
228 optionTmp.uri = dbPath;
229 sqlite3 *db = nullptr;
230 int errCode = SQLiteUtils::OpenDatabase(optionTmp, db);
231 if (errCode != E_OK) {
232 return errCode;
233 }
234 errCode = SQLiteUtils::GetVersion(db, version);
235 (void)sqlite3_close_v2(db);
236 db = nullptr;
237 return errCode;
238 }
239
SetMetaUpgrade(const SecurityOption & currentOpt,const SecurityOption & expectOpt,const std::string & subDir)240 void SQLiteSingleVerDatabaseUpgrader::SetMetaUpgrade(const SecurityOption ¤tOpt,
241 const SecurityOption &expectOpt, const std::string &subDir)
242 {
243 std::string secOptUpgradeFile = subDir + "/" + DBConstant::SET_SECOPT_POSTFIX;
244 // the same version should upgrade while user open db with s3sece.
245 if ((!OS::CheckPathExistence(secOptUpgradeFile)) && currentOpt.securityLabel == SecurityLabel::NOT_SET &&
246 ParamCheckUtils::IsS3SECEOpt(expectOpt)) {
247 isMetaUpgrade_ = true;
248 } else {
249 isMetaUpgrade_ = false;
250 }
251 }
252
SetSubdir(const std::string & subDir)253 void SQLiteSingleVerDatabaseUpgrader::SetSubdir(const std::string &subDir)
254 {
255 subDir_ = subDir;
256 }
257
SetPathSecOptWithCheck(const std::string & path,const SecurityOption & secOption,const std::string & dbStore,bool isWithChecked)258 int SQLiteSingleVerDatabaseUpgrader::SetPathSecOptWithCheck(const std::string &path, const SecurityOption &secOption,
259 const std::string &dbStore, bool isWithChecked)
260 {
261 SecurityOption dbOpt;
262 std::vector<std::string> dbFilePathVec {DBConstant::SQLITE_DB_EXTENSION};
263 std::string dbFilePath = path + "/" + dbStore + DBConstant::SQLITE_DB_EXTENSION;
264 if (OS::CheckPathExistence(dbFilePath) && isWithChecked) {
265 int errCode = RuntimeContext::GetInstance()->GetSecurityOption(dbFilePath, dbOpt);
266 if (errCode != E_OK) {
267 LOGE("[SetPathSecOptWithCheck] GetSecurityOption failed:%d", errCode);
268 if (errCode == -E_NOT_SUPPORT) {
269 dbOpt = SecurityOption();
270 } else {
271 return errCode;
272 }
273 }
274 }
275
276 for (const auto &item : dbFilePathVec) {
277 std::string dbItemFilePath = path + "/" + dbStore + item;
278 if (!OS::CheckPathExistence(dbItemFilePath)) {
279 continue;
280 }
281 if (OS::CheckPathExistence(dbItemFilePath) && dbOpt.securityLabel == NOT_SET) {
282 int errCode = RuntimeContext::GetInstance()->SetSecurityOption(dbItemFilePath, secOption);
283 if (errCode != E_OK) {
284 LOGE("[SetPathSecOptWithCheck] SetSecurityOption failed.");
285 return errCode;
286 }
287 } else if (dbOpt == secOption) {
288 LOGI("[SetPathSecOptWithCheck] already set secoption");
289 } else {
290 LOGE("[SetPathSecOptWithCheck] already set secoption,but different from early option.");
291 return -E_INVALID_ARGS;
292 }
293 }
294 return E_OK;
295 }
296
SetSecOption(const std::string & path,const SecurityOption & secOption,bool isWithChecked)297 int SQLiteSingleVerDatabaseUpgrader::SetSecOption(const std::string &path, const SecurityOption &secOption,
298 bool isWithChecked)
299 {
300 if (!ParamCheckUtils::CheckSecOption(secOption)) {
301 return -E_INVALID_ARGS;
302 }
303 if (secOption.securityLabel == NOT_SET) {
304 return E_OK;
305 }
306 std::string secOptUpgradeFile = path + "/" + DBConstant::SET_SECOPT_POSTFIX;
307 if (OS::CheckPathExistence(secOptUpgradeFile) && !ParamCheckUtils::IsS3SECEOpt(secOption)) {
308 LOGE("[SingleVerUp][SetSec] Security option is invalid");
309 return -E_INVALID_ARGS;
310 }
311 int errCode = E_OK;
312 if (secOption.securityLabel != NOT_SET) {
313 std::string mainDbPath = path + "/" + DBConstant::MAINDB_DIR;
314 std::string cacheDbPath = path + "/" + DBConstant::CACHEDB_DIR;
315 std::string metaDbPath = path + "/" + DBConstant::METADB_DIR;
316 errCode = SetPathSecOptWithCheck(mainDbPath, secOption, DBConstant::SINGLE_VER_DATA_STORE, isWithChecked);
317 if (errCode != E_OK) {
318 return errCode;
319 }
320 errCode = SetPathSecOptWithCheck(cacheDbPath, secOption, DBConstant::SINGLE_VER_CACHE_STORE, isWithChecked);
321 if (errCode != E_OK) {
322 LOGE("[SQLiteSingleVerDatabaseUpgrader] cacheDb SetSecurityOption failed.");
323 return errCode;
324 }
325 SecurityOption metaSecOpt;
326 metaSecOpt.securityLabel = ((secOption.securityLabel >= SecurityLabel::S2) ?
327 SecurityLabel::S2 : secOption.securityLabel);
328 errCode = SetPathSecOptWithCheck(metaDbPath, metaSecOpt, DBConstant::SINGLE_VER_META_STORE, false);
329 if (errCode != E_OK) {
330 LOGE("[SQLiteSingleVerDatabaseUpgrader] metaDb SetSecurityOption failed.");
331 return errCode;
332 }
333 }
334 if (OS::CheckPathExistence(secOptUpgradeFile) && (OS::RemoveFile(secOptUpgradeFile) != E_OK)) {
335 return -E_SYSTEM_API_FAIL;
336 }
337
338 return errCode;
339 }
340
MoveDatabaseToNewDir(const std::string & parentDir,const std::string & upgradeLockFile)341 int SQLiteSingleVerDatabaseUpgrader::MoveDatabaseToNewDir(const std::string &parentDir,
342 const std::string &upgradeLockFile)
343 {
344 std::vector<std::string> dbFilePathVec {DBConstant::SQLITE_DB_EXTENSION, ".db-wal", ".db-shm"};
345 for (const auto &item : dbFilePathVec) {
346 std::string oldDbPath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + item;
347 std::string currentDbPath = parentDir + "/" + DBConstant::MAINDB_DIR + "/" +
348 DBConstant::SINGLE_VER_DATA_STORE + item;
349 if (OS::CheckPathExistence(oldDbPath)) {
350 if (OS::RenameFilePath(oldDbPath, currentDbPath) != E_OK) {
351 LOGE("[SQLiteSinVerUp] Move database file to the new directory failed, errno:%d", errno);
352 return -E_SYSTEM_API_FAIL;
353 }
354 }
355 }
356 int errCode = OS::RemoveFile(upgradeLockFile);
357 if (errCode != E_OK) {
358 LOGE("[SQLiteSinVerUp] Remove upgrade flag file failed, errno:%d", errno);
359 }
360 return errCode;
361 }
362 } // namespace DistributedDB
363