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
21 namespace DistributedDB {
GetDataValueByType(sqlite3_stmt * statement,int cid,DataValue & value)22 int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, DataValue &value)
23 {
24 if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
25 return -E_INVALID_ARGS;
26 }
27
28 int errCode = E_OK;
29 int storageType = sqlite3_column_type(statement, cid);
30 switch (storageType) {
31 case SQLITE_INTEGER: {
32 value = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
33 break;
34 }
35 case SQLITE_FLOAT: {
36 value = sqlite3_column_double(statement, cid);
37 break;
38 }
39 case SQLITE_BLOB: {
40 std::vector<uint8_t> blobValue;
41 errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
42 if (errCode != E_OK) {
43 return errCode;
44 }
45 auto blob = new (std::nothrow) Blob;
46 if (blob == nullptr) {
47 return -E_OUT_OF_MEMORY;
48 }
49 blob->WriteBlob(blobValue.data(), static_cast<uint32_t>(blobValue.size()));
50 errCode = value.Set(blob);
51 break;
52 }
53 case SQLITE_NULL: {
54 break;
55 }
56 case SQLITE3_TEXT: {
57 std::string str;
58 (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
59 value = str;
60 if (value.GetType() != StorageType::STORAGE_TYPE_TEXT) {
61 errCode = -E_OUT_OF_MEMORY;
62 }
63 break;
64 }
65 default: {
66 break;
67 }
68 }
69 return errCode;
70 }
71
GetSelectValues(sqlite3_stmt * stmt)72 std::vector<DataValue> SQLiteRelationalUtils::GetSelectValues(sqlite3_stmt *stmt)
73 {
74 std::vector<DataValue> values;
75 for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) {
76 DataValue value;
77 (void)GetDataValueByType(stmt, cid, value);
78 values.emplace_back(std::move(value));
79 }
80 return values;
81 }
82
GetCloudValueByType(sqlite3_stmt * statement,int type,int cid,Type & cloudValue)83 int SQLiteRelationalUtils::GetCloudValueByType(sqlite3_stmt *statement, int type, int cid, Type &cloudValue)
84 {
85 if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
86 return -E_INVALID_ARGS;
87 }
88 switch (sqlite3_column_type(statement, cid)) {
89 case SQLITE_INTEGER: {
90 if (type == TYPE_INDEX<bool>) {
91 cloudValue = static_cast<bool>(sqlite3_column_int(statement, cid));
92 break;
93 }
94 cloudValue = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
95 break;
96 }
97 case SQLITE_FLOAT: {
98 cloudValue = sqlite3_column_double(statement, cid);
99 break;
100 }
101 case SQLITE_BLOB: {
102 std::vector<uint8_t> blobValue;
103 int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
104 if (errCode != E_OK) {
105 return errCode;
106 }
107 cloudValue = blobValue;
108 break;
109 }
110 case SQLITE3_TEXT: {
111 bool isBlob = (type == TYPE_INDEX<Bytes> || type == TYPE_INDEX<Asset> || type == TYPE_INDEX<Assets>);
112 if (isBlob) {
113 std::vector<uint8_t> blobValue;
114 int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
115 if (errCode != E_OK) {
116 return errCode;
117 }
118 cloudValue = blobValue;
119 break;
120 }
121 std::string str;
122 (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
123 cloudValue = str;
124 break;
125 }
126 default: {
127 cloudValue = Nil();
128 }
129 }
130 return E_OK;
131 }
132
CalCloudValueLen(Type & cloudValue,uint32_t & totalSize)133 void SQLiteRelationalUtils::CalCloudValueLen(Type &cloudValue, uint32_t &totalSize)
134 {
135 switch (cloudValue.index()) {
136 case TYPE_INDEX<int64_t>:
137 totalSize += sizeof(int64_t);
138 break;
139 case TYPE_INDEX<double>:
140 totalSize += sizeof(double);
141 break;
142 case TYPE_INDEX<std::string>:
143 totalSize += std::get<std::string>(cloudValue).size();
144 break;
145 case TYPE_INDEX<bool>:
146 totalSize += sizeof(int32_t);
147 break;
148 case TYPE_INDEX<Bytes>:
149 case TYPE_INDEX<Asset>:
150 case TYPE_INDEX<Assets>:
151 totalSize += std::get<Bytes>(cloudValue).size();
152 break;
153 default: {
154 break;
155 }
156 }
157 }
158 } // namespace DistributedDB