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