• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &currentOpt,
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