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_INT64: {
124 int64_t value = 0;
125 arg.GetLong(value);
126 errCode = sqlite3_bind_int64(stmtHandle, index, value);
127 break;
128 }
129 case ValueObjectType::TYPE_DOUBLE: {
130 double doubleVal = 0;
131 arg.GetDouble(doubleVal);
132 errCode = sqlite3_bind_double(stmtHandle, index, doubleVal);
133 break;
134 }
135 case ValueObjectType::TYPE_BLOB: {
136 std::vector<uint8_t> blob;
137 arg.GetBlob(blob);
138 errCode = sqlite3_bind_blob(stmtHandle, index, static_cast<const void *>(blob.data()), blob.size(),
139 SQLITE_TRANSIENT);
140 break;
141 }
142 case ValueObjectType::TYPE_BOOL: {
143 bool boolVal = false;
144 arg.GetBool(boolVal);
145 errCode = sqlite3_bind_int64(stmtHandle, index, boolVal ? 1 : 0);
146 break;
147 }
148 default: {
149 std::string str;
150 arg.GetString(str);
151 errCode = sqlite3_bind_text(stmtHandle, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
152 break;
153 }
154 }
155
156 if (errCode != SQLITE_OK) {
157 return SQLiteError::ErrNo(errCode);
158 }
159
160 index++;
161 }
162
163 return E_OK;
164 }
165
ResetStatementAndClearBindings() const166 int SqliteStatement::ResetStatementAndClearBindings() const
167 {
168 if (stmtHandle == nullptr) {
169 return E_OK;
170 }
171
172 int errCode = sqlite3_reset(stmtHandle);
173 if (errCode != SQLITE_OK) {
174 LOG_ERROR("Reset statement failed. %{public}d", errCode);
175 return SQLiteError::ErrNo(errCode);
176 }
177
178 errCode = sqlite3_clear_bindings(stmtHandle);
179 if (errCode != SQLITE_OK) {
180 LOG_ERROR("Reset clear bindings failed. %{public}d", errCode);
181 return SQLiteError::ErrNo(errCode);
182 }
183
184 return E_OK;
185 }
186
Step() const187 int SqliteStatement::Step() const
188 {
189 int errCode = sqlite3_step(stmtHandle);
190 return errCode;
191 }
192
GetColumnCount(int & count) const193 int SqliteStatement::GetColumnCount(int &count) const
194 {
195 if (stmtHandle == nullptr) {
196 return E_INVALID_STATEMENT;
197 }
198 count = columnCount;
199 return E_OK;
200 }
201
202 /**
203 * Obtains the number that the statement has.
204 */
GetNumParameters(int & numParams) const205 int SqliteStatement::GetNumParameters(int &numParams) const
206 {
207 if (stmtHandle == nullptr) {
208 return E_INVALID_STATEMENT;
209 }
210 numParams = numParameters;
211 return E_OK;
212 }
213
GetColumnName(int index,std::string & columnName) const214 int SqliteStatement::GetColumnName(int index, std::string &columnName) const
215 {
216 if (stmtHandle == nullptr) {
217 return E_INVALID_STATEMENT;
218 }
219
220 if (index >= columnCount) {
221 return E_INVALID_COLUMN_INDEX;
222 }
223
224 const char *name = sqlite3_column_name(stmtHandle, index);
225 if (name == nullptr) {
226 return E_ERROR;
227 }
228 columnName = std::string(name);
229 return E_OK;
230 }
231
GetColumnType(int index,int & columnType) const232 int SqliteStatement::GetColumnType(int index, int &columnType) const
233 {
234 if (stmtHandle == nullptr) {
235 return E_INVALID_STATEMENT;
236 }
237
238 if (index >= columnCount) {
239 return E_INVALID_COLUMN_INDEX;
240 }
241
242 int type = sqlite3_column_type(stmtHandle, index);
243 switch (type) {
244 case SQLITE_INTEGER:
245 case SQLITE_FLOAT:
246 case SQLITE_BLOB:
247 case SQLITE_NULL:
248 case SQLITE_TEXT:
249 columnType = type;
250 return E_OK;
251 default:
252 return E_ERROR;
253 }
254 }
255
GetColumnBlob(int index,std::vector<uint8_t> & value) const256 int SqliteStatement::GetColumnBlob(int index, std::vector<uint8_t> &value) const
257 {
258 if (stmtHandle == nullptr) {
259 return E_INVALID_STATEMENT;
260 }
261
262 if (index >= columnCount) {
263 return E_INVALID_COLUMN_INDEX;
264 }
265
266 int type = sqlite3_column_type(stmtHandle, index);
267 if (type != SQLITE_BLOB && type != SQLITE_TEXT && type != SQLITE_NULL) {
268 return E_INVALID_COLUMN_TYPE;
269 }
270
271 int size = sqlite3_column_bytes(stmtHandle, index);
272 auto blob = static_cast<const uint8_t *>(sqlite3_column_blob(stmtHandle, index));
273 if (size == 0 || blob == nullptr) {
274 value.resize(0);
275 } else {
276 value.resize(size);
277 value.assign(blob, blob + size);
278 }
279
280 return E_OK;
281 }
282
GetColumnString(int index,std::string & value) const283 int SqliteStatement::GetColumnString(int index, std::string &value) const
284 {
285 if (stmtHandle == nullptr) {
286 return E_INVALID_STATEMENT;
287 }
288
289 if (index >= columnCount) {
290 return E_INVALID_COLUMN_INDEX;
291 }
292
293 int type = sqlite3_column_type(stmtHandle, index);
294 switch (type) {
295 case SQLITE_TEXT: {
296 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
297 value = (val == nullptr) ? "" : std::string(val, sqlite3_column_bytes(stmtHandle, index));
298 break;
299 }
300 case SQLITE_INTEGER: {
301 int64_t val = sqlite3_column_int64(stmtHandle, index);
302 value = std::to_string(val);
303 break;
304 }
305 case SQLITE_FLOAT: {
306 double val = sqlite3_column_double(stmtHandle, index);
307 std::ostringstream os;
308 if (os << std::setprecision(SET_DATA_PRECISION) << val)
309 value = os.str();
310 break;
311 }
312 case SQLITE_NULL: {
313 value = "";
314 return E_OK;
315 }
316 case SQLITE_BLOB: {
317 return E_INVALID_COLUMN_TYPE;
318 }
319 default:
320 return E_ERROR;
321 }
322 return E_OK;
323 }
324
GetColumnLong(int index,int64_t & value) const325 int SqliteStatement::GetColumnLong(int index, int64_t &value) const
326 {
327 if (stmtHandle == nullptr) {
328 return E_INVALID_STATEMENT;
329 }
330
331 if (index >= columnCount) {
332 return E_INVALID_COLUMN_INDEX;
333 }
334 char *errStr = nullptr;
335 int type = sqlite3_column_type(stmtHandle, index);
336 if (type == SQLITE_INTEGER) {
337 value = sqlite3_column_int64(stmtHandle, index);
338 } else if (type == SQLITE_TEXT) {
339 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
340 value = (val == nullptr) ? 0 : strtoll(val, &errStr, 0);
341 } else if (type == SQLITE_FLOAT) {
342 double val = sqlite3_column_double(stmtHandle, index);
343 value = static_cast<int64_t>(val);
344 } else if (type == SQLITE_NULL) {
345 value = 0;
346 } else if (type == SQLITE_BLOB) {
347 return E_INVALID_COLUMN_TYPE;
348 } else {
349 return E_ERROR;
350 }
351
352 return E_OK;
353 }
GetColumnDouble(int index,double & value) const354 int SqliteStatement::GetColumnDouble(int index, double &value) const
355 {
356 if (stmtHandle == nullptr) {
357 return E_INVALID_STATEMENT;
358 }
359
360 if (index >= columnCount) {
361 return E_INVALID_COLUMN_INDEX;
362 }
363 char *ptr = nullptr;
364 int type = sqlite3_column_type(stmtHandle, index);
365 if (type == SQLITE_FLOAT) {
366 value = sqlite3_column_double(stmtHandle, index);
367 } else if (type == SQLITE_INTEGER) {
368 int64_t val = sqlite3_column_int64(stmtHandle, index);
369 value = static_cast<double>(val);
370 } else if (type == SQLITE_TEXT) {
371 auto val = reinterpret_cast<const char *>(sqlite3_column_text(stmtHandle, index));
372 value = (val == nullptr) ? 0.0 : std::strtod(val, &ptr);
373 } else if (type == SQLITE_NULL) {
374 value = 0.0;
375 } else if (type == SQLITE_BLOB) {
376 return E_INVALID_COLUMN_TYPE;
377 } else {
378 return E_ERROR;
379 }
380
381 return E_OK;
382 }
IsReadOnly() const383 bool SqliteStatement::IsReadOnly() const
384 {
385 return readOnly;
386 }
387 } // namespace NativeRdb
388 } // namespace OHOS
389