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 <iomanip>
19 #include <sstream>
20
21 #include "logger.h"
22 #include "raw_data_parser.h"
23 #include "rdb_errno.h"
24 #include "sqlite_errno.h"
25 #include "sqlite_utils.h"
26 #include "sqlite_connection.h"
27
28 namespace OHOS {
29 namespace NativeRdb {
30 using namespace OHOS::Rdb;
31
32 // Setting Data Precision
33 const int SET_DATA_PRECISION = 15;
SqliteStatement()34 SqliteStatement::SqliteStatement() : sql(""), stmtHandle(nullptr), readOnly(false), columnCount(0), numParameters(0)
35 {
36 }
37
~SqliteStatement()38 SqliteStatement::~SqliteStatement()
39 {
40 Finalize();
41 }
42
CreateStatement(std::shared_ptr<SqliteConnection> connection,const std::string & sql)43 std::shared_ptr<SqliteStatement> SqliteStatement::CreateStatement(
44 std::shared_ptr<SqliteConnection> connection, const std::string &sql)
45 {
46 sqlite3_stmt *stmt = nullptr;
47 int errCode = sqlite3_prepare_v2(connection->dbHandle, sql.c_str(), sql.length(), &stmt, nullptr);
48 if (errCode != SQLITE_OK) {
49 LOG_ERROR("prepare_v2 ret is %{public}d", errCode);
50 if (stmt != nullptr) {
51 sqlite3_finalize(stmt);
52 }
53 return nullptr;
54 }
55 std::shared_ptr<SqliteStatement> sqliteStatement = std::make_shared<SqliteStatement>();
56 sqliteStatement->stmtHandle = stmt;
57 sqliteStatement->readOnly = (sqlite3_stmt_readonly(stmt) != 0) ? true : false;
58 sqliteStatement->columnCount = sqlite3_column_count(stmt);
59 sqliteStatement->numParameters = sqlite3_bind_parameter_count(stmt);
60 return sqliteStatement;
61 }
62
Prepare(sqlite3 * dbHandle,const std::string & newSql)63 int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql)
64 {
65 if (sql.compare(newSql) == 0) {
66 return E_OK;
67 }
68 // prepare the new sqlite3_stmt
69 sqlite3_stmt *stmt = nullptr;
70 int errCode = sqlite3_prepare_v2(dbHandle, newSql.c_str(), newSql.length(), &stmt, nullptr);
71 if (errCode != SQLITE_OK) {
72 if (stmt != nullptr) {
73 sqlite3_finalize(stmt);
74 }
75 return SQLiteError::ErrNo(errCode);
76 }
77 Finalize(); // finalize the old
78 sql = newSql;
79 stmtHandle = stmt;
80 readOnly = (sqlite3_stmt_readonly(stmtHandle) != 0) ? true : false;
81 columnCount = sqlite3_column_count(stmtHandle);
82 numParameters = sqlite3_bind_parameter_count(stmtHandle);
83 return E_OK;
84 }
85
Finalize()86 int SqliteStatement::Finalize()
87 {
88 if (stmtHandle == nullptr) {
89 return E_OK;
90 }
91
92 int errCode = sqlite3_finalize(stmtHandle);
93 stmtHandle = nullptr;
94 sql = "";
95 readOnly = false;
96 columnCount = 0;
97 numParameters = 0;
98 if (errCode != SQLITE_OK) {
99 LOG_ERROR("finalize ret is %{public}d", errCode);
100 return SQLiteError::ErrNo(errCode);
101 }
102 return E_OK;
103 }
104
BindArguments(const std::vector<ValueObject> & bindArgs) const105 int SqliteStatement::BindArguments(const std::vector<ValueObject> &bindArgs) const
106 {
107 int count = static_cast<int>(bindArgs.size());
108 std::vector<ValueObject> abindArgs;
109
110 if (count == 0) {
111 return E_OK;
112 }
113 // Obtains the bound parameter set.
114 if ((numParameters != 0) && (count <= numParameters)) {
115 for (const auto& i : bindArgs) {
116 abindArgs.push_back(i);
117 }
118
119 for (int i = count; i < numParameters; i++) { // TD: when count <> numParameters
120 ValueObject val;
121 abindArgs.push_back(val);
122 }
123 }
124
125 if (count > numParameters) {
126 LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d)", count, numParameters);
127 return E_INVALID_BIND_ARGS_COUNT;
128 }
129
130 return InnerBindArguments(abindArgs);
131 }
132
InnerBindArguments(const std::vector<ValueObject> & bindArgs) const133 int SqliteStatement::InnerBindArguments(const std::vector<ValueObject> &bindArgs) const
134 {
135 int index = 1;
136 int errCode;
137 for (auto arg : bindArgs) {
138 switch (arg.GetType()) {
139 case ValueObjectType::TYPE_NULL: {
140 errCode = sqlite3_bind_null(stmtHandle, index);
141 break;
142 }
143 case ValueObjectType::TYPE_INT: {
144 int64_t value = 0;
145 arg.GetLong(value);
146 errCode = sqlite3_bind_int64(stmtHandle, index, value);
147 break;
148 }
149 case ValueObjectType::TYPE_DOUBLE: {
150 double doubleVal = 0;
151 arg.GetDouble(doubleVal);
152 errCode = sqlite3_bind_double(stmtHandle, index, doubleVal);
153 break;
154 }
155 case ValueObjectType::TYPE_BLOB: {
156 std::vector<uint8_t> blob;
157 arg.GetBlob(blob);
158 errCode = sqlite3_bind_blob(stmtHandle, index, static_cast<const void *>(blob.data()), blob.size(),
159 SQLITE_TRANSIENT);
160 break;
161 }
162 case ValueObjectType::TYPE_BOOL: {
163 bool boolVal = false;
164 arg.GetBool(boolVal);
165 errCode = sqlite3_bind_int64(stmtHandle, index, boolVal ? 1 : 0);
166 break;
167 }
168 case ValueObjectType::TYPE_ASSET: {
169 Asset asset;
170 arg.GetAsset(asset);
171 auto rawData = RawDataParser::PackageRawData(asset);
172 errCode = sqlite3_bind_blob(stmtHandle, index, static_cast<const void *>(rawData.data()),
173 rawData.size(), SQLITE_TRANSIENT);
174 break;
175 }
176 case ValueObjectType::TYPE_ASSETS: {
177 Assets assets;
178 arg.GetAssets(assets);
179 auto rawData = RawDataParser::PackageRawData(assets);
180 errCode = sqlite3_bind_blob(stmtHandle, index, static_cast<const void *>(rawData.data()),
181 rawData.size(), SQLITE_TRANSIENT);
182 break;
183 }
184 default: {
185 std::string str;
186 arg.GetString(str);
187 errCode = sqlite3_bind_text(stmtHandle, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
188 break;
189 }
190 }
191
192 if (errCode != SQLITE_OK) {
193 LOG_ERROR("bind ret is %{public}d", errCode);
194 return SQLiteError::ErrNo(errCode);
195 }
196
197 index++;
198 }
199
200 return E_OK;
201 }
202
ResetStatementAndClearBindings() const203 int SqliteStatement::ResetStatementAndClearBindings() const
204 {
205 if (stmtHandle == nullptr) {
206 return E_OK;
207 }
208
209 int errCode = sqlite3_reset(stmtHandle);
210 if (errCode != SQLITE_OK) {
211 LOG_ERROR("reset ret is %{public}d", errCode);
212 return SQLiteError::ErrNo(errCode);
213 }
214
215 errCode = sqlite3_clear_bindings(stmtHandle);
216 if (errCode != SQLITE_OK) {
217 LOG_ERROR("clear_bindings ret is %{public}d", errCode);
218 return SQLiteError::ErrNo(errCode);
219 }
220
221 return E_OK;
222 }
223
Step() const224 int SqliteStatement::Step() const
225 {
226 int errCode = sqlite3_step(stmtHandle);
227 return errCode;
228 }
229
GetColumnCount(int & count) const230 int SqliteStatement::GetColumnCount(int &count) const
231 {
232 if (stmtHandle == nullptr) {
233 LOG_ERROR("invalid statement.");
234 return E_INVALID_STATEMENT;
235 }
236 count = columnCount;
237 return E_OK;
238 }
239
GetColumnName(int index,std::string & columnName) const240 int SqliteStatement::GetColumnName(int index, std::string &columnName) const
241 {
242 int ret = IsValid(index);
243 if (ret != E_OK) {
244 return ret;
245 }
246
247 const char *name = sqlite3_column_name(stmtHandle, index);
248 if (name == nullptr) {
249 LOG_ERROR("column_name is null.");
250 return E_ERROR;
251 }
252 columnName = std::string(name);
253 return E_OK;
254 }
255
GetColumnType(int index,int & columnType) const256 int SqliteStatement::GetColumnType(int index, int &columnType) const
257 {
258 int ret = IsValid(index);
259 if (ret != E_OK) {
260 return ret;
261 }
262
263 int type = sqlite3_column_type(stmtHandle, index);
264 switch (type) {
265 case SQLITE_INTEGER:
266 case SQLITE_FLOAT:
267 case SQLITE_NULL:
268 case SQLITE_TEXT:
269 columnType = type;
270 return E_OK;
271 case SQLITE_BLOB: {
272 auto declType = SqliteUtils::StrToUpper(std::string(sqlite3_column_decltype(stmtHandle, index)));
273 if (declType == ValueObject::DeclType<ValueObject::Asset>()) {
274 columnType = COLUMN_TYPE_ASSET;
275 return E_OK;
276 }
277 if (declType == ValueObject::DeclType<ValueObject::Assets>()) {
278 columnType = COLUMN_TYPE_ASSETS;
279 return E_OK;
280 }
281 columnType = type;
282 return E_OK;
283 }
284 default:
285 LOG_ERROR("invalid type %{public}d.", type);
286 return E_ERROR;
287 }
288 }
289
GetColumnBlob(int index,std::vector<uint8_t> & value) const290 int SqliteStatement::GetColumnBlob(int index, std::vector<uint8_t> &value) const
291 {
292 int ret = IsValid(index);
293 if (ret != E_OK) {
294 return ret;
295 }
296
297 int type = sqlite3_column_type(stmtHandle, index);
298 if (type != SQLITE_BLOB && type != SQLITE_TEXT && type != SQLITE_NULL) {
299 LOG_ERROR("invalid type %{public}d.", type);
300 return E_INVALID_COLUMN_TYPE;
301 }
302
303 int size = sqlite3_column_bytes(stmtHandle, index);
304 auto blob = static_cast<const uint8_t *>(sqlite3_column_blob(stmtHandle, index));
305 if (size == 0 || blob == nullptr) {
306 value.resize(0);
307 } else {
308 value.resize(size);
309 value.assign(blob, blob + size);
310 }
311
312 return E_OK;
313 }
314
GetColumnString(int index,std::string & value) const315 int SqliteStatement::GetColumnString(int index, std::string &value) const
316 {
317 int ret = IsValid(index);
318 if (ret != E_OK) {
319 return ret;
320 }
321
322 int type = sqlite3_column_type(stmtHandle, index);
323 switch (type) {
324 case SQLITE_TEXT: {
325 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
326 value = (val == nullptr) ? "" : std::string(val, sqlite3_column_bytes(stmtHandle, index));
327 break;
328 }
329 case SQLITE_INTEGER: {
330 int64_t val = sqlite3_column_int64(stmtHandle, index);
331 value = std::to_string(val);
332 break;
333 }
334 case SQLITE_FLOAT: {
335 double val = sqlite3_column_double(stmtHandle, index);
336 std::ostringstream os;
337 if (os << std::setprecision(SET_DATA_PRECISION) << val)
338 value = os.str();
339 break;
340 }
341 case SQLITE_NULL: {
342 value = "";
343 return E_OK;
344 }
345 case SQLITE_BLOB: {
346 return E_INVALID_COLUMN_TYPE;
347 }
348 default:
349 return E_ERROR;
350 }
351 return E_OK;
352 }
353
GetColumnLong(int index,int64_t & value) const354 int SqliteStatement::GetColumnLong(int index, int64_t &value) const
355 {
356 int ret = IsValid(index);
357 if (ret != E_OK) {
358 return ret;
359 }
360
361 char *errStr = nullptr;
362 int type = sqlite3_column_type(stmtHandle, index);
363 if (type == SQLITE_INTEGER) {
364 value = sqlite3_column_int64(stmtHandle, index);
365 } else if (type == SQLITE_TEXT) {
366 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
367 value = (val == nullptr) ? 0 : strtoll(val, &errStr, 0);
368 } else if (type == SQLITE_FLOAT) {
369 double val = sqlite3_column_double(stmtHandle, index);
370 value = static_cast<int64_t>(val);
371 } else if (type == SQLITE_NULL) {
372 value = 0;
373 } else if (type == SQLITE_BLOB) {
374 return E_INVALID_COLUMN_TYPE;
375 } else {
376 return E_ERROR;
377 }
378
379 return E_OK;
380 }
GetColumnDouble(int index,double & value) const381 int SqliteStatement::GetColumnDouble(int index, double &value) const
382 {
383 int ret = IsValid(index);
384 if (ret != E_OK) {
385 return ret;
386 }
387
388 char *ptr = nullptr;
389 int type = sqlite3_column_type(stmtHandle, index);
390 if (type == SQLITE_FLOAT) {
391 value = sqlite3_column_double(stmtHandle, index);
392 } else if (type == SQLITE_INTEGER) {
393 int64_t val = sqlite3_column_int64(stmtHandle, index);
394 value = static_cast<double>(val);
395 } else if (type == SQLITE_TEXT) {
396 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
397 value = (val == nullptr) ? 0.0 : std::strtod(val, &ptr);
398 } else if (type == SQLITE_NULL) {
399 value = 0.0;
400 } else if (type == SQLITE_BLOB) {
401 return E_INVALID_COLUMN_TYPE;
402 } else {
403 LOG_ERROR("invalid type %{public}d.", type);
404 return E_ERROR;
405 }
406
407 return E_OK;
408 }
409
GetColumn(int index,ValueObject & value) const410 int SqliteStatement::GetColumn(int index, ValueObject &value) const
411 {
412 int ret = IsValid(index);
413 if (ret != E_OK) {
414 return ret;
415 }
416
417 int type = sqlite3_column_type(stmtHandle, index);
418 switch (type) {
419 case SQLITE_FLOAT:
420 value = sqlite3_column_double(stmtHandle, index);
421 return E_OK;
422 case SQLITE_INTEGER:
423 value = static_cast<int64_t>(sqlite3_column_int64(stmtHandle, index));
424 return E_OK;
425 case SQLITE_TEXT:
426 value = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
427 return E_OK;
428 case SQLITE_NULL:
429 return E_OK;
430 default:
431 break;
432 }
433 const char *decl = sqlite3_column_decltype(stmtHandle, index);
434 if (type != SQLITE_BLOB || decl == nullptr) {
435 LOG_ERROR("invalid type %{public}d.", type);
436 return E_ERROR;
437 }
438 int size = sqlite3_column_bytes(stmtHandle, index);
439 auto blob = static_cast<const uint8_t *>(sqlite3_column_blob(stmtHandle, index));
440 std::string declType = decl;
441 if (SqliteUtils::StrToUpper(declType) == ValueObject::DeclType<Asset>()) {
442 Asset asset;
443 RawDataParser::ParserRawData(blob, size, asset);
444 value = std::move(asset);
445 return E_OK;
446 }
447 if (SqliteUtils::StrToUpper(declType) == ValueObject::DeclType<Assets>()) {
448 Assets assets;
449 RawDataParser::ParserRawData(blob, size, assets);
450 value = std::move(assets);
451 return E_OK;
452 }
453 std::vector<uint8_t> rawData;
454 if (size > 0 || blob != nullptr) {
455 rawData.resize(size);
456 rawData.assign(blob, blob + size);
457 }
458 value = std::move(rawData);
459 return E_OK;
460 }
461
GetSize(int index,size_t & size) const462 int SqliteStatement::GetSize(int index, size_t &size) const
463 {
464 size = 0;
465 if (stmtHandle == nullptr) {
466 return E_INVALID_STATEMENT;
467 }
468
469 if (index >= columnCount) {
470 return E_INVALID_COLUMN_INDEX;
471 }
472
473 int type = sqlite3_column_type(stmtHandle, index);
474 if (type == SQLITE_BLOB || type == SQLITE_TEXT || type == SQLITE_NULL) {
475 size = static_cast<size_t>(sqlite3_column_bytes(stmtHandle, index));
476 return E_OK;
477 }
478
479 return E_INVALID_COLUMN_TYPE;
480 }
481
IsReadOnly() const482 bool SqliteStatement::IsReadOnly() const
483 {
484 return readOnly;
485 }
486
IsValid(int index) const487 int SqliteStatement::IsValid(int index) const
488 {
489 if (stmtHandle == nullptr) {
490 LOG_ERROR("invalid statement.");
491 return E_INVALID_STATEMENT;
492 }
493
494 if (index >= columnCount) {
495 LOG_ERROR("index (%{public}d) >= columnCount (%{public}d)", index, columnCount);
496 return E_INVALID_COLUMN_INDEX;
497 }
498
499 return E_OK;
500 }
501 } // namespace NativeRdb
502 } // namespace OHOS
503