1 /*
2 * Copyright (c) 2022 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_relational_utils.h"
17 #include "db_errno.h"
18 #include "cloud/cloud_db_types.h"
19 #include "sqlite_utils.h"
20 #include "cloud/cloud_storage_utils.h"
21 #include "runtime_context.h"
22 #include "cloud/cloud_db_constant.h"
23
24 namespace DistributedDB {
GetDataValueByType(sqlite3_stmt * statement,int cid,DataValue & value)25 int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, DataValue &value)
26 {
27 if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
28 return -E_INVALID_ARGS;
29 }
30
31 int errCode = E_OK;
32 int storageType = sqlite3_column_type(statement, cid);
33 switch (storageType) {
34 case SQLITE_INTEGER: {
35 value = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
36 break;
37 }
38 case SQLITE_FLOAT: {
39 value = sqlite3_column_double(statement, cid);
40 break;
41 }
42 case SQLITE_BLOB: {
43 std::vector<uint8_t> blobValue;
44 errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
45 if (errCode != E_OK) {
46 return errCode;
47 }
48 auto blob = new (std::nothrow) Blob;
49 if (blob == nullptr) {
50 return -E_OUT_OF_MEMORY;
51 }
52 blob->WriteBlob(blobValue.data(), static_cast<uint32_t>(blobValue.size()));
53 errCode = value.Set(blob);
54 break;
55 }
56 case SQLITE_NULL: {
57 break;
58 }
59 case SQLITE3_TEXT: {
60 std::string str;
61 (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
62 value = str;
63 if (value.GetType() != StorageType::STORAGE_TYPE_TEXT) {
64 errCode = -E_OUT_OF_MEMORY;
65 }
66 break;
67 }
68 default: {
69 break;
70 }
71 }
72 return errCode;
73 }
74
GetSelectValues(sqlite3_stmt * stmt)75 std::vector<DataValue> SQLiteRelationalUtils::GetSelectValues(sqlite3_stmt *stmt)
76 {
77 std::vector<DataValue> values;
78 for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) {
79 DataValue value;
80 (void)GetDataValueByType(stmt, cid, value);
81 values.emplace_back(std::move(value));
82 }
83 return values;
84 }
85
GetCloudValueByType(sqlite3_stmt * statement,int type,int cid,Type & cloudValue)86 int SQLiteRelationalUtils::GetCloudValueByType(sqlite3_stmt *statement, int type, int cid, Type &cloudValue)
87 {
88 if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
89 return -E_INVALID_ARGS;
90 }
91 switch (sqlite3_column_type(statement, cid)) {
92 case SQLITE_INTEGER: {
93 if (type == TYPE_INDEX<bool>) {
94 cloudValue = static_cast<bool>(sqlite3_column_int(statement, cid));
95 break;
96 }
97 cloudValue = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
98 break;
99 }
100 case SQLITE_FLOAT: {
101 cloudValue = sqlite3_column_double(statement, cid);
102 break;
103 }
104 case SQLITE_BLOB: {
105 std::vector<uint8_t> blobValue;
106 int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
107 if (errCode != E_OK) {
108 return errCode;
109 }
110 cloudValue = blobValue;
111 break;
112 }
113 case SQLITE3_TEXT: {
114 bool isBlob = (type == TYPE_INDEX<Bytes> || type == TYPE_INDEX<Asset> || type == TYPE_INDEX<Assets>);
115 if (isBlob) {
116 std::vector<uint8_t> blobValue;
117 int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
118 if (errCode != E_OK) {
119 return errCode;
120 }
121 cloudValue = blobValue;
122 break;
123 }
124 std::string str;
125 (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
126 cloudValue = str;
127 break;
128 }
129 default: {
130 cloudValue = Nil();
131 break;
132 }
133 }
134 return E_OK;
135 }
136
CalCloudValueLen(Type & cloudValue,uint32_t & totalSize)137 void SQLiteRelationalUtils::CalCloudValueLen(Type &cloudValue, uint32_t &totalSize)
138 {
139 switch (cloudValue.index()) {
140 case TYPE_INDEX<int64_t>:
141 totalSize += sizeof(int64_t);
142 break;
143 case TYPE_INDEX<double>:
144 totalSize += sizeof(double);
145 break;
146 case TYPE_INDEX<std::string>:
147 totalSize += std::get<std::string>(cloudValue).size();
148 break;
149 case TYPE_INDEX<bool>:
150 totalSize += sizeof(int32_t);
151 break;
152 case TYPE_INDEX<Bytes>:
153 case TYPE_INDEX<Asset>:
154 case TYPE_INDEX<Assets>:
155 totalSize += std::get<Bytes>(cloudValue).size();
156 break;
157 default: {
158 break;
159 }
160 }
161 }
162
BindStatementByType(sqlite3_stmt * statement,int cid,Type & typeVal)163 int SQLiteRelationalUtils::BindStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal)
164 {
165 int errCode = E_OK;
166 switch (typeVal.index()) {
167 case TYPE_INDEX<int64_t>: {
168 int64_t value = 0;
169 (void)CloudStorageUtils::GetValueFromType(typeVal, value);
170 errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value);
171 break;
172 }
173 case TYPE_INDEX<bool>: {
174 bool value = false;
175 (void)CloudStorageUtils::GetValueFromType<bool>(typeVal, value);
176 errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value);
177 break;
178 }
179 case TYPE_INDEX<double>: {
180 double value = 0.0;
181 (void)CloudStorageUtils::GetValueFromType<double>(typeVal, value);
182 errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, value));
183 break;
184 }
185 case TYPE_INDEX<std::string>: {
186 std::string value;
187 (void)CloudStorageUtils::GetValueFromType<std::string>(typeVal, value);
188 errCode = SQLiteUtils::BindTextToStatement(statement, cid, value);
189 break;
190 }
191 default: {
192 errCode = BindExtendStatementByType(statement, cid, typeVal);
193 break;
194 }
195 }
196 return errCode;
197 }
198
BindExtendStatementByType(sqlite3_stmt * statement,int cid,Type & typeVal)199 int SQLiteRelationalUtils::BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal)
200 {
201 int errCode = E_OK;
202 switch (typeVal.index()) {
203 case TYPE_INDEX<Bytes>: {
204 Bytes value;
205 (void)CloudStorageUtils::GetValueFromType<Bytes>(typeVal, value);
206 errCode = SQLiteUtils::BindBlobToStatement(statement, cid, value);
207 break;
208 }
209 case TYPE_INDEX<Asset>: {
210 Asset value;
211 (void)CloudStorageUtils::GetValueFromType<Asset>(typeVal, value);
212 Bytes val;
213 errCode = RuntimeContext::GetInstance()->AssetToBlob(value, val);
214 if (errCode != E_OK) {
215 break;
216 }
217 errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val);
218 break;
219 }
220 case TYPE_INDEX<Assets>: {
221 Assets value;
222 (void)CloudStorageUtils::GetValueFromType<Assets>(typeVal, value);
223 Bytes val;
224 errCode = RuntimeContext::GetInstance()->AssetsToBlob(value, val);
225 if (errCode != E_OK) {
226 break;
227 }
228 errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val);
229 break;
230 }
231 default: {
232 errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid));
233 break;
234 }
235 }
236 return errCode;
237 }
238
StepNext(bool isMemDB,sqlite3_stmt * stmt)239 int SQLiteRelationalUtils::StepNext(bool isMemDB, sqlite3_stmt *stmt)
240 {
241 if (stmt == nullptr) {
242 return -E_INVALID_ARGS;
243 }
244 int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDB);
245 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
246 errCode = -E_FINISHED;
247 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
248 errCode = E_OK;
249 }
250 return errCode;
251 }
252
GetSelectVBucket(sqlite3_stmt * stmt,VBucket & bucket)253 int SQLiteRelationalUtils::GetSelectVBucket(sqlite3_stmt *stmt, VBucket &bucket)
254 {
255 if (stmt == nullptr) {
256 return -E_INVALID_ARGS;
257 }
258 for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) {
259 Type typeVal;
260 int errCode = GetTypeValByStatement(stmt, cid, typeVal);
261 if (errCode != E_OK) {
262 LOGE("get typeVal from stmt failed");
263 return errCode;
264 }
265 const char *colName = sqlite3_column_name(stmt, cid);
266 bucket.insert_or_assign(colName, std::move(typeVal));
267 }
268 return E_OK;
269 }
270
GetDbFileName(sqlite3 * db,std::string & fileName)271 bool SQLiteRelationalUtils::GetDbFileName(sqlite3 *db, std::string &fileName)
272 {
273 if (db == nullptr) {
274 return false;
275 }
276
277 auto dbFilePath = sqlite3_db_filename(db, nullptr);
278 if (dbFilePath == nullptr) {
279 return false;
280 }
281 fileName = std::string(dbFilePath);
282 return true;
283 }
284
GetTypeValByStatement(sqlite3_stmt * stmt,int cid,Type & typeVal)285 int SQLiteRelationalUtils::GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal)
286 {
287 if (stmt == nullptr || cid < 0 || cid >= sqlite3_column_count(stmt)) {
288 return -E_INVALID_ARGS;
289 }
290 int errCode = E_OK;
291 switch (sqlite3_column_type(stmt, cid)) {
292 case SQLITE_INTEGER: {
293 const char *declType = sqlite3_column_decltype(stmt, cid);
294 if (declType == nullptr) {
295 typeVal = static_cast<int64_t>(sqlite3_column_int64(stmt, cid));
296 break;
297 }
298 if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL.c_str()) == 0 ||
299 strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN.c_str()) == 0) {
300 typeVal = static_cast<bool>(sqlite3_column_int(stmt, cid));
301 break;
302 }
303 typeVal = static_cast<int64_t>(sqlite3_column_int64(stmt, cid));
304 break;
305 }
306 case SQLITE_FLOAT: {
307 typeVal = sqlite3_column_double(stmt, cid);
308 break;
309 }
310 case SQLITE_BLOB: {
311 errCode = GetBlobByStatement(stmt, cid, typeVal);
312 if (errCode != E_OK) {
313 break;
314 }
315 }
316 case SQLITE3_TEXT: {
317 errCode = GetBlobByStatement(stmt, cid, typeVal);
318 if (errCode != E_OK) {
319 break;
320 }
321 if (typeVal.index() != TYPE_INDEX<Nil>) {
322 break;
323 }
324 std::string str;
325 (void)SQLiteUtils::GetColumnTextValue(stmt, cid, str);
326 typeVal = str;
327 break;
328 }
329 default: {
330 typeVal = Nil();
331 break;
332 }
333 }
334 return errCode;
335 }
336
GetBlobByStatement(sqlite3_stmt * stmt,int cid,Type & typeVal)337 int SQLiteRelationalUtils::GetBlobByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal)
338 {
339 const char *declType = sqlite3_column_decltype(stmt, cid);
340 int errCode = E_OK;
341 if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSET) == 0) {
342 std::vector<uint8_t> blobValue;
343 errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
344 if (errCode != E_OK) {
345 return errCode;
346 }
347 Asset asset;
348 errCode = RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset);
349 if (errCode != E_OK) {
350 return errCode;
351 }
352 typeVal = asset;
353 } else if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSETS) == 0) {
354 std::vector<uint8_t> blobValue;
355 errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
356 if (errCode != E_OK) {
357 return errCode;
358 }
359 Assets assets;
360 errCode = RuntimeContext::GetInstance()->BlobToAssets(blobValue, assets);
361 if (errCode != E_OK) {
362 return errCode;
363 }
364 typeVal = assets;
365 } else if (sqlite3_column_type(stmt, cid) == SQLITE_BLOB) {
366 std::vector<uint8_t> blobValue;
367 errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
368 if (errCode != E_OK) {
369 return errCode;
370 }
371 typeVal = blobValue;
372 }
373 return E_OK;
374 }
375
SelectServerObserver(sqlite3 * db,const std::string & tableName,bool isChanged)376 int SQLiteRelationalUtils::SelectServerObserver(sqlite3 *db, const std::string &tableName, bool isChanged)
377 {
378 if (db == nullptr || tableName.empty()) {
379 return -E_INVALID_ARGS;
380 }
381 std::string sql;
382 if (isChanged) {
383 sql = "SELECT server_observer('" + tableName + "', 1);";
384 } else {
385 sql = "SELECT server_observer('" + tableName + "', 0);";
386 }
387 sqlite3_stmt *stmt = nullptr;
388 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
389 if (errCode != E_OK) {
390 LOGE("get select server observer stmt failed. %d", errCode);
391 return errCode;
392 }
393 errCode = SQLiteUtils::StepWithRetry(stmt, false);
394 int ret = E_OK;
395 SQLiteUtils::ResetStatement(stmt, true, ret);
396 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
397 LOGE("select server observer failed. %d", errCode);
398 return SQLiteUtils::MapSQLiteErrno(errCode);
399 }
400 return ret == E_OK ? E_OK : ret;
401 }
402
AddUpgradeSqlToList(const TableInfo & tableInfo,const std::vector<std::pair<std::string,std::string>> & fieldList,std::vector<std::string> & sqlList)403 void SQLiteRelationalUtils::AddUpgradeSqlToList(const TableInfo &tableInfo,
404 const std::vector<std::pair<std::string, std::string>> &fieldList, std::vector<std::string> &sqlList)
405 {
406 for (const auto &[colName, colType] : fieldList) {
407 auto it = tableInfo.GetFields().find(colName);
408 if (it != tableInfo.GetFields().end()) {
409 continue;
410 }
411 sqlList.push_back("alter table " + tableInfo.GetTableName() + " add " + colName +
412 " " + colType + ";");
413 }
414 }
415
AnalysisTrackerTable(sqlite3 * db,const TrackerTable & trackerTable,TableInfo & tableInfo)416 int SQLiteRelationalUtils::AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo)
417 {
418 int errCode = SQLiteUtils::AnalysisSchema(db, trackerTable.GetTableName(), tableInfo, true);
419 if (errCode != E_OK) {
420 LOGE("analysis table schema failed %d.", errCode);
421 return errCode;
422 }
423 tableInfo.SetTrackerTable(trackerTable);
424 errCode = tableInfo.CheckTrackerTable();
425 if (errCode != E_OK) {
426 LOGE("check tracker table schema failed %d.", errCode);
427 }
428 return errCode;
429 }
430 } // namespace DistributedDB