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
16 #include "sqlite_statement.h"
17
18 #include <sstream>
19 #include <iomanip>
20
21 #include "logger.h"
22 #include "rdb_errno.h"
23 #include "sqlite_errno.h"
24
25 namespace OHOS {
26 namespace NativeRdb {
27 // Setting Data Precision
28 const int SET_DATA_PRECISION = 15;
SqliteStatement()29 SqliteStatement::SqliteStatement() : sql(""), stmtHandle(nullptr), readOnly(false), columnCount(0), numParameters(0)
30 {
31 }
~SqliteStatement()32 SqliteStatement::~SqliteStatement()
33 {
34 Finalize();
35 }
36
Prepare(sqlite3 * dbHandle,const std::string & newSql)37 int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql)
38 {
39 if (sql.compare(newSql) == 0) {
40 return E_OK;
41 }
42 // prepare the new sqlite3_stmt
43 sqlite3_stmt *stmt = nullptr;
44 int errCode = sqlite3_prepare_v2(dbHandle, newSql.c_str(), newSql.length(), &stmt, nullptr);
45 if (errCode != SQLITE_OK) {
46 LOG_ERROR("SqliteStatement::Prepare failed err = %{public}d", errCode);
47 if (stmt != nullptr) {
48 sqlite3_finalize(stmt);
49 }
50 return SQLiteError::ErrNo(errCode);
51 }
52 Finalize(); // finalize the old
53 sql = newSql;
54 stmtHandle = stmt;
55 readOnly = (sqlite3_stmt_readonly(stmtHandle) != 0) ? true : false;
56 columnCount = sqlite3_column_count(stmtHandle);
57 numParameters = sqlite3_bind_parameter_count(stmtHandle);
58 return E_OK;
59 }
60
Finalize()61 int SqliteStatement::Finalize()
62 {
63 if (stmtHandle == nullptr) {
64 return E_OK;
65 }
66
67 int errCode = sqlite3_finalize(stmtHandle);
68 stmtHandle = nullptr;
69 sql = "";
70 readOnly = false;
71 columnCount = 0;
72 numParameters = 0;
73 if (errCode != SQLITE_OK) {
74 LOG_ERROR("SqliteStatement::Finalize failed err = %{public}d", errCode);
75 return SQLiteError::ErrNo(errCode);
76 }
77 return E_OK;
78 }
79
BindArguments(const std::vector<ValueObject> & bindArgs) const80 int SqliteStatement::BindArguments(const std::vector<ValueObject> &bindArgs) const
81 {
82 int count = static_cast<int>(bindArgs.size());
83 std::vector<ValueObject> abindArgs;
84
85 if (count == 0) {
86 return E_OK;
87 }
88 // Obtains the bound parameter set.
89 if ((numParameters != 0) && (count <= numParameters)) {
90 for (const auto& i : bindArgs) {
91 abindArgs.push_back(i);
92 }
93
94 for (int i = count; i < numParameters; i++) {
95 ValueObject val;
96 abindArgs.push_back(val);
97 }
98 }
99
100 if (count > numParameters) {
101 return E_INVALID_BIND_ARGS_COUNT;
102 }
103
104 return InnerBindArguments(abindArgs);
105 }
106
InnerBindArguments(const std::vector<ValueObject> & bindArgs) const107 int SqliteStatement::InnerBindArguments(const std::vector<ValueObject> &bindArgs) const
108 {
109 int index = 1;
110 int errCode;
111 for (auto arg : bindArgs) {
112 switch (arg.GetType()) {
113 case ValueObjectType::TYPE_NULL: {
114 errCode = sqlite3_bind_null(stmtHandle, index);
115 break;
116 }
117 case ValueObjectType::TYPE_INT: {
118 int64_t value = 0;
119 arg.GetLong(value);
120 errCode = sqlite3_bind_int64(stmtHandle, index, value);
121 break;
122 }
123 case ValueObjectType::TYPE_DOUBLE: {
124 double doubleVal = 0;
125 arg.GetDouble(doubleVal);
126 errCode = sqlite3_bind_double(stmtHandle, index, doubleVal);
127 break;
128 }
129 case ValueObjectType::TYPE_BLOB: {
130 std::vector<uint8_t> blob;
131 arg.GetBlob(blob);
132 errCode = sqlite3_bind_blob(stmtHandle, index, static_cast<const void *>(blob.data()), blob.size(),
133 SQLITE_TRANSIENT);
134 break;
135 }
136 case ValueObjectType::TYPE_BOOL: {
137 bool boolVal = false;
138 arg.GetBool(boolVal);
139 errCode = sqlite3_bind_int64(stmtHandle, index, boolVal ? 1 : 0);
140 break;
141 }
142 default: {
143 std::string str;
144 arg.GetString(str);
145 errCode = sqlite3_bind_text(stmtHandle, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
146 break;
147 }
148 }
149
150 if (errCode != SQLITE_OK) {
151 return SQLiteError::ErrNo(errCode);
152 }
153
154 index++;
155 }
156
157 return E_OK;
158 }
159
ResetStatementAndClearBindings() const160 int SqliteStatement::ResetStatementAndClearBindings() const
161 {
162 if (stmtHandle == nullptr) {
163 return E_OK;
164 }
165
166 int errCode = sqlite3_reset(stmtHandle);
167 if (errCode != SQLITE_OK) {
168 LOG_ERROR("Reset statement failed. %{public}d", errCode);
169 return SQLiteError::ErrNo(errCode);
170 }
171
172 errCode = sqlite3_clear_bindings(stmtHandle);
173 if (errCode != SQLITE_OK) {
174 LOG_ERROR("Reset clear bindings failed. %{public}d", errCode);
175 return SQLiteError::ErrNo(errCode);
176 }
177
178 return E_OK;
179 }
180
Step() const181 int SqliteStatement::Step() const
182 {
183 int errCode = sqlite3_step(stmtHandle);
184 return errCode;
185 }
186
GetColumnCount(int & count) const187 int SqliteStatement::GetColumnCount(int &count) const
188 {
189 if (stmtHandle == nullptr) {
190 return E_INVALID_STATEMENT;
191 }
192 count = columnCount;
193 return E_OK;
194 }
195
196 /**
197 * Obtains the number that the statement has.
198 */
GetNumParameters(int & numParams) const199 int SqliteStatement::GetNumParameters(int &numParams) const
200 {
201 if (stmtHandle == nullptr) {
202 return E_INVALID_STATEMENT;
203 }
204 numParams = numParameters;
205 return E_OK;
206 }
207
GetColumnName(int index,std::string & columnName) const208 int SqliteStatement::GetColumnName(int index, std::string &columnName) const
209 {
210 if (stmtHandle == nullptr) {
211 return E_INVALID_STATEMENT;
212 }
213
214 if (index >= columnCount) {
215 return E_INVALID_COLUMN_INDEX;
216 }
217
218 const char *name = sqlite3_column_name(stmtHandle, index);
219 if (name == nullptr) {
220 return E_ERROR;
221 }
222 columnName = std::string(name);
223 return E_OK;
224 }
225
GetColumnType(int index,int & columnType) const226 int SqliteStatement::GetColumnType(int index, int &columnType) const
227 {
228 if (stmtHandle == nullptr) {
229 return E_INVALID_STATEMENT;
230 }
231
232 if (index >= columnCount) {
233 return E_INVALID_COLUMN_INDEX;
234 }
235
236 int type = sqlite3_column_type(stmtHandle, index);
237 switch (type) {
238 case SQLITE_INTEGER:
239 case SQLITE_FLOAT:
240 case SQLITE_BLOB:
241 case SQLITE_NULL:
242 case SQLITE_TEXT:
243 columnType = type;
244 return E_OK;
245 default:
246 return E_ERROR;
247 }
248 }
249
GetColumnBlob(int index,std::vector<uint8_t> & value) const250 int SqliteStatement::GetColumnBlob(int index, std::vector<uint8_t> &value) const
251 {
252 if (stmtHandle == nullptr) {
253 return E_INVALID_STATEMENT;
254 }
255
256 if (index >= columnCount) {
257 return E_INVALID_COLUMN_INDEX;
258 }
259
260 int type = sqlite3_column_type(stmtHandle, index);
261 if (type != SQLITE_BLOB && type != SQLITE_TEXT && type != SQLITE_NULL) {
262 return E_INVALID_COLUMN_TYPE;
263 }
264
265 int size = sqlite3_column_bytes(stmtHandle, index);
266 auto blob = static_cast<const uint8_t *>(sqlite3_column_blob(stmtHandle, index));
267 if (size == 0 || blob == nullptr) {
268 value.resize(0);
269 } else {
270 value.resize(size);
271 value.assign(blob, blob + size);
272 }
273
274 return E_OK;
275 }
276
GetColumnString(int index,std::string & value) const277 int SqliteStatement::GetColumnString(int index, std::string &value) const
278 {
279 if (stmtHandle == nullptr) {
280 return E_INVALID_STATEMENT;
281 }
282
283 if (index >= columnCount) {
284 return E_INVALID_COLUMN_INDEX;
285 }
286
287 int type = sqlite3_column_type(stmtHandle, index);
288 if (type == SQLITE_TEXT) {
289 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
290 value = (val == nullptr) ? "" : val;
291 } else if (type == SQLITE_INTEGER) {
292 int64_t val = sqlite3_column_int64(stmtHandle, index);
293 value = std::to_string(val);
294 } else if (type == SQLITE_FLOAT) {
295 double val = sqlite3_column_double(stmtHandle, index);
296 std::ostringstream os;
297 if (os << std::setprecision(SET_DATA_PRECISION) << val)
298 value = os.str();
299 } else if (type == SQLITE_NULL) {
300 value = "";
301 return E_OK;
302 } else if (type == SQLITE_BLOB) {
303 return E_INVALID_COLUMN_TYPE;
304 } else {
305 return E_ERROR;
306 }
307
308 return E_OK;
309 }
310
GetColumnLong(int index,int64_t & value) const311 int SqliteStatement::GetColumnLong(int index, int64_t &value) const
312 {
313 if (stmtHandle == nullptr) {
314 return E_INVALID_STATEMENT;
315 }
316
317 if (index >= columnCount) {
318 return E_INVALID_COLUMN_INDEX;
319 }
320 char *errStr = nullptr;
321 int type = sqlite3_column_type(stmtHandle, index);
322 if (type == SQLITE_INTEGER) {
323 value = sqlite3_column_int64(stmtHandle, index);
324 } else if (type == SQLITE_TEXT) {
325 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
326 value = (val == nullptr) ? 0 : strtoll(val, &errStr, 0);
327 } else if (type == SQLITE_FLOAT) {
328 double val = sqlite3_column_double(stmtHandle, index);
329 value = static_cast<int64_t>(val);
330 } else if (type == SQLITE_NULL) {
331 value = 0;
332 } else if (type == SQLITE_BLOB) {
333 return E_INVALID_COLUMN_TYPE;
334 } else {
335 return E_ERROR;
336 }
337
338 return E_OK;
339 }
GetColumnDouble(int index,double & value) const340 int SqliteStatement::GetColumnDouble(int index, double &value) const
341 {
342 if (stmtHandle == nullptr) {
343 return E_INVALID_STATEMENT;
344 }
345
346 if (index >= columnCount) {
347 return E_INVALID_COLUMN_INDEX;
348 }
349 char *ptr = nullptr;
350 int type = sqlite3_column_type(stmtHandle, index);
351 if (type == SQLITE_FLOAT) {
352 value = sqlite3_column_double(stmtHandle, index);
353 } else if (type == SQLITE_INTEGER) {
354 int64_t val = sqlite3_column_int64(stmtHandle, index);
355 value = static_cast<double>(val);
356 } else if (type == SQLITE_TEXT) {
357 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
358 value = (val == nullptr) ? 0.0 : std::strtod(val, &ptr);
359 } else if (type == SQLITE_NULL) {
360 value = 0.0;
361 } else if (type == SQLITE_BLOB) {
362 return E_INVALID_COLUMN_TYPE;
363 } else {
364 return E_ERROR;
365 }
366
367 return E_OK;
368 }
IsReadOnly() const369 bool SqliteStatement::IsReadOnly() const
370 {
371 return readOnly;
372 }
373 } // namespace NativeRdb
374 } // namespace OHOS
375