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