• 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 #ifdef RELATIONAL_STORE
16 #include "sqlite_single_relational_storage_engine.h"
17 
18 #include "db_common.h"
19 #include "db_errno.h"
20 #include "res_finalizer.h"
21 #include "sqlite_relational_database_upgrader.h"
22 #include "sqlite_single_ver_relational_storage_executor.h"
23 
24 
25 namespace DistributedDB {
SQLiteSingleRelationalStorageEngine(RelationalDBProperties properties)26 SQLiteSingleRelationalStorageEngine::SQLiteSingleRelationalStorageEngine(RelationalDBProperties properties)
27     : properties_(properties)
28 {}
29 
~SQLiteSingleRelationalStorageEngine()30 SQLiteSingleRelationalStorageEngine::~SQLiteSingleRelationalStorageEngine()
31 {}
32 
NewSQLiteStorageExecutor(sqlite3 * dbHandle,bool isWrite,bool isMemDb)33 StorageExecutor *SQLiteSingleRelationalStorageEngine::NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite,
34     bool isMemDb)
35 {
36     auto mode = static_cast<DistributedTableMode>(properties_.GetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE,
37         DistributedTableMode::SPLIT_BY_DEVICE));
38     return new (std::nothrow) SQLiteSingleVerRelationalStorageExecutor(dbHandle, isWrite, mode);
39 }
40 
Upgrade(sqlite3 * db)41 int SQLiteSingleRelationalStorageEngine::Upgrade(sqlite3 *db)
42 {
43     int errCode = CreateRelationalMetaTable(db);
44     if (errCode != E_OK) {
45         LOGE("Create relational store meta table failed. err=%d", errCode);
46         return errCode;
47     }
48     LOGD("[RelationalEngine][Upgrade] upgrade relational store.");
49     auto upgrader = std::make_unique<SqliteRelationalDatabaseUpgrader>(db);
50     return upgrader->Upgrade();
51 }
52 
RegisterFunction(sqlite3 * db) const53 int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const
54 {
55     int errCode = SQLiteUtils::RegisterCalcHash(db);
56     if (errCode != E_OK) {
57         LOGE("[engine] register calculate hash failed!");
58         return errCode;
59     }
60 
61     errCode = SQLiteUtils::RegisterGetLastTime(db);
62     if (errCode != E_OK) {
63         LOGE("[engine] register get last time failed!");
64         return errCode;
65     }
66 
67     errCode = SQLiteUtils::RegisterGetSysTime(db);
68     if (errCode != E_OK) {
69         LOGE("[engine] register get sys time failed!");
70         return errCode;
71     }
72 
73     errCode = SQLiteUtils::RegisterGetRawSysTime(db);
74     if (errCode != E_OK) {
75         LOGE("[engine] register get raw sys time failed!");
76     }
77 
78     return errCode;
79 }
80 
CreateNewExecutor(bool isWrite,StorageExecutor * & handle)81 int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle)
82 {
83     sqlite3 *db = nullptr;
84     int errCode = SQLiteUtils::OpenDatabase(option_, db, false);
85     if (errCode != E_OK) {
86         return errCode;
87     }
88     do {
89         errCode = Upgrade(db); // create meta_data table.
90         if (errCode != E_OK) {
91             break;
92         }
93 
94         errCode = RegisterFunction(db);
95         if (errCode != E_OK) {
96             break;
97         }
98 
99         handle = NewSQLiteStorageExecutor(db, isWrite, false);
100         if (handle == nullptr) {
101             LOGE("[Relational] New SQLiteStorageExecutor[%d] for the pool failed.", isWrite);
102             errCode = -E_OUT_OF_MEMORY;
103             break;
104         }
105         return E_OK;
106     } while (false);
107 
108     (void)sqlite3_close_v2(db);
109     db = nullptr;
110     return errCode;
111 }
112 
ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor * & handle)113 int SQLiteSingleRelationalStorageEngine::ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&handle)
114 {
115     if (handle == nullptr) {
116         return E_OK;
117     }
118     StorageExecutor *databaseHandle = handle;
119     Recycle(databaseHandle);
120     handle = nullptr;
121     return E_OK;
122 }
123 
SetSchema(const RelationalSchemaObject & schema)124 void SQLiteSingleRelationalStorageEngine::SetSchema(const RelationalSchemaObject &schema)
125 {
126     std::lock_guard lock(schemaMutex_);
127     schema_ = schema;
128 }
129 
GetSchema() const130 RelationalSchemaObject SQLiteSingleRelationalStorageEngine::GetSchema() const
131 {
132     std::lock_guard lock(schemaMutex_);
133     return schema_;
134 }
135 
136 namespace {
137 const std::string DEVICE_TYPE = "device";
138 const std::string CLOUD_TYPE = "cloud";
139 const std::string SYNC_TABLE_TYPE = "sync_table_type_";
140 
SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor * handle,const RelationalSchemaObject & schema)141 int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema)
142 {
143     const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY.begin(), DBConstant::RELATIONAL_SCHEMA_KEY.end());
144     Value schemaVal;
145     DBCommon::StringToVector(schema.ToSchemaString(), schemaVal);
146     int errCode = handle->PutKvData(schemaKey, schemaVal); // save schema to meta_data
147     if (errCode != E_OK) {
148         LOGE("Save schema to meta table failed. %d", errCode);
149     }
150     return errCode;
151 }
152 
SaveSyncTableTypeToMeta(SQLiteSingleVerRelationalStorageExecutor * handle,const std::string & tableName,TableSyncType syncType)153 int SaveSyncTableTypeToMeta(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName,
154     TableSyncType syncType)
155 {
156     Key key;
157     DBCommon::StringToVector(SYNC_TABLE_TYPE + tableName, key);
158     Value value;
159     DBCommon::StringToVector(syncType == DEVICE_COOPERATION ? DEVICE_TYPE : CLOUD_TYPE, value);
160     int errCode = handle->PutKvData(key, value);
161     if (errCode != E_OK) {
162         LOGE("Save sync table type to meta table failed. %d", errCode);
163     }
164     return errCode;
165 }
166 }
167 
CreateDistributedTable(const std::string & tableName,const std::string & identity,bool & schemaChanged,TableSyncType syncType)168 int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName,
169     const std::string &identity, bool &schemaChanged, TableSyncType syncType)
170 {
171     std::lock_guard lock(schemaMutex_);
172     RelationalSchemaObject schema = schema_;
173     bool isUpgraded = false;
174     if (schema.GetTable(tableName).GetTableName() == tableName) {
175         LOGI("distributed table bas been created.");
176         if (schema.GetTable(tableName).GetTableSyncType() != syncType) {
177             LOGE("table sync type mismatch.");
178             return -E_TYPE_MISMATCH;
179         }
180         isUpgraded = true;
181         int errCode = UpgradeDistributedTable(tableName, schemaChanged, syncType);
182         if (errCode != E_OK) {
183             LOGE("Upgrade distributed table failed. %d", errCode);
184             return errCode;
185         }
186         // Triggers may need to be rebuilt, no return directly
187     } else if (schema.GetTables().size() >= DBConstant::MAX_DISTRIBUTED_TABLE_COUNT) {
188         LOGE("The number of distributed tables is exceeds limit.");
189         return -E_MAX_LIMITS;
190     } else {
191         schemaChanged = true;
192     }
193 
194     return CreateDistributedTable(tableName, isUpgraded, identity, schema, syncType);
195 }
196 
CreateDistributedTable(const std::string & tableName,bool isUpgraded,const std::string & identity,RelationalSchemaObject & schema,TableSyncType tableSyncType)197 int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, bool isUpgraded,
198     const std::string &identity, RelationalSchemaObject &schema, TableSyncType tableSyncType)
199 {
200     LOGD("Create distributed table.");
201     int errCode = E_OK;
202     auto *handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
203         errCode));
204     if (handle == nullptr) {
205         return errCode;
206     }
207     ResFinalizer finalizer([&handle, this] { this->ReleaseExecutor(handle); });
208 
209     errCode = handle->StartTransaction(TransactType::IMMEDIATE);
210     if (errCode != E_OK) {
211         return errCode;
212     }
213 
214     auto mode = static_cast<DistributedTableMode>(properties_.GetIntProp(
215         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
216     TableInfo table;
217     table.SetTableName(tableName);
218     table.SetTableSyncType(tableSyncType);
219     errCode = handle->CreateDistributedTable(mode, isUpgraded, identity, table, tableSyncType);
220     if (errCode != E_OK) {
221         LOGE("create distributed table failed. %d", errCode);
222         (void)handle->Rollback();
223         return errCode;
224     }
225 
226     schema.SetTableMode(mode);
227     schema.AddRelationalTable(table);
228     errCode = SaveSchemaToMetaTable(handle, schema);
229     if (errCode != E_OK) {
230         LOGE("Save schema to meta table for create distributed table failed. %d", errCode);
231         (void)handle->Rollback();
232         return errCode;
233     }
234 
235     errCode = SaveSyncTableTypeToMeta(handle, tableName, tableSyncType);
236     if (errCode != E_OK) {
237         (void)handle->Rollback();
238         return errCode;
239     }
240 
241     errCode = handle->Commit();
242     if (errCode == E_OK) {
243         schema_ = schema;
244     }
245     return errCode;
246 }
247 
UpgradeDistributedTable(const std::string & tableName,bool & schemaChanged,TableSyncType syncType)248 int SQLiteSingleRelationalStorageEngine::UpgradeDistributedTable(const std::string &tableName, bool &schemaChanged,
249     TableSyncType syncType)
250 {
251     LOGD("Upgrade distributed table.");
252     RelationalSchemaObject schema = schema_;
253     int errCode = E_OK;
254     auto *handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
255         errCode));
256     if (handle == nullptr) {
257         return errCode;
258     }
259 
260     errCode = handle->StartTransaction(TransactType::IMMEDIATE);
261     if (errCode != E_OK) {
262         ReleaseExecutor(handle);
263         return errCode;
264     }
265 
266     auto mode = static_cast<DistributedTableMode>(properties_.GetIntProp(
267         RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
268     errCode = handle->UpgradeDistributedTable(tableName, mode, schemaChanged, schema, syncType);
269     if (errCode != E_OK) {
270         LOGE("Upgrade distributed table failed. %d", errCode);
271         (void)handle->Rollback();
272         ReleaseExecutor(handle);
273         return errCode;
274     }
275 
276     errCode = SaveSchemaToMetaTable(handle, schema);
277         if (errCode != E_OK) {
278         LOGE("Save schema to meta table for upgrade distributed table failed. %d", errCode);
279         (void)handle->Rollback();
280         ReleaseExecutor(handle);
281         return errCode;
282     }
283 
284     errCode = handle->Commit();
285     if (errCode == E_OK) {
286         schema_ = schema;
287     }
288     ReleaseExecutor(handle);
289     return errCode;
290 }
291 
CleanDistributedDeviceTable(std::vector<std::string> & missingTables)292 int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector<std::string> &missingTables)
293 {
294     int errCode = E_OK;
295     auto handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
296         errCode));
297     if (handle == nullptr) {
298         return errCode;
299     }
300 
301     std::lock_guard lock(schemaMutex_);
302     errCode = handle->StartTransaction(TransactType::IMMEDIATE);
303     if (errCode != E_OK) {
304         ReleaseExecutor(handle);
305         return errCode;
306     }
307 
308     errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables);
309     if (errCode == E_OK) {
310         errCode = handle->Commit();
311         if (errCode == E_OK) {
312             // Remove non-existent tables from the schema
313             for (const auto &tableName : missingTables) {
314                 schema_.RemoveRelationalTable(tableName);
315             }
316             SaveSchemaToMetaTable(handle, schema_); // save schema to meta_data
317         }
318     } else {
319         LOGE("Check distributed table failed. %d", errCode);
320         (void)handle->Rollback();
321     }
322 
323     ReleaseExecutor(handle);
324     return errCode;
325 }
326 
GetProperties() const327 const RelationalDBProperties &SQLiteSingleRelationalStorageEngine::GetProperties() const
328 {
329     return properties_;
330 }
331 
SetProperties(const RelationalDBProperties & properties)332 void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties)
333 {
334     properties_ = properties;
335 }
336 
CreateRelationalMetaTable(sqlite3 * db)337 int SQLiteSingleRelationalStorageEngine::CreateRelationalMetaTable(sqlite3 *db)
338 {
339     std::string sql =
340         "CREATE TABLE IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + "metadata(" \
341         "key    BLOB PRIMARY KEY NOT NULL," \
342         "value  BLOB);";
343     int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
344     if (errCode != E_OK) {
345         LOGE("[SQLite] execute create table sql failed, err=%d", errCode);
346     }
347     return errCode;
348 }
349 }
350 #endif