• 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 <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