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