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