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 = SQLiteUtils::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::RegisterGetSysTime(db);
62 if (errCode != E_OK) {
63 LOGE("[engine] register get sys time failed!");
64 }
65 return E_OK;
66 }
67
CreateNewExecutor(bool isWrite,StorageExecutor * & handle)68 int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle)
69 {
70 sqlite3 *db = nullptr;
71 int errCode = SQLiteUtils::OpenDatabase(option_, db, false);
72 if (errCode != E_OK) {
73 return errCode;
74 }
75 do {
76 errCode = Upgrade(db); // create meta_data table.
77 if (errCode != E_OK) {
78 break;
79 }
80
81 errCode = RegisterFunction(db);
82 if (errCode != E_OK) {
83 break;
84 }
85
86 handle = NewSQLiteStorageExecutor(db, isWrite, false);
87 if (handle == nullptr) {
88 LOGE("[Relational] New SQLiteStorageExecutor[%d] for the pool failed.", isWrite);
89 errCode = -E_OUT_OF_MEMORY;
90 break;
91 }
92 return E_OK;
93 } while (false);
94
95 (void)sqlite3_close_v2(db);
96 db = nullptr;
97 return errCode;
98 }
99
ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor * & handle)100 int SQLiteSingleRelationalStorageEngine::ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&handle)
101 {
102 if (handle == nullptr) {
103 return E_OK;
104 }
105 StorageExecutor *databaseHandle = handle;
106 Recycle(databaseHandle);
107 handle = nullptr;
108 return E_OK;
109 }
110
SetSchema(const RelationalSchemaObject & schema)111 void SQLiteSingleRelationalStorageEngine::SetSchema(const RelationalSchemaObject &schema)
112 {
113 std::lock_guard lock(schemaMutex_);
114 schema_ = schema;
115 }
116
GetSchema() const117 RelationalSchemaObject SQLiteSingleRelationalStorageEngine::GetSchema() const
118 {
119 std::lock_guard lock(schemaMutex_);
120 return schema_;
121 }
122
123 namespace {
SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor * handle,const RelationalSchemaObject & schema)124 int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema)
125 {
126 const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY.begin(), DBConstant::RELATIONAL_SCHEMA_KEY.end());
127 Value schemaVal;
128 DBCommon::StringToVector(schema.ToSchemaString(), schemaVal);
129 int errCode = handle->PutKvData(schemaKey, schemaVal); // save schema to meta_data
130 if (errCode != E_OK) {
131 LOGE("Save schema to meta table failed. %d", errCode);
132 }
133 return errCode;
134 }
135 }
136
CreateDistributedTable(const std::string & tableName,const std::string & identity,bool & schemaChanged)137 int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName,
138 const std::string &identity, bool &schemaChanged)
139 {
140 std::lock_guard lock(schemaMutex_);
141 RelationalSchemaObject schema = schema_;
142 bool isUpgraded = false;
143 if (schema.GetTable(tableName).GetTableName() == tableName) {
144 LOGI("distributed table bas been created.");
145 isUpgraded = true;
146 int errCode = UpgradeDistributedTable(tableName, schemaChanged);
147 if (errCode != E_OK) {
148 LOGE("Upgrade distributed table failed. %d", errCode);
149 return errCode;
150 }
151 // Triggers may need to be rebuilt, no return directly
152 } else if (schema.GetTables().size() >= DBConstant::MAX_DISTRIBUTED_TABLE_COUNT) {
153 LOGE("The number of distributed tables is exceeds limit.");
154 return -E_MAX_LIMITS;
155 } else {
156 schemaChanged = true;
157 }
158
159 return CreateDistributedTable(tableName, isUpgraded, identity, schema);
160 }
161
CreateDistributedTable(const std::string & tableName,bool isUpgraded,const std::string & identity,RelationalSchemaObject & schema)162 int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, bool isUpgraded,
163 const std::string &identity, RelationalSchemaObject &schema)
164 {
165 LOGD("Create distributed table.");
166 int errCode = E_OK;
167 auto *handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
168 errCode));
169 if (handle == nullptr) {
170 return errCode;
171 }
172 ResFinalizer finalizer([&handle, this] { this->ReleaseExecutor(handle); });
173
174 errCode = handle->StartTransaction(TransactType::IMMEDIATE);
175 if (errCode != E_OK) {
176 return errCode;
177 }
178
179 auto mode = static_cast<DistributedTableMode>(properties_.GetIntProp(
180 RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
181 TableInfo table;
182 errCode = handle->CreateDistributedTable(tableName, mode, isUpgraded, identity, table);
183 if (errCode != E_OK) {
184 LOGE("create distributed table failed. %d", errCode);
185 (void)handle->Rollback();
186 return errCode;
187 }
188
189 schema.SetTableMode(mode);
190 schema.AddRelationalTable(table);
191 errCode = SaveSchemaToMetaTable(handle, schema);
192 if (errCode != E_OK) {
193 LOGE("Save schema to meta table for create distributed table failed. %d", errCode);
194 (void)handle->Rollback();
195 return errCode;
196 }
197
198 errCode = handle->Commit();
199 if (errCode == E_OK) {
200 schema_ = schema;
201 }
202 return errCode;
203 }
204
UpgradeDistributedTable(const std::string & tableName,bool & schemaChanged)205 int SQLiteSingleRelationalStorageEngine::UpgradeDistributedTable(const std::string &tableName, bool &schemaChanged)
206 {
207 LOGD("Upgrade distributed table.");
208 RelationalSchemaObject schema = schema_;
209 int errCode = E_OK;
210 auto *handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
211 errCode));
212 if (handle == nullptr) {
213 return errCode;
214 }
215
216 errCode = handle->StartTransaction(TransactType::IMMEDIATE);
217 if (errCode != E_OK) {
218 ReleaseExecutor(handle);
219 return errCode;
220 }
221
222 auto mode = static_cast<DistributedTableMode>(properties_.GetIntProp(
223 RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE));
224 errCode = handle->UpgradeDistributedTable(tableName, mode, schemaChanged, schema);
225 if (errCode != E_OK) {
226 LOGE("Upgrade distributed table failed. %d", errCode);
227 (void)handle->Rollback();
228 ReleaseExecutor(handle);
229 return errCode;
230 }
231
232 errCode = SaveSchemaToMetaTable(handle, schema);
233 if (errCode != E_OK) {
234 LOGE("Save schema to meta table for upgrade distributed table failed. %d", errCode);
235 (void)handle->Rollback();
236 ReleaseExecutor(handle);
237 return errCode;
238 }
239
240 errCode = handle->Commit();
241 if (errCode == E_OK) {
242 schema_ = schema;
243 }
244 ReleaseExecutor(handle);
245 return errCode;
246 }
247
CleanDistributedDeviceTable(std::vector<std::string> & missingTables)248 int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector<std::string> &missingTables)
249 {
250 int errCode = E_OK;
251 auto handle = static_cast<SQLiteSingleVerRelationalStorageExecutor *>(FindExecutor(true, OperatePerm::NORMAL_PERM,
252 errCode));
253 if (handle == nullptr) {
254 return errCode;
255 }
256
257 std::lock_guard lock(schemaMutex_);
258 errCode = handle->StartTransaction(TransactType::IMMEDIATE);
259 if (errCode != E_OK) {
260 ReleaseExecutor(handle);
261 return errCode;
262 }
263
264 errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables);
265 if (errCode == E_OK) {
266 errCode = handle->Commit();
267 if (errCode == E_OK) {
268 // Remove non-existent tables from the schema
269 for (const auto &tableName : missingTables) {
270 schema_.RemoveRelationalTable(tableName);
271 }
272 SaveSchemaToMetaTable(handle, schema_); // save schema to meta_data
273 }
274 } else {
275 LOGE("Check distributed table failed. %d", errCode);
276 (void)handle->Rollback();
277 }
278
279 ReleaseExecutor(handle);
280 return errCode;
281 }
282
GetProperties() const283 const RelationalDBProperties &SQLiteSingleRelationalStorageEngine::GetProperties() const
284 {
285 return properties_;
286 }
287
SetProperties(const RelationalDBProperties & properties)288 void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties)
289 {
290 properties_ = properties;
291 }
292 }
293 #endif