• 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_sql_builder.h"
17 
18 #include <list>
19 #include <regex>
20 
21 #include "logger.h"
22 #include "rdb_errno.h"
23 #include "rdb_trace.h"
24 #include "string_utils.h"
25 #include "sqlite_utils.h"
26 
27 namespace OHOS {
28 namespace NativeRdb {
29 using namespace OHOS::Rdb;
30 std::vector<std::string> g_onConflictClause = {
31     "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE"
32 };
SqliteSqlBuilder()33 SqliteSqlBuilder::SqliteSqlBuilder() {}
~SqliteSqlBuilder()34 SqliteSqlBuilder::~SqliteSqlBuilder() {}
35 
36 /**
37  * Build a delete SQL string using the given condition for SQLite.
38  */
BuildDeleteString(const std::string & tableName,const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)39 std::string SqliteSqlBuilder::BuildDeleteString(const std::string &tableName, const std::string &index,
40     const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
41 {
42     std::string sql;
43     sql.append("Delete ").append("FROM ").append(tableName).append(
44         BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset));
45     return sql;
46 }
47 
48 /**
49  * Build a count SQL string using the given condition for SQLite.
50  */
BuildUpdateString(const ValuesBucket & values,const std::string & tableName,const std::vector<std::string> & whereArgs,const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset,std::vector<ValueObject> & bindArgs,ConflictResolution conflictResolution)51 std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, const std::string &tableName,
52     const std::vector<std::string> &whereArgs, const std::string &index, const std::string &whereClause,
53     const std::string &group, const std::string &order, int limit, int offset, std::vector<ValueObject> &bindArgs,
54     ConflictResolution conflictResolution)
55 {
56     std::string sql;
57 
58     sql.append("UPDATE")
59         .append(g_onConflictClause[static_cast<int>(conflictResolution)])
60         .append(" ")
61         .append(tableName)
62         .append(" SET ");
63     const char *split = "";
64     for (auto &[key, val] : values.values_) {
65         sql.append(split);
66         sql.append(key).append("=?");
67         bindArgs.push_back(val);
68         split = ",";
69     }
70 
71     if (!whereArgs.empty()) {
72         for (size_t i = 0; i < whereArgs.size(); i++) {
73             bindArgs.push_back(ValueObject(whereArgs[i]));
74         }
75     }
76     sql.append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset));
77     return sql;
78 }
79 
80 /**
81  * Build a query SQL string using the given condition for SQLite.
82  */
BuildQueryString(bool distinct,const std::string & table,const std::string & joinClause,const std::vector<std::string> & columns,const std::string & whereClause,const std::string & groupBy,const std::string & indexName,const std::string & orderBy,const int & limit,const int & offset,std::string & outSql)83 int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, const std::string &joinClause,
84     const std::vector<std::string> &columns, const std::string &whereClause, const std::string &groupBy,
85     const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset, std::string &outSql)
86 {
87     if (table.empty()) {
88         return E_EMPTY_TABLE_NAME;
89     }
90 
91     std::string sql;
92     sql.append("SELECT ");
93     if (distinct) {
94         sql.append("DISTINCT ");
95     }
96     if (columns.size() != 0) {
97         AppendColumns(sql, columns);
98     } else {
99         sql.append("* ");
100     }
101     sql.append("FROM ").append(table).append(
102         BuildSqlStringFromPredicates(indexName, joinClause, whereClause, groupBy, orderBy, limit, offset));
103     outSql = sql;
104 
105     return E_OK;
106 }
107 
108 /**
109  * Build a count SQL string using the given condition for SQLite.
110  */
BuildCountString(const std::string & tableName,const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)111 std::string SqliteSqlBuilder::BuildCountString(const std::string &tableName, const std::string &index,
112     const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
113 {
114     std::string sql;
115     sql.append("SELECT COUNT(*) FROM ")
116         .append(tableName)
117         .append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset));
118     return sql;
119 }
120 
BuildSqlStringFromPredicates(const std::string & index,const std::string & joinClause,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)121 std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause,
122     const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
123 {
124     std::string sqlString;
125 
126     std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit);
127     std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset);
128 
129     AppendClause(sqlString, " INDEXED BY ", index);
130     AppendClause(sqlString, " ", joinClause);
131     AppendClause(sqlString, " WHERE ", whereClause);
132     AppendClause(sqlString, " GROUP BY ", group);
133     AppendClause(sqlString, " ORDER BY ", order);
134     AppendClause(sqlString, " LIMIT ", limitStr);
135     AppendClause(sqlString, " OFFSET ", offsetStr);
136 
137     return sqlString;
138 }
139 
BuildSqlStringFromPredicates(const AbsPredicates & predicates)140 std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const AbsPredicates &predicates)
141 {
142     std::string limitStr =
143         (predicates.GetLimit() == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(predicates.GetLimit());
144     std::string offsetStr =
145         (predicates.GetOffset() == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(predicates.GetOffset());
146 
147     std::string sqlString;
148     AppendClause(sqlString, " INDEXED BY ", predicates.GetIndex());
149     AppendClause(sqlString, " WHERE ", predicates.GetWhereClause());
150     AppendClause(sqlString, " GROUP BY ", predicates.GetGroup());
151     AppendClause(sqlString, " ORDER BY ", predicates.GetOrder());
152     AppendClause(sqlString, " LIMIT ", limitStr);
153     AppendClause(sqlString, " OFFSET ", offsetStr);
154 
155     return sqlString;
156 }
157 
BuildSqlStringFromPredicatesNoWhere(const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)158 std::string SqliteSqlBuilder::BuildSqlStringFromPredicatesNoWhere(const std::string &index,
159     const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
160 {
161     std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit);
162     std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset);
163 
164     std::string sqlString;
165     AppendClause(sqlString, " INDEXED BY ", index);
166     AppendClause(sqlString, " ", whereClause);
167     AppendClause(sqlString, " GROUP BY ", group);
168     AppendClause(sqlString, " ORDER BY ", order);
169     AppendClause(sqlString, " LIMIT ", limitStr);
170     AppendClause(sqlString, " OFFSET ", offsetStr);
171 
172     return sqlString;
173 }
174 
AppendClause(std::string & builder,const std::string & name,const std::string & clause,const std::string & table)175 void SqliteSqlBuilder::AppendClause(std::string &builder, const std::string &name,
176     const std::string &clause, const std::string &table)
177 {
178     if (clause.empty()) {
179         return;
180     }
181     builder.append(name);
182     if (!table.empty()) {
183         builder.append(table).append(".");
184     }
185     builder.append(clause);
186 }
187 
188 /**
189  * Add the names that are non-null in columns to s, separating them with commas.
190  */
AppendColumns(std::string & builder,const std::vector<std::string> & columns,const std::string & table)191 void SqliteSqlBuilder::AppendColumns(
192     std::string &builder, const std::vector<std::string> &columns, const std::string &table)
193 {
194     for (size_t i = 0; i < columns.size(); i++) {
195         const auto &col = columns[i];
196         if (col.empty()) {
197             continue;
198         }
199         if (i > 0 && !(columns[i - 1].empty())) {
200             builder.append(", ");
201         }
202         if (!table.empty()) {
203             builder.append(table).append(".");
204         }
205         builder.append(col);
206     }
207     if (table.empty()) {
208         builder += ' ';
209     }
210 }
211 
BuildQueryString(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns)212 std::string SqliteSqlBuilder::BuildQueryString(
213     const AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
214 {
215     bool distinct = predicates.IsDistinct();
216     std::string tableName = predicates.GetTableName();
217     std::string joinClauseStr = predicates.GetJoinClause();
218     std::string whereClauseStr = predicates.GetWhereClause();
219     std::string groupStr = predicates.GetGroup();
220     std::string indexStr = predicates.GetIndex();
221     std::string orderStr = predicates.GetOrder();
222     int limit = predicates.GetLimit();
223     int offset = predicates.GetOffset();
224     std::string sqlStr;
225     BuildQueryString(distinct, tableName, joinClauseStr, columns, whereClauseStr,
226         groupStr, indexStr, orderStr, limit, offset, sqlStr);
227     return sqlStr;
228 }
229 
BuildCountString(const AbsRdbPredicates & predicates)230 std::string SqliteSqlBuilder::BuildCountString(const AbsRdbPredicates &predicates)
231 {
232     std::string tableName = predicates.GetTableName();
233     return "SELECT COUNT(*) FROM " + tableName + BuildSqlStringFromPredicates(predicates);
234 }
235 
BuildCursorQueryString(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns,const std::string & logTable)236 std::string SqliteSqlBuilder::BuildCursorQueryString(
237     const AbsRdbPredicates &predicates, const std::vector<std::string> &columns, const std::string &logTable)
238 {
239     std::string sql;
240     std::string table = predicates.GetTableName();
241     if (table.empty() || logTable.empty()) {
242         return sql;
243     }
244     sql.append("SELECT ");
245     if (predicates.IsDistinct()) {
246         sql.append("DISTINCT ");
247     }
248     if (!columns.empty()) {
249         AppendColumns(sql, columns, table);
250     } else {
251         sql.append(table + ".*");
252     }
253     sql.append(", " + logTable + ".cursor");
254     sql.append(", CASE WHEN ").append(logTable).append(".")
255         .append("flag & 0x8 = 0x8 THEN true ELSE false END AS deleted_flag ");
256     sql.append("FROM ").append(table);
257     AppendClause(sql, " INDEXED BY ", predicates.GetIndex());
258     sql.append(" INNER JOIN ").append(logTable).append(" ON ").append(table)
259         .append(".ROWID = ").append(logTable).append(".data_key");
260     auto whereClause = predicates.GetWhereClause();
261     SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + ".");
262     AppendClause(sql, " WHERE ", whereClause);
263     AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table);
264     auto order = predicates.GetOrder();
265     SqliteUtils::Replace(order, SqliteUtils::REP, logTable + ".");
266     AppendClause(sql, " ORDER BY ", order);
267     int limit = predicates.GetLimit();
268     auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit);
269     int offset = predicates.GetOffset();
270     auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset);
271     AppendClause(sql, " LIMIT ", limitClause);
272     AppendClause(sql, " OFFSET ", offsetClause);
273     return sql;
274 }
275 } // namespace NativeRdb
276 } // namespace OHOS
277