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