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