• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "sg_sqlite_helper.h"
17 #include "security_guard_log.h"
18 #include "security_guard_define.h"
19 #include <sstream>
20 #include <string>
21 
22 namespace OHOS::Security::SecurityGuard {
SgSqliteHelper(const std::string & dbName,const std::string & dbPath,int version,const std::vector<std::string> & createSqls)23 SgSqliteHelper::SgSqliteHelper(const std::string &dbName, const std::string &dbPath, int version,
24     const std::vector<std::string> &createSqls) : SqliteHelper(dbName, dbPath, version), createSqls_(createSqls)
25 {
26     Open();
27 }
28 
OnCreate()29 void SgSqliteHelper::OnCreate()
30 {
31     SGLOGI("db create");
32     int32_t ret = FAILED;
33     size_t size = createSqls_.size();
34     if (size == 0) {
35         return;
36     }
37     for (size_t i = 0; i < size; i++) {
38         ret = ExecuteSql(createSqls_[i]);
39         if (ret == 0) {
40             return;
41         }
42     }
43     return;
44 }
45 
OnUpdate()46 void SgSqliteHelper::OnUpdate()
47 {
48     return;
49 }
50 
Insert(int64_t & outRowId,const std::string & table,const GenericValues & values)51 int SgSqliteHelper::Insert(int64_t &outRowId, const std::string &table, const GenericValues &values)
52 {
53     if (table.empty() || values.GetAllKeys().empty()) {
54         SGLOGE("invalid param");
55         return FAILED;
56     }
57 
58     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
59     std::string sql = BuildInsertSql(table, values);
60     if (sql.empty()) {
61         return FAILED;
62     }
63 
64     Statement stmt = Prepare(sql);
65     std::vector<std::string> keys = values.GetAllKeys();
66     for (const auto &key : keys) {
67         VariantValue val = values.Get(key);
68         if (val.GetType() == ValueType::TYPE_NULL) {
69             continue;
70         }
71         stmt.Bind(key, val);
72     }
73 
74     Statement::State execRet = stmt.Step();
75     if (execRet != Statement::DONE) {
76         SGLOGE("insert fail");
77         return FAILED;
78     }
79 
80     outRowId = sqlite3_last_insert_rowid(GetDb());
81     return SUCCESS;
82 }
83 
BatchInsert(int64_t & outInsertNum,const std::string & table,const std::vector<GenericValues> & initialBatchValues)84 int SgSqliteHelper::BatchInsert(int64_t &outInsertNum, const std::string &table,
85     const std::vector<GenericValues> &initialBatchValues)
86 {
87     (void)outInsertNum;
88     (void)table;
89     (void)initialBatchValues;
90     return SUCCESS;
91 }
92 
Update(int & changedRows,const std::string & table,const GenericValues & value)93 int SgSqliteHelper::Update(int &changedRows, const std::string &table, const GenericValues &value)
94 {
95     (void)changedRows;
96     (void)table;
97     (void)value;
98     return SUCCESS;
99 }
100 
Delete(int & deletedRows,const std::string & table,const GenericValues & conditions)101 int SgSqliteHelper::Delete(int &deletedRows, const std::string &table, const GenericValues &conditions)
102 {
103     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
104     Statement stmt = PrepareDeleteStmt(table, conditions);
105     if (stmt.Step() == Statement::DONE) {
106         deletedRows = sqlite3_changes(GetDb());
107         return SUCCESS;
108     }
109     return FAILED;
110 }
111 
Attach(const std::string & alias,const std::string & pathName,const std::vector<uint8_t> destEncryptKey)112 int SgSqliteHelper::Attach(const std::string &alias, const std::string &pathName,
113     const std::vector<uint8_t> destEncryptKey)
114 {
115     (void)alias;
116     (void)pathName;
117     (void)destEncryptKey;
118     return SUCCESS;
119 }
120 
ExecuteSql(const std::string & sql)121 int SgSqliteHelper::ExecuteSql(const std::string &sql)
122 {
123     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
124     return SqliteHelper::ExecuteSql(sql);
125 }
126 
ExecuteAndGetLong(int64_t & outValue,const std::string & sql,const std::vector<std::string> & bindArgs)127 int SgSqliteHelper::ExecuteAndGetLong(int64_t &outValue, const std::string &sql,
128     const std::vector<std::string> &bindArgs)
129 {
130     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
131     Statement stmt = Prepare(sql);
132     for (size_t i = 0; i < bindArgs.size(); ++i) {
133         stmt.Bind(i + 1, bindArgs[i]);
134     }
135 
136     if (stmt.Step() == Statement::ROW) {
137         outValue = stmt.GetColumnInt64(0);
138         return SUCCESS;
139     }
140     return FAILED;
141 }
142 
Count(int64_t & outValue,const std::string & table,const GenericValues & conditions,const QueryOptions & options)143 int SgSqliteHelper::Count(int64_t &outValue, const std::string &table, const GenericValues &conditions,
144                           const QueryOptions &options)
145 {
146     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
147     Statement stmt = PrepareCountStmt(table, conditions, options);
148     if (stmt.Step() == Statement::ROW) {
149         outValue = stmt.GetColumnInt64(0);
150         return SUCCESS;
151     }
152     return FAILED;
153 }
154 
ExecuteRowData(Statement & stmt)155 GenericValues SgSqliteHelper::ExecuteRowData(Statement &stmt)
156 {
157     GenericValues row;
158     const int columnCount = stmt.GetColumnCount();
159     for (int i = 0; i < columnCount; ++i) {
160         VariantValue value = stmt.GetValue(i, true);
161         const std::string columnName = stmt.GetColumnName(i);
162         switch (value.GetType()) {
163             case ValueType::TYPE_INT:
164                 row.Put(columnName, value.GetInt());
165                 break;
166             case ValueType::TYPE_INT64:
167                 row.Put(columnName, value.GetInt64());
168                 break;
169             case ValueType::TYPE_STRING:
170                 row.Put(columnName, value.GetString());
171                 break;
172             default:
173                 row.Put(columnName, "");
174                 break;
175         }
176     }
177 
178     return row;
179 }
180 
Query(const std::string & table,const GenericValues & conditions,std::vector<GenericValues> & results,const QueryOptions & options)181 int SgSqliteHelper::Query(const std::string &table, const GenericValues &conditions,
182     std::vector<GenericValues> &results, const QueryOptions &options)
183 {
184     OHOS::Utils::UniqueWriteGuard<OHOS::Utils::RWLock> lock(rwLock_);
185     std::string sql = BuildSelectSql(table, conditions, options);
186     if (sql.empty()) {
187         SGLOGE("BuildSelectSql fail");
188         return FAILED;
189     }
190 
191     Statement stmt = PrepareBoundStateStmt(sql, conditions);
192     while (stmt.Step() == Statement::ROW) {
193         results.emplace_back(ExecuteRowData(stmt));
194     }
195     return SUCCESS;
196 }
197 
BuildInsertSql(const std::string & table,const GenericValues & values)198 std::string SgSqliteHelper::BuildInsertSql(const std::string &table, const GenericValues &values)
199 {
200     std::vector<std::string> keys = values.GetAllKeys();
201     if (keys.empty()) {
202         SGLOGE("invalid param");
203         return "";
204     }
205 
206     std::ostringstream oss;
207     oss << " INSERT INTO " << table << " (";
208     for (size_t i = 0; i < keys.size(); ++i) {
209         oss << keys[i];
210         if (i != keys.size() - 1) {
211             oss << ",";
212         }
213     }
214 
215     oss << ") VALUES (";
216     for (size_t i = 0; i < keys.size(); ++i) {
217         oss << ":" << keys[i];
218         if (i != keys.size() - 1) {
219             oss << ",";
220         }
221     }
222     oss << ")";
223 
224     return oss.str();
225 }
226 
BuildUpdateSql(const std::string & table,const GenericValues & values,const std::string & where)227 std::string SgSqliteHelper::BuildUpdateSql(const std::string &table, const GenericValues &values,
228     const std::string &where)
229 {
230     auto keys = values.GetAllKeys();
231     if (keys.empty()) {
232         SGLOGE("update values is empty");
233         return "";
234     }
235 
236     std::string setClause;
237     for (size_t i = 0; i < keys.size(); ++i) {
238         setClause += keys[i] + "=?";
239         if (i != keys.size() - 1) {
240             setClause += ",";
241         }
242     }
243     std::string sql = "UPDATE " + table + " SET " + setClause;
244     if (!where.empty()) {
245         sql += " WHERE " + where;
246     }
247     return sql;
248 }
249 
BuildSelectSql(const std::string & table,const GenericValues & conditions,const QueryOptions & options)250 std::string SgSqliteHelper::BuildSelectSql(const std::string &table, const GenericValues &conditions,
251     const QueryOptions &options)
252 {
253     std::string columns = options.columns.empty() ? "*" : Join(options.columns, ", ");
254     std::string sql = "SELECT " + columns + " FROM " + table;
255     std::string whereClause = BuildWhereClause(conditions);
256     if (!whereClause.empty()) {
257         sql += " WHERE " + whereClause;
258     }
259     if (!options.orderBy.empty()) {
260         sql += " ORDER BY " + options.orderBy;
261     }
262     if (options.limit > 0) {
263         sql += " LIMIT " + std::to_string(options.limit);
264     }
265 
266     return sql;
267 }
268 
BuildInPlaceholders(const std::string & key,const std::string & values)269 std::string SgSqliteHelper::BuildInPlaceholders(const std::string &key, const std::string &values)
270 {
271     auto items = Split(values, ',');
272     std::vector<std::string> placeholders;
273     for (size_t i = 0; i < items.size(); ++i) {
274         placeholders.push_back(":" + key + "_" + std::to_string(i));
275     }
276 
277     return Join(placeholders, ",");
278 }
279 
Split(const std::string & s,char delimiter)280 std::vector<std::string> SgSqliteHelper::Split(const std::string &s, char delimiter)
281 {
282     std::vector<std::string> tokens;
283     std::string token;
284     std::istringstream tokenSteam(s);
285     while (std::getline(tokenSteam, token, delimiter)) {
286         tokens.push_back(token);
287     }
288     return tokens;
289 }
290 
PrepareBoundStateStmt(const std::string & sql,const GenericValues & conditions)291 Statement SgSqliteHelper::PrepareBoundStateStmt(const std::string &sql, const GenericValues &conditions)
292 {
293     Statement stmt = Prepare(sql);
294     auto keys = conditions.GetAllKeys();
295     for (const auto& key: keys) {
296         VariantValue value = conditions.Get(key);
297         if (key.find("_IN") != std::string::npos) {
298             auto items = Split(value.GetString(), ',');
299             for (size_t i = 0; i < items.size(); ++i) {
300                 const std::string paramName = key + "_" + std::to_string(i);
301                 stmt.Bind(paramName, VariantValue(items[i]));
302             }
303             continue;
304         }
305 
306         if (value.GetType() == ValueType::TYPE_INT) {
307             stmt.Bind(key, VariantValue(value.GetInt()));
308         } else if (value.GetType() == ValueType::TYPE_INT64) {
309             stmt.Bind(key, VariantValue(value.GetInt64()));
310         } else if (value.GetType() == ValueType::TYPE_STRING) {
311             stmt.Bind(key, VariantValue(value.GetString()));
312         }
313     }
314     return stmt;
315 }
316 
EndWith(const std::string & str,const std::string & suffix) const317 bool SgSqliteHelper::EndWith(const std::string &str, const std::string &suffix) const
318 {
319     if (str.length() < suffix.length()) {
320         return false;
321     }
322 
323     return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
324 }
325 
BuildWhereClause(const GenericValues & conditions)326 std::string SgSqliteHelper::BuildWhereClause(const GenericValues &conditions)
327 {
328     std::vector<std::string> clauses;
329     std::vector<std::string> ops = {"_IN", "_GE", "_LT", "_LIKE"};
330 
331     auto keys = conditions.GetAllKeys();
332     for (const auto& key : keys) {
333         std::string opFound;
334         std::string field = key;
335 
336         for (const auto& op: ops) {
337             if (EndWith(key, op)) {
338                 opFound = op.substr(1);
339                 field = key.substr(0, key.size() - op.size());
340                 break;
341             }
342         }
343 
344         if (opFound.empty()) {
345             clauses.push_back(key + " = :" + key);
346             continue;
347         }
348 
349         if (opFound == "IN") {
350             std::string placeholders = BuildInPlaceholders(key, conditions.Get(key).GetString());
351             clauses.push_back(field + " IN (" + placeholders + ")");
352         } else if (opFound == "GE") {
353             clauses.push_back(field + " >= :" + key);
354         } else if (opFound == "LT") {
355             clauses.push_back(field + " < :" + key);
356         } else if (opFound == "LIKE") {
357             clauses.push_back(field + " LIKE :" + key);
358         }
359     }
360 
361     return clauses.empty() ? "" : Join(clauses, " AND ");
362 }
363 
PrepareCountStmt(const std::string & table,const GenericValues & conditions,const QueryOptions & options)364 Statement SgSqliteHelper::PrepareCountStmt(const std::string &table, const GenericValues &conditions,
365     const QueryOptions &options)
366 {
367     std::string sql = "SELECT COUNT(*) FROM " + table;
368     std::string where = BuildWhereClause(conditions);
369     if (!where.empty()) {
370         sql += " WHERE " + where;
371     }
372 
373     return PrepareBoundStateStmt(sql, conditions);
374 }
375 
PrepareDeleteStmt(const std::string & table,const GenericValues & conditions)376 Statement SgSqliteHelper::PrepareDeleteStmt(const std::string &table, const GenericValues &conditions)
377 {
378     std::string sql = "DELETE FROM " + table;
379     std::string where = BuildWhereClause(conditions);
380     if (!where.empty()) {
381         sql += " WHERE " + where;
382     }
383 
384     return PrepareBoundStateStmt(sql, conditions);
385 }
386 
Join(const std::vector<std::string> & items,const std::string & delimiter)387 std::string SgSqliteHelper::Join(const std::vector<std::string> &items, const std::string &delimiter)
388 {
389     if (items.empty()) {
390         return "";
391     }
392 
393     std::string result;
394     bool isFirst = true;
395     for (const auto &str : items) {
396         if (!isFirst) {
397             result += delimiter;
398         }
399 
400         result += str;
401         isFirst = false;
402     }
403 
404     return result;
405 }
406 }
407