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