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
26 namespace OHOS {
27 namespace NativeRdb {
28 using namespace OHOS::Rdb;
29 std::vector<std::string> g_onConflictClause = {
30 "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE"
31 };
SqliteSqlBuilder()32 SqliteSqlBuilder::SqliteSqlBuilder() {}
~SqliteSqlBuilder()33 SqliteSqlBuilder::~SqliteSqlBuilder() {}
34
35 /**
36 * Build a delete SQL string using the given condition for SQLite.
37 */
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)38 std::string SqliteSqlBuilder::BuildDeleteString(const std::string &tableName, const std::string &index,
39 const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
40 {
41 std::string sql;
42 sql.append("Delete ").append("FROM ").append(tableName).append(
43 BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset));
44 return sql;
45 }
46
47 /**
48 * Build a count SQL string using the given condition for SQLite.
49 */
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)50 std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, const std::string &tableName,
51 const std::vector<std::string> &whereArgs, const std::string &index, const std::string &whereClause,
52 const std::string &group, const std::string &order, int limit, int offset, std::vector<ValueObject> &bindArgs,
53 ConflictResolution conflictResolution)
54 {
55 std::string sql;
56
57 sql.append("UPDATE")
58 .append(g_onConflictClause[static_cast<int>(conflictResolution)])
59 .append(" ")
60 .append(tableName)
61 .append(" SET ");
62 const char *split = "";
63 for (auto &[key, val] : values.values_) {
64 sql.append(split);
65 sql.append(key).append("=?");
66 bindArgs.push_back(val);
67 split = ",";
68 }
69
70 if (!whereArgs.empty()) {
71 for (size_t i = 0; i < whereArgs.size(); i++) {
72 bindArgs.push_back(ValueObject(whereArgs[i]));
73 }
74 }
75 sql.append(BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset));
76 return sql;
77 }
78
79 /**
80 * Build a query SQL string using the given condition for SQLite.
81 */
BuildQueryString(bool distinct,const std::string & table,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)82 int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table,
83 const std::vector<std::string> &columns, const std::string &whereClause, const std::string &groupBy,
84 const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset, std::string &outSql)
85 {
86 if (table.empty()) {
87 return E_EMPTY_TABLE_NAME;
88 }
89
90 std::string sql;
91 sql.append("SELECT ");
92 if (distinct) {
93 sql.append("DISTINCT ");
94 }
95 if (columns.size() != 0) {
96 AppendColumns(sql, columns);
97 } else {
98 sql.append("* ");
99 }
100 sql.append("FROM ").append(table).append(
101 BuildSqlStringFromPredicates(indexName, whereClause, groupBy, orderBy, limit, offset));
102 outSql = sql;
103
104 return E_OK;
105 }
106
107 /**
108 * Build a count SQL string using the given condition for SQLite.
109 */
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)110 std::string SqliteSqlBuilder::BuildCountString(const std::string &tableName, const std::string &index,
111 const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
112 {
113 std::string sql;
114 sql.append("SELECT COUNT(*) FROM ")
115 .append(tableName)
116 .append(BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset));
117 return sql;
118 }
119
BuildSqlStringFromPredicates(const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)120 std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &whereClause,
121 const std::string &group, const std::string &order, int limit, int offset)
122 {
123 std::string sqlString;
124
125 std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit);
126 std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset);
127
128 AppendClause(sqlString, " INDEXED BY ", index);
129 AppendClause(sqlString, " WHERE ", whereClause);
130 AppendClause(sqlString, " GROUP BY ", group);
131 AppendClause(sqlString, " ORDER BY ", order);
132 AppendClause(sqlString, " LIMIT ", limitStr);
133 AppendClause(sqlString, " OFFSET ", offsetStr);
134
135 return sqlString;
136 }
137
BuildSqlStringFromPredicates(const AbsPredicates & predicates)138 std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const AbsPredicates &predicates)
139 {
140 std::string limitStr =
141 (predicates.GetLimit() == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(predicates.GetLimit());
142 std::string offsetStr =
143 (predicates.GetOffset() == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(predicates.GetOffset());
144
145 std::string sqlString;
146 AppendClause(sqlString, " INDEXED BY ", predicates.GetIndex());
147 AppendClause(sqlString, " WHERE ", predicates.GetWhereClause());
148 AppendClause(sqlString, " GROUP BY ", predicates.GetGroup());
149 AppendClause(sqlString, " ORDER BY ", predicates.GetOrder());
150 AppendClause(sqlString, " LIMIT ", limitStr);
151 AppendClause(sqlString, " OFFSET ", offsetStr);
152
153 return sqlString;
154 }
155
BuildSqlStringFromPredicatesNoWhere(const std::string & index,const std::string & whereClause,const std::string & group,const std::string & order,int limit,int offset)156 std::string SqliteSqlBuilder::BuildSqlStringFromPredicatesNoWhere(const std::string &index,
157 const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset)
158 {
159 std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit);
160 std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset);
161
162 std::string sqlString;
163 AppendClause(sqlString, " INDEXED BY ", index);
164 AppendClause(sqlString, " ", whereClause);
165 AppendClause(sqlString, " GROUP BY ", group);
166 AppendClause(sqlString, " ORDER BY ", order);
167 AppendClause(sqlString, " LIMIT ", limitStr);
168 AppendClause(sqlString, " OFFSET ", offsetStr);
169
170 return sqlString;
171 }
172
AppendClause(std::string & builder,const std::string & name,const std::string & clause)173 void SqliteSqlBuilder::AppendClause(std::string &builder, const std::string &name, const std::string &clause)
174 {
175 if (clause.empty()) {
176 return;
177 }
178 builder.append(name);
179 builder.append(clause);
180 }
181
182 /**
183 * Add the names that are non-null in columns to s, separating them with commas.
184 */
AppendColumns(std::string & builder,const std::vector<std::string> & columns)185 void SqliteSqlBuilder::AppendColumns(std::string &builder, const std::vector<std::string> &columns)
186 {
187 size_t length = columns.size();
188 for (size_t i = 0; i < length; i++) {
189 std::string column = columns[i];
190
191 if (column.size() != 0) {
192 if (i > 0) {
193 builder.append(", ");
194 }
195 builder.append(column);
196 }
197 }
198
199 builder += ' ';
200 }
201
BuildQueryString(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns)202 std::string SqliteSqlBuilder::BuildQueryString(
203 const AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
204 {
205 bool distinct = predicates.IsDistinct();
206 std::string tableNameStr = predicates.GetJoinClause();
207 std::string whereClauseStr = predicates.GetWhereClause();
208 std::string groupStr = predicates.GetGroup();
209 std::string indexStr = predicates.GetIndex();
210 std::string orderStr = predicates.GetOrder();
211 int limit = predicates.GetLimit();
212 int offset = predicates.GetOffset();
213 std::string sqlStr;
214 BuildQueryString(
215 distinct, tableNameStr, columns, whereClauseStr, groupStr, indexStr, orderStr, limit, offset, sqlStr);
216 return sqlStr;
217 }
218
BuildCountString(const AbsRdbPredicates & predicates)219 std::string SqliteSqlBuilder::BuildCountString(const AbsRdbPredicates &predicates)
220 {
221 std::string tableName = predicates.GetTableName();
222 return "SELECT COUNT(*) FROM " + tableName + BuildSqlStringFromPredicates(predicates);
223 }
224 } // namespace NativeRdb
225 } // namespace OHOS
226