• 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 "abs_predicates.h"
17 
18 #include <algorithm>
19 #include <initializer_list>
20 #include <variant>
21 
22 #include "logger.h"
23 #include "rdb_trace.h"
24 #include "sqlite_sql_builder.h"
25 #include "string_utils.h"
26 
27 namespace OHOS {
28 namespace NativeRdb {
29 using namespace OHOS::Rdb;
30 
AbsPredicates()31 AbsPredicates::AbsPredicates()
32 {
33     Initial();
34 }
35 
~AbsPredicates()36 AbsPredicates::~AbsPredicates()
37 {
38 }
39 
Clear()40 void AbsPredicates::Clear()
41 {
42     Initial();
43 }
44 
IsNeedAnd() const45 bool AbsPredicates::IsNeedAnd() const
46 {
47     return isNeedAnd;
48 }
49 
50 /**
51  * Restricts the value of the field to be greater than the specified value.
52  */
EqualTo(const std::string & field,const ValueObject & value)53 AbsPredicates *AbsPredicates::EqualTo(const std::string &field, const ValueObject &value)
54 {
55     if (!CheckParameter("equalTo", field, { value })) {
56         return this;
57     }
58     if (isNeedAnd) {
59         whereClause += "AND ";
60     } else {
61         isNeedAnd = true;
62     }
63     whereClause += field + " = ? ";
64     bindArgs.push_back(value);
65     return this;
66 }
67 
68 /**
69  * Restricts the value of the field to be unequal to the specified value.
70  */
NotEqualTo(const std::string & field,const ValueObject & value)71 AbsPredicates *AbsPredicates::NotEqualTo(const std::string &field, const ValueObject &value)
72 {
73     if (!CheckParameter("notEqualTo", field, { value })) {
74         return this;
75     }
76     CheckIsNeedAnd();
77     whereClause += field + " <> ? ";
78     bindArgs.push_back(value);
79     return this;
80 }
81 
BeginWrap()82 AbsPredicates *AbsPredicates::BeginWrap()
83 {
84     if (isNeedAnd) {
85         whereClause += "AND ";
86         isNeedAnd = false;
87     }
88     whereClause += " ( ";
89     return this;
90 }
91 
EndWrap()92 AbsPredicates *AbsPredicates::EndWrap()
93 {
94     if (!isNeedAnd) {
95         LOG_WARN("fail to add EndWrap.");
96         return this;
97     }
98     whereClause += " ) ";
99     return this;
100 }
101 
Or()102 AbsPredicates *AbsPredicates::Or()
103 {
104     if (!isNeedAnd) {
105         LOG_WARN("fail to add Or.");
106         return this;
107     }
108     whereClause += " OR ";
109     isNeedAnd = false;
110     return this;
111 }
112 
And()113 AbsPredicates *AbsPredicates::And()
114 {
115     if (!isNeedAnd) {
116         LOG_WARN("fail to add And.");
117         return this;
118     }
119     return this;
120 }
121 
122 /**
123  * Restricts the value of the field to contain the specified string.
124  */
Contains(const std::string & field,const std::string & value)125 AbsPredicates *AbsPredicates::Contains(const std::string &field, const std::string &value)
126 {
127     if (!CheckParameter("contains", field, { value })) {
128         return this;
129     }
130     CheckIsNeedAnd();
131     whereClause += field + " LIKE ? ";
132     bindArgs.push_back(ValueObject("%" + value + "%"));
133     return this;
134 }
135 
136 /**
137  * Restricts the field to start with the specified string.
138  */
BeginsWith(const std::string & field,const std::string & value)139 AbsPredicates *AbsPredicates::BeginsWith(const std::string &field, const std::string &value)
140 {
141     if (!CheckParameter("beginsWith", field, { value })) {
142         return this;
143     }
144     CheckIsNeedAnd();
145     whereClause += field + " LIKE ? ";
146     bindArgs.push_back(ValueObject(value + "%"));
147     return this;
148 }
149 
150 /**
151  * Restricts the field to end with the specified string.
152  */
EndsWith(const std::string & field,const std::string & value)153 AbsPredicates *AbsPredicates::EndsWith(const std::string &field, const std::string &value)
154 {
155     if (!CheckParameter("endsWith", field, { value })) {
156         return this;
157     }
158     CheckIsNeedAnd();
159     whereClause += field + " LIKE ? ";
160     bindArgs.push_back(ValueObject("%" + value));
161     return this;
162 }
163 
164 /**
165  * Restricts the value of the field to be null.
166  */
IsNull(const std::string & field)167 AbsPredicates *AbsPredicates::IsNull(const std::string &field)
168 {
169     if (!CheckParameter("isNull", field, {})) {
170         return this;
171     }
172     CheckIsNeedAnd();
173     whereClause += field + " IS NULL ";
174     return this;
175 }
176 
177 /**
178  * estricts the value of the field not to be null.
179  */
IsNotNull(const std::string & field)180 AbsPredicates *AbsPredicates::IsNotNull(const std::string &field)
181 {
182     if (!CheckParameter("isNotNull", field, {})) {
183         return this;
184     }
185     CheckIsNeedAnd();
186     whereClause += field + " IS NOT NULL ";
187     return this;
188 }
189 
190 /**
191  * Restricts the value of the field to have a pattern like field.
192  */
Like(const std::string & field,const std::string & value)193 AbsPredicates *AbsPredicates::Like(const std::string &field, const std::string &value)
194 {
195     if (!CheckParameter("like", field, { value })) {
196         return this;
197     }
198     CheckIsNeedAnd();
199     whereClause += field + " LIKE ? ";
200     bindArgs.push_back(ValueObject(value));
201     return this;
202 }
203 
204 /**
205  * Configures to match the specified field whose data type is String and the value contains a wildcard.
206  */
Glob(const std::string & field,const std::string & value)207 AbsPredicates *AbsPredicates::Glob(const std::string &field, const std::string &value)
208 {
209     if (!CheckParameter("glob", field, { value })) {
210         return this;
211     }
212     CheckIsNeedAnd();
213     whereClause += field + " GLOB ? ";
214     bindArgs.push_back(ValueObject(value));
215     return this;
216 }
217 
218 /**
219  * Restricts the value of the field to be unequal to the specified value.
220  */
Between(const std::string & field,const ValueObject & low,const ValueObject & high)221 AbsPredicates *AbsPredicates::Between(const std::string &field, const ValueObject &low, const ValueObject &high)
222 {
223     if (!CheckParameter("between", field, { low, high })) {
224         return this;
225     }
226     CheckIsNeedAnd();
227     whereClause += field + " BETWEEN ? AND ? ";
228     bindArgs.push_back(low);
229     bindArgs.push_back(high);
230     return this;
231 }
232 
233 /**
234  * Configures to match the specified field whose data type is String and value is out of a given range.
235  */
NotBetween(const std::string & field,const ValueObject & low,const ValueObject & high)236 AbsPredicates *AbsPredicates::NotBetween(const std::string &field, const ValueObject &low, const ValueObject &high)
237 {
238     if (!CheckParameter("notBetween", field, { low, high })) {
239         return this;
240     }
241     CheckIsNeedAnd();
242     whereClause += field + " NOT BETWEEN ? AND ? ";
243     bindArgs.push_back(low);
244     bindArgs.push_back(high);
245     return this;
246 }
247 
248 /**
249  * Restricts the value of the field to be greater than the specified value.
250  */
GreaterThan(const std::string & field,const ValueObject & value)251 AbsPredicates *AbsPredicates::GreaterThan(const std::string &field, const ValueObject &value)
252 {
253     if (!CheckParameter("greaterThan", field, { value })) {
254         return this;
255     }
256     CheckIsNeedAnd();
257     whereClause += field + " > ? ";
258     bindArgs.push_back(value);
259     return this;
260 }
261 
262 /**
263  * Restricts the value of the field to be smaller than the specified value.
264  */
LessThan(const std::string & field,const ValueObject & value)265 AbsPredicates *AbsPredicates::LessThan(const std::string &field, const ValueObject &value)
266 {
267     if (!CheckParameter("lessThan", field, { value })) {
268         return this;
269     }
270     CheckIsNeedAnd();
271     whereClause += field + " < ? ";
272     bindArgs.push_back(value);
273     return this;
274 }
275 
276 /**
277  * Restricts the value of the field to be greater than or equal to the specified value.
278  */
GreaterThanOrEqualTo(const std::string & field,const ValueObject & value)279 AbsPredicates *AbsPredicates::GreaterThanOrEqualTo(const std::string &field, const ValueObject &value)
280 {
281     if (!CheckParameter("greaterThanOrEqualTo", field, { value })) {
282         return this;
283     }
284     CheckIsNeedAnd();
285     whereClause += field + " >= ? ";
286     bindArgs.push_back(value);
287     return this;
288 }
289 
290 /**
291  * Restricts the value of the field to be smaller than or equal to the specified value.
292  */
LessThanOrEqualTo(const std::string & field,const ValueObject & value)293 AbsPredicates *AbsPredicates::LessThanOrEqualTo(const std::string &field, const ValueObject &value)
294 {
295     if (!CheckParameter("greaterThanOrEqualTo", field, { value })) {
296         return this;
297     }
298     CheckIsNeedAnd();
299     whereClause += field + " <= ? ";
300     bindArgs.push_back(value);
301     return this;
302 }
303 
304 /**
305  * Restricts the ascending order of the return list. When there are several orders,
306  * the one close to the head has the highest priority.
307  */
OrderByAsc(const std::string & field)308 AbsPredicates *AbsPredicates::OrderByAsc(const std::string &field)
309 {
310     if (!CheckParameter("orderByAsc", field, {})) {
311         return this;
312     }
313     if (isSorted) {
314         order += ',';
315     }
316     order += field + " ASC ";
317     isSorted = true;
318     return this;
319 }
320 
321 /**
322  * Restricts the descending order of the return list. When there are several orders,
323  * the one close to the head has the highest priority.
324  */
OrderByDesc(const std::string & field)325 AbsPredicates *AbsPredicates::OrderByDesc(const std::string &field)
326 {
327     if (!CheckParameter("orderByDesc", field, {})) {
328         return this;
329     }
330     if (isSorted) {
331         order += ',';
332     }
333     order += field + " DESC ";
334     isSorted = true;
335     return this;
336 }
337 
Distinct()338 AbsPredicates *AbsPredicates::Distinct()
339 {
340     distinct = true;
341     return this;
342 }
343 
344 /**
345  * Restricts the max number of return records.
346  */
Limit(const int limit)347 AbsPredicates *AbsPredicates::Limit(const int limit)
348 {
349     this->limit = (limit <= 0) ? -1 : limit;
350     return this;
351 }
352 
353 /**
354  * Restricts the max number of return records.
355  */
Limit(const int offset,const int limit)356 AbsPredicates *AbsPredicates::Limit(const int offset, const int limit)
357 {
358     return this->Limit(limit)->Offset(offset);
359 }
360 
361 /**
362  * Configures to specify the start position of the returned result.
363  */
Offset(const int offset)364 AbsPredicates *AbsPredicates::Offset(const int offset)
365 {
366     this->offset = (offset < 0) ? -1 : offset;
367     return this;
368 }
369 
370 /**
371  * Configures {@code AbsPredicates} to group query results by specified columns.
372  */
GroupBy(const std::vector<std::string> & fields)373 AbsPredicates *AbsPredicates::GroupBy(const std::vector<std::string> &fields)
374 {
375     if (fields.empty()) {
376         LOG_WARN("groupBy() fails because fields can't be null.");
377         return this;
378     }
379     for (auto &field : fields) {
380         if (!CheckParameter("GroupBy", field, {})) {
381             return this;
382         }
383         group += field + ",";
384     }
385     size_t pos = group.find_last_of(",");
386     if (pos != group.npos) {
387         group.erase(pos, 1);
388     }
389     return this;
390 }
391 
392 /**
393  * Configures {@code AbsPredicates} to specify the index column.
394  */
IndexedBy(const std::string & indexName)395 AbsPredicates *AbsPredicates::IndexedBy(const std::string &indexName)
396 {
397     if (!CheckParameter("indexedBy", indexName, {})) {
398         return this;
399     }
400     index = RemoveQuotes(indexName);
401     return this;
402 }
403 
In(const std::string & field,const std::vector<std::string> & values)404 AbsPredicates *AbsPredicates::In(const std::string &field, const std::vector<std::string> &values)
405 {
406     std::vector<ValueObject> bindArgs;
407     std::for_each(values.begin(), values.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
408     return In(field, bindArgs);
409 }
410 
411 /**
412  * Configures to match the specified field whose data type is String array and values are within a given range.
413  */
In(const std::string & field,const std::vector<ValueObject> & values)414 AbsPredicates *AbsPredicates::In(const std::string &field, const std::vector<ValueObject> &values)
415 {
416     bool chekParaFlag = CheckParameter("in", field, {});
417     if (!chekParaFlag) {
418         return this;
419     }
420     if (values.empty()) {
421         LOG_WARN("in() fails because values can't be null.");
422         return this;
423     }
424 
425     CheckIsNeedAnd();
426 
427     std::vector<std::string> replaceValues(values.size(), "?");
428     bindArgs.insert(bindArgs.end(), values.begin(), values.end());
429     AppendWhereClauseWithInOrNotIn(" IN ", field, replaceValues);
430     return this;
431 }
432 
NotIn(const std::string & field,const std::vector<std::string> & values)433 AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector<std::string> &values)
434 {
435     std::vector<ValueObject> bindArgs;
436     std::for_each(values.begin(), values.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
437     return NotIn(field, bindArgs);
438 }
439 
440 /**
441  * Configures to match the specified field whose data type is String array and values are out of a given range.
442  */
NotIn(const std::string & field,const std::vector<ValueObject> & values)443 AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector<ValueObject> &values)
444 {
445     bool chekParaFlag = CheckParameter("notIn", field, {});
446     if (!chekParaFlag) {
447         return this;
448     }
449     if (values.empty()) {
450         LOG_WARN("fails as values is null.");
451         return this;
452     }
453     CheckIsNeedAnd();
454     std::vector<std::string> replaceValues(values.size(), "?");
455     bindArgs.insert(bindArgs.end(), values.begin(), values.end());
456     AppendWhereClauseWithInOrNotIn(" NOT IN ", field, replaceValues);
457     return this;
458 }
459 
Initial()460 void AbsPredicates::Initial()
461 {
462     distinct = false;
463     isNeedAnd = false;
464     isSorted = false;
465     bindArgs.clear();
466     whereClause.clear();
467     order.clear();
468     group.clear();
469     index.clear();
470     limit = INIT_LIMIT_VALUE;
471     offset = INIT_OFFSET_VALUE;
472 }
473 
474 /**
475  * Check the parameter validity.
476  */
CheckParameter(const std::string & methodName,const std::string & field,const std::initializer_list<ValueObject> & args) const477 bool AbsPredicates::CheckParameter(
478     const std::string &methodName, const std::string &field, const std::initializer_list<ValueObject> &args) const
479 {
480     if (field.empty()) {
481         LOG_WARN("%{public}s: string 'field' is empty.", methodName.c_str());
482         return false;
483     }
484     for (auto &arg : args) {
485         if (auto pval = std::get_if<std::string>(&arg.value)) {
486             if ((*pval).empty()) {
487                 LOG_WARN("%{public}s: value is empty.", methodName.c_str());
488                 return false;
489             }
490         }
491     }
492     return true;
493 }
494 
RemoveQuotes(const std::string & source) const495 std::string AbsPredicates::RemoveQuotes(const std::string &source) const
496 {
497     std::string src = source;
498     if (source.empty()) {
499         return source;
500     }
501     src.erase(std::remove(src.begin(), src.end(), '\''), src.end());
502     src.erase(std::remove(src.begin(), src.end(), '\"'), src.end());
503     src.erase(std::remove(src.begin(), src.end(), '`'), src.end());
504     return src;
505 }
506 
CheckIsNeedAnd()507 void AbsPredicates::CheckIsNeedAnd()
508 {
509     if (isNeedAnd) {
510         whereClause += " AND ";
511     } else {
512         isNeedAnd = true;
513     }
514 }
515 
AppendWhereClauseWithInOrNotIn(const std::string & methodName,const std::string & field,const std::vector<std::string> & replaceValues)516 void AbsPredicates::AppendWhereClauseWithInOrNotIn(
517     const std::string &methodName, const std::string &field, const std::vector<std::string> &replaceValues)
518 {
519     whereClause += field + StringUtils::SurroundWithFunction(methodName, ",", replaceValues);
520 }
521 
GetStatement() const522 std::string AbsPredicates::GetStatement()  const
523 {
524     return SqliteSqlBuilder::BuildSqlStringFromPredicates(*this);
525 }
526 
GetWhereClause() const527 std::string AbsPredicates::GetWhereClause() const
528 {
529     return whereClause;
530 }
531 
SetWhereClause(const std::string & whereClause)532 void AbsPredicates::SetWhereClause(const std::string &whereClause)
533 {
534     if (whereClause.empty()) {
535         return;
536     }
537     this->whereClause = whereClause;
538 }
539 
GetWhereArgs() const540 std::vector<std::string> AbsPredicates::GetWhereArgs() const
541 {
542     std::vector<std::string> whereArgs;
543     for (auto &arg : this->bindArgs) {
544         std::string temp;
545         if (!arg.GetString(temp)) {
546             LOG_WARN("No matching type, empty string instead.");
547         }
548         whereArgs.push_back(temp);
549     }
550     return whereArgs;
551 }
552 
SetWhereArgs(const std::vector<std::string> & whereArgs)553 void AbsPredicates::SetWhereArgs(const std::vector<std::string> &whereArgs)
554 {
555     this->bindArgs.clear();
556     std::for_each(whereArgs.begin(), whereArgs.end(), [this](const auto &it) { bindArgs.push_back(ValueObject(it)); });
557 }
558 
GetBindArgs() const559 std::vector<ValueObject> AbsPredicates::GetBindArgs() const
560 {
561     return bindArgs;
562 }
563 
SetBindArgs(const std::vector<ValueObject> & bindArgs)564 void AbsPredicates::SetBindArgs(const std::vector<ValueObject> &bindArgs)
565 {
566     this->bindArgs = bindArgs;
567 }
568 
GetOrder() const569 std::string AbsPredicates::GetOrder() const
570 {
571     return order;
572 }
573 
SetOrder(const std::string & order)574 void AbsPredicates::SetOrder(const std::string &order)
575 {
576     if (order.empty()) {
577         return;
578     }
579     this->order = order;
580 }
581 
GetLimit() const582 int AbsPredicates::GetLimit() const
583 {
584     return limit;
585 }
586 
GetOffset() const587 int AbsPredicates::GetOffset() const
588 {
589     return offset;
590 }
591 
IsDistinct() const592 bool AbsPredicates::IsDistinct() const
593 {
594     return distinct;
595 }
596 
IsSorted() const597 bool AbsPredicates::IsSorted() const
598 {
599     return isSorted;
600 }
601 
GetGroup() const602 std::string AbsPredicates::GetGroup() const
603 {
604     return group;
605 }
606 
GetIndex() const607 std::string AbsPredicates::GetIndex() const
608 {
609     return index;
610 }
611 } // namespace NativeRdb
612 } // namespace OHOS