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 "res_finalizer.h"
24 #include "runtime_context.h"
25 #include "sqlite_single_ver_storage_executor_sql.h"
26
27 namespace DistributedDB {
28 namespace {
29 const constexpr char *CREATE_LOCAL_TABLE_SQL =
30 "CREATE TABLE IF NOT EXISTS local_data(" \
31 "key BLOB PRIMARY KEY," \
32 "value BLOB," \
33 "timestamp INT," \
34 "hash_key BLOB);";
35
36 const constexpr char *CREATE_SYNC_TABLE_SQL =
37 "CREATE TABLE IF NOT EXISTS sync_data(" \
38 "key BLOB NOT NULL," \
39 "value BLOB," \
40 "timestamp INT NOT NULL," \
41 "flag INT NOT NULL," \
42 "device BLOB," \
43 "ori_device BLOB," \
44 "hash_key BLOB PRIMARY KEY NOT NULL," \
45 "w_timestamp INT," \
46 "modify_time INT DEFAULT 0," \
47 "create_time INT DEFAULT 0" \
48 ");";
49
50 const constexpr char *CREATE_META_TABLE_SQL =
51 "CREATE TABLE IF NOT EXISTS meta_data(" \
52 "key BLOB PRIMARY KEY NOT NULL," \
53 "value BLOB);";
54
55 const constexpr char *CREATE_SINGLE_META_TABLE_SQL =
56 "CREATE TABLE IF NOT EXISTS meta.meta_data(" \
57 "key BLOB PRIMARY KEY NOT NULL," \
58 "value BLOB);";
59
60 const constexpr char *CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX =
61 "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);";
62
63 const constexpr char *CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX =
64 "CREATE INDEX IF NOT EXISTS time_index ON sync_data (timestamp);";
65
66 const constexpr char *CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX =
67 "CREATE INDEX IF NOT EXISTS dev_index ON sync_data (device);";
68
69 const constexpr char *CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX =
70 "CREATE INDEX IF NOT EXISTS local_hashkey_index ON local_data (hash_key);";
71
72 const constexpr char *DROP_META_TABLE_SQL = "DROP TABLE IF EXISTS main.meta_data;";
73 const constexpr char *COPY_META_TABLE_SQL = "INSERT OR REPLACE INTO meta.meta_data SELECT * FROM meta_data "
74 "where (SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='main.meta_data') > 0;";
75 }
76
SQLiteSingleVerDatabaseUpgrader(sqlite3 * db,const SecurityOption & secopt,bool isMemDb)77 SQLiteSingleVerDatabaseUpgrader::SQLiteSingleVerDatabaseUpgrader(sqlite3 *db,
78 const SecurityOption &secopt, bool isMemDb)
79 : db_(db),
80 secOpt_(secopt),
81 isMemDB_(isMemDb),
82 isMetaUpgrade_(false)
83 {
84 }
85
~SQLiteSingleVerDatabaseUpgrader()86 SQLiteSingleVerDatabaseUpgrader::~SQLiteSingleVerDatabaseUpgrader()
87 {
88 db_ = nullptr;
89 }
90
TransferDatabasePath(const std::string & parentDir,const OpenDbProperties & option)91 int SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(const std::string &parentDir,
92 const OpenDbProperties &option)
93 {
94 std::string dbFilePath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION;
95 std::string upgradeLockFile = parentDir + "/" + DBConstant::UPGRADE_POSTFIX;
96
97 if (OS::CheckPathExistence(upgradeLockFile)) {
98 return MoveDatabaseToNewDir(parentDir, upgradeLockFile);
99 }
100 if (OS::CheckPathExistence(dbFilePath)) {
101 int currentVersion = 0;
102 int errCode = GetDbVersion(dbFilePath, option, currentVersion);
103 if (errCode != E_OK) {
104 LOGE("[SQLiteSinVerUp] Get version of old database failed");
105 return errCode;
106 }
107 if (currentVersion == 0) {
108 LOGI("The database file has not been initialized, maybe invalid database");
109 if (OS::RemoveFile(dbFilePath) != E_OK) {
110 LOGE("[SQLiteSinVerUp] Remove the uninitialized database failed, errno[%d]", errno);
111 return -E_SYSTEM_API_FAIL;
112 }
113 }
114 if (currentVersion >= SINGLE_VER_STORE_VERSION_V1 && currentVersion <= SINGLE_VER_STORE_VERSION_V2) {
115 LOGI("[SQLiteSinVerUp] Old version[%d] database exists.", currentVersion);
116 if (OS::CreateFileByFileName(upgradeLockFile) != E_OK) {
117 return -E_SYSTEM_API_FAIL;
118 }
119 return MoveDatabaseToNewDir(parentDir, upgradeLockFile);
120 }
121 }
122 return E_OK;
123 }
124
BeginUpgrade()125 int SQLiteSingleVerDatabaseUpgrader::BeginUpgrade()
126 {
127 return SQLiteUtils::BeginTransaction(db_, TransactType::IMMEDIATE);
128 }
129
EndUpgrade(bool isSuccess)130 int SQLiteSingleVerDatabaseUpgrader::EndUpgrade(bool isSuccess)
131 {
132 if (isSuccess) {
133 return SQLiteUtils::CommitTransaction(db_);
134 } else {
135 int errCode = SQLiteUtils::RollbackTransaction(db_);
136 std::string secOptUpgradeFile = subDir_ + "/" + DBConstant::SET_SECOPT_POSTFIX;
137 if (errCode == E_OK && OS::CheckPathExistence(secOptUpgradeFile) &&
138 (OS::RemoveFile(secOptUpgradeFile) != E_OK)) {
139 LOGW("[EndUpgrade] Delete secure upgrade file failed");
140 return -E_SYSTEM_API_FAIL;
141 }
142 return errCode;
143 }
144 }
145
GetDatabaseVersion(int & version) const146 int SQLiteSingleVerDatabaseUpgrader::GetDatabaseVersion(int &version) const
147 {
148 return SQLiteUtils::GetVersion(db_, version);
149 }
150
SetDatabaseVersion(int version)151 int SQLiteSingleVerDatabaseUpgrader::SetDatabaseVersion(int version)
152 {
153 return SQLiteUtils::SetUserVer(db_, version);
154 }
155
SetUpgradeSqls(int version,std::vector<std::string> & sqls,bool & isCreateUpgradeFile) const156 void SQLiteSingleVerDatabaseUpgrader::SetUpgradeSqls(int version, std::vector<std::string> &sqls,
157 bool &isCreateUpgradeFile) const
158 {
159 if (version == 0) { // no write version.
160 if ((!isMemDB_) && ParamCheckUtils::IsS3SECEOpt(secOpt_)) {
161 sqls = {
162 CREATE_LOCAL_TABLE_SQL,
163 CREATE_SINGLE_META_TABLE_SQL,
164 CREATE_SYNC_TABLE_SQL,
165 CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX,
166 CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX,
167 CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX,
168 CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX
169 };
170 } else {
171 sqls = {
172 CREATE_LOCAL_TABLE_SQL,
173 CREATE_META_TABLE_SQL,
174 CREATE_SYNC_TABLE_SQL,
175 CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX,
176 CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX,
177 CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX,
178 CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX
179 };
180 }
181 } else {
182 if (version <= SINGLE_VER_STORE_VERSION_V1) {
183 sqls = {
184 "DROP INDEX key_index;",
185 "CREATE INDEX IF NOT EXISTS key_index ON sync_data (key, flag);",
186 "ALTER TABLE sync_data ADD w_timestamp INT;",
187 "UPDATE sync_data SET w_timestamp=timestamp;",
188 "ALTER TABLE local_data ADD timestamp INT;",
189 "ALTER TABLE local_data ADD hash_key BLOB;",
190 "UPDATE local_data SET hash_key=calc_hash_key(key), timestamp=0;",
191 "CREATE INDEX IF NOT EXISTS local_hashkey_index ON local_data (hash_key);"
192 };
193 }
194 if ((version <= SINGLE_VER_STORE_VERSION_V2 && ParamCheckUtils::IsS3SECEOpt(secOpt_)) ||
195 (version >= SINGLE_VER_STORE_VERSION_V3 && isMetaUpgrade_ == true)) {
196 sqls.emplace_back(CREATE_SINGLE_META_TABLE_SQL);
197 sqls.emplace_back(COPY_META_TABLE_SQL);
198 sqls.emplace_back(DROP_META_TABLE_SQL);
199 isCreateUpgradeFile = true;
200 }
201 if (version < SINGLE_VER_STORE_VERSION_V4) {
202 sqls.emplace_back("ALTER TABLE sync_data ADD modify_time INT DEFAULT 0");
203 sqls.emplace_back("ALTER TABLE sync_data ADD create_time INT DEFAULT 0");
204 }
205 }
206 }
207
UpgradeFromDatabaseVersion(int version)208 int SQLiteSingleVerDatabaseUpgrader::UpgradeFromDatabaseVersion(int version)
209 {
210 std::vector<std::string> sqls;
211 bool isCreateUpgradeFile = false;
212 LOGI("[SqlSingleUp] metaSplit[%d], secLabel[%d], secFlag[%d], version[%d]",
213 isMetaUpgrade_, secOpt_.securityLabel, secOpt_.securityFlag, version);
214 SetUpgradeSqls(version, sqls, isCreateUpgradeFile);
215 for (const auto &item : sqls) {
216 int errCode = SQLiteUtils::ExecuteRawSQL(db_, item);
217 if (errCode != E_OK) {
218 LOGE("[SqlSingleUp][UpFrom] Execute upgrade sql failed:%d", errCode);
219 return errCode;
220 }
221 }
222 InitTimeForUpgrade(version);
223 if (isCreateUpgradeFile) {
224 std::string secOptUpgradeFile = subDir_ + "/" + DBConstant::SET_SECOPT_POSTFIX;
225 if (!OS::CheckPathExistence(secOptUpgradeFile) && (OS::CreateFileByFileName(secOptUpgradeFile) != E_OK)) {
226 LOGE("[SqlSingleUp][UpFrom] Create s3sece flag file failed");
227 return -E_SYSTEM_API_FAIL;
228 }
229 LOGD("[SqlSingleUp][UpFrom] Create s3sece mark file success");
230 }
231 return E_OK;
232 }
233
GetDbVersion(const std::string & dbPath,const OpenDbProperties & option,int & version)234 int SQLiteSingleVerDatabaseUpgrader::GetDbVersion(const std::string &dbPath, const OpenDbProperties &option,
235 int &version)
236 {
237 OpenDbProperties optionTmp(option);
238 optionTmp.uri = dbPath;
239 sqlite3 *db = nullptr;
240 int errCode = SQLiteUtils::OpenDatabase(optionTmp, db);
241 if (errCode != E_OK) {
242 return errCode;
243 }
244 errCode = SQLiteUtils::GetVersion(db, version);
245 (void)sqlite3_close_v2(db);
246 db = nullptr;
247 return errCode;
248 }
249
SetMetaUpgrade(const SecurityOption & currentOpt,const SecurityOption & expectOpt,const std::string & subDir)250 void SQLiteSingleVerDatabaseUpgrader::SetMetaUpgrade(const SecurityOption ¤tOpt,
251 const SecurityOption &expectOpt, const std::string &subDir)
252 {
253 std::string secOptUpgradeFile = subDir + "/" + DBConstant::SET_SECOPT_POSTFIX;
254 // the same version should upgrade while user open db with s3sece.
255 if ((!OS::CheckPathExistence(secOptUpgradeFile)) && currentOpt.securityLabel == SecurityLabel::NOT_SET &&
256 ParamCheckUtils::IsS3SECEOpt(expectOpt)) {
257 isMetaUpgrade_ = true;
258 } else {
259 isMetaUpgrade_ = false;
260 }
261 }
262
SetSubdir(const std::string & subDir)263 void SQLiteSingleVerDatabaseUpgrader::SetSubdir(const std::string &subDir)
264 {
265 subDir_ = subDir;
266 }
267
SetPathSecOptWithCheck(const std::string & path,const SecurityOption & secOption,const std::string & dbStore,bool isWithChecked)268 int SQLiteSingleVerDatabaseUpgrader::SetPathSecOptWithCheck(const std::string &path, const SecurityOption &secOption,
269 const std::string &dbStore, bool isWithChecked)
270 {
271 SecurityOption dbOpt;
272 std::vector<std::string> dbFilePathVec {DBConstant::DB_EXTENSION};
273 std::string dbFilePath = path + "/" + dbStore + DBConstant::DB_EXTENSION;
274 if (OS::CheckPathExistence(dbFilePath) && isWithChecked) {
275 int errCode = RuntimeContext::GetInstance()->GetSecurityOption(dbFilePath, dbOpt);
276 if (errCode != E_OK) {
277 LOGE("[SetPathSecOptWithCheck] GetSecurityOption failed:%d", errCode);
278 if (errCode == -E_NOT_SUPPORT) {
279 dbOpt = SecurityOption();
280 } else {
281 return errCode;
282 }
283 }
284 }
285
286 for (const auto &item : dbFilePathVec) {
287 std::string dbItemFilePath = path + "/" + dbStore + item;
288 if (!OS::CheckPathExistence(dbItemFilePath)) {
289 continue;
290 }
291 int errCode = RuntimeContext::GetInstance()->SetSecurityOption(dbItemFilePath, secOption);
292 if (errCode != E_OK) {
293 LOGE("[SetPathSecOptWithCheck] SetSecurityOption failed.");
294 return errCode;
295 }
296 }
297 return E_OK;
298 }
299
SetSecOption(const std::string & path,const SecurityOption & secOption,bool isWithChecked)300 int SQLiteSingleVerDatabaseUpgrader::SetSecOption(const std::string &path, const SecurityOption &secOption,
301 bool isWithChecked)
302 {
303 if (!ParamCheckUtils::CheckSecOption(secOption)) {
304 return -E_INVALID_ARGS;
305 }
306 if (secOption.securityLabel == NOT_SET) {
307 return E_OK;
308 }
309 std::string secOptUpgradeFile = path + "/" + DBConstant::SET_SECOPT_POSTFIX;
310 if (OS::CheckPathExistence(secOptUpgradeFile) && !ParamCheckUtils::IsS3SECEOpt(secOption)) {
311 LOGE("[SingleVerUp][SetSec] Security option is invalid");
312 return -E_INVALID_ARGS;
313 }
314 int errCode = E_OK;
315 if (secOption.securityLabel != NOT_SET) {
316 std::string mainDbPath = path + "/" + DBConstant::MAINDB_DIR;
317 std::string cacheDbPath = path + "/" + DBConstant::CACHEDB_DIR;
318 std::string metaDbPath = path + "/" + DBConstant::METADB_DIR;
319 errCode = SetPathSecOptWithCheck(mainDbPath, secOption, DBConstant::SINGLE_VER_DATA_STORE, isWithChecked);
320 if (errCode != E_OK) {
321 return errCode;
322 }
323 errCode = SetPathSecOptWithCheck(cacheDbPath, secOption, DBConstant::SINGLE_VER_CACHE_STORE, isWithChecked);
324 if (errCode != E_OK) {
325 LOGE("[SQLiteSingleVerDatabaseUpgrader] cacheDb SetSecurityOption failed.");
326 return errCode;
327 }
328 SecurityOption metaSecOpt;
329 metaSecOpt.securityLabel = ((secOption.securityLabel >= SecurityLabel::S2) ?
330 SecurityLabel::S2 : secOption.securityLabel);
331 errCode = SetPathSecOptWithCheck(metaDbPath, metaSecOpt, DBConstant::SINGLE_VER_META_STORE, false);
332 if (errCode != E_OK) {
333 LOGE("[SQLiteSingleVerDatabaseUpgrader] metaDb SetSecurityOption failed.");
334 return errCode;
335 }
336 }
337 if (OS::CheckPathExistence(secOptUpgradeFile) && (OS::RemoveFile(secOptUpgradeFile) != E_OK)) {
338 return -E_SYSTEM_API_FAIL;
339 }
340
341 return errCode;
342 }
343
MoveDatabaseToNewDir(const std::string & parentDir,const std::string & upgradeLockFile)344 int SQLiteSingleVerDatabaseUpgrader::MoveDatabaseToNewDir(const std::string &parentDir,
345 const std::string &upgradeLockFile)
346 {
347 std::vector<std::string> dbFilePathVec {DBConstant::DB_EXTENSION, ".db-wal", ".db-shm"};
348 for (const auto &item : dbFilePathVec) {
349 std::string oldDbPath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + item;
350 std::string currentDbPath = parentDir + "/" + DBConstant::MAINDB_DIR + "/" +
351 DBConstant::SINGLE_VER_DATA_STORE + item;
352 if (OS::CheckPathExistence(oldDbPath)) {
353 if (OS::RenameFilePath(oldDbPath, currentDbPath) != E_OK) {
354 LOGE("[SQLiteSinVerUp] Move database file to the new directory failed, errno:%d", errno);
355 return -E_SYSTEM_API_FAIL;
356 }
357 }
358 }
359 int errCode = OS::RemoveFile(upgradeLockFile);
360 if (errCode != E_OK) {
361 LOGE("[SQLiteSinVerUp] Remove upgrade flag file failed, errno:%d", errno);
362 }
363 return errCode;
364 }
365
IsValueNeedUpgrade() const366 bool SQLiteSingleVerDatabaseUpgrader::IsValueNeedUpgrade() const
367 {
368 return valueNeedUpgrade_;
369 }
370
InitTimeForUpgrade(int version)371 void SQLiteSingleVerDatabaseUpgrader::InitTimeForUpgrade(int version)
372 {
373 if (version >= SINGLE_VER_STORE_VERSION_V4) {
374 return;
375 }
376 auto [errCode, offset] = GetLocalTimeOffset();
377 if (errCode != E_OK) {
378 // init time failed should not block upgrade
379 return;
380 }
381 UpgradeTime(offset);
382 }
383
GetLocalTimeOffset()384 std::pair<int, TimeOffset> SQLiteSingleVerDatabaseUpgrader::GetLocalTimeOffset()
385 {
386 std::pair<int, TimeOffset> res;
387 auto &[errCode, offset] = res;
388 sqlite3_stmt *stmt = nullptr;
389 errCode = SQLiteUtils::GetStatement(db_, SELECT_META_VALUE_SQL, stmt);
390 if (errCode != E_OK) {
391 LOGW("[SQLiteSinVerUp] Prepare get meta data failed %d", errCode);
392 return res;
393 }
394 ResFinalizer finalizer([stmt]() {
395 int ret = E_OK;
396 sqlite3_stmt *sqlite3Stmt = stmt;
397 SQLiteUtils::ResetStatement(sqlite3Stmt, true, ret);
398 if (ret != E_OK) {
399 LOGW("[SQLiteSinVerUp] Finalize select stmt failed %d", ret);
400 }
401 });
402 const std::string_view localTimeOffset = DBConstant::LOCALTIME_OFFSET_KEY;
403 Key key(localTimeOffset.begin(), localTimeOffset.end());
404 errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key); // 1 is time offset
405 if (errCode != E_OK) {
406 LOGW("[SQLiteSinVerUp] Bind localTimeOffset failed %d", errCode);
407 return res;
408 }
409 errCode = SQLiteUtils::StepWithRetry(stmt, isMemDB_);
410 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
411 errCode = -E_NOT_FOUND;
412 } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
413 LOGW("[SQLiteSinVerUp] Get meta data failed %d", errCode);
414 return res;
415 }
416 Value value;
417 errCode = SQLiteUtils::GetColumnBlobValue(stmt, 0, value);
418 if (errCode != E_OK) {
419 LOGW("[SQLiteSinVerUp] Get blob local offset failed %d", errCode);
420 return res;
421 }
422 offset = std::strtoll(std::string(value.begin(), value.end()).c_str(), nullptr, DBConstant::STR_TO_LL_BY_DEVALUE);
423 return res;
424 }
425
UpgradeTime(TimeOffset offset)426 void SQLiteSingleVerDatabaseUpgrader::UpgradeTime(TimeOffset offset)
427 {
428 std::string addOffset;
429 if (offset < 0) {
430 addOffset = "+";
431 } else {
432 addOffset = "-";
433 }
434 addOffset += std::to_string(std::abs(offset));
435 std::string updateSQL = "UPDATE sync_data SET modify_time=timestamp" + addOffset + ", create_time=w_timestamp" +
436 addOffset + " WHERE modify_time = 0";
437 int errCode = SQLiteUtils::ExecuteRawSQL(db_, updateSQL);
438 if (errCode != E_OK) {
439 LOGE("[SQLiteSinVerUp] Upgrade time failed %d", errCode);
440 }
441 }
442 } // namespace DistributedDB
443