• 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  * Configures to match the specified field whose data type is String and the value not contains a wildcard.
260  */
NotGlob(const std::string & field,const std::string & value)261 AbsPredicates *AbsPredicates::NotGlob(const std::string &field, const std::string &value)
262 {
263     if (!CheckParameter("notGlob", field, { value })) {
264         return this;
265     }
266     CheckIsNeedAnd();
267     whereClause += field + " NOT GLOB ? ";
268     bindArgs.push_back(ValueObject(value));
269     return this;
270 }
271 
272 /**
273  * Restricts the value of the field to be unequal to the specified value.
274  */
Between(const std::string & field,const ValueObject & low,const ValueObject & high)275 AbsPredicates *AbsPredicates::Between(const std::string &field, const ValueObject &low, const ValueObject &high)
276 {
277     if (!CheckParameter("between", field, { low, high })) {
278         return this;
279     }
280     hasSpecificField = hasSpecificField || IsSpecificField(field);
281     CheckIsNeedAnd();
282     whereClause += field + " BETWEEN ? AND ? ";
283     bindArgs.push_back(low);
284     bindArgs.push_back(high);
285     return this;
286 }
287 
288 /**
289  * Configures to match the specified field whose data type is String and value is out of a given range.
290  */
NotBetween(const std::string & field,const ValueObject & low,const ValueObject & high)291 AbsPredicates *AbsPredicates::NotBetween(const std::string &field, const ValueObject &low, const ValueObject &high)
292 {
293     if (!CheckParameter("notBetween", field, { low, high })) {
294         return this;
295     }
296     hasSpecificField = hasSpecificField || IsSpecificField(field);
297     CheckIsNeedAnd();
298     whereClause += field + " NOT BETWEEN ? AND ? ";
299     bindArgs.push_back(low);
300     bindArgs.push_back(high);
301     return this;
302 }
303 
304 /**
305  * Restricts the value of the field to be greater than the specified value.
306  */
GreaterThan(const std::string & field,const ValueObject & value)307 AbsPredicates *AbsPredicates::GreaterThan(const std::string &field, const ValueObject &value)
308 {
309     if (!CheckParameter("greaterThan", field, { value })) {
310         return this;
311     }
312     hasSpecificField = hasSpecificField || IsSpecificField(field);
313     CheckIsNeedAnd();
314     whereClause += field + " > ? ";
315     bindArgs.push_back(value);
316     return this;
317 }
318 
319 /**
320  * Restricts the value of the field to be smaller than the specified value.
321  */
LessThan(const std::string & field,const ValueObject & value)322 AbsPredicates *AbsPredicates::LessThan(const std::string &field, const ValueObject &value)
323 {
324     if (!CheckParameter("lessThan", field, { value })) {
325         return this;
326     }
327     hasSpecificField = hasSpecificField || IsSpecificField(field);
328     CheckIsNeedAnd();
329     whereClause += field + " < ? ";
330     bindArgs.push_back(value);
331     return this;
332 }
333 
334 /**
335  * Restricts the value of the field to be greater than or equal to the specified value.
336  */
GreaterThanOrEqualTo(const std::string & field,const ValueObject & value)337 AbsPredicates *AbsPredicates::GreaterThanOrEqualTo(const std::string &field, const ValueObject &value)
338 {
339     if (!CheckParameter("greaterThanOrEqualTo", field, { value })) {
340         return this;
341     }
342     hasSpecificField = hasSpecificField || IsSpecificField(field);
343     CheckIsNeedAnd();
344     whereClause += field + " >= ? ";
345     bindArgs.push_back(value);
346     return this;
347 }
348 
349 /**
350  * Restricts the value of the field to be smaller than or equal to the specified value.
351  */
LessThanOrEqualTo(const std::string & field,const ValueObject & value)352 AbsPredicates *AbsPredicates::LessThanOrEqualTo(const std::string &field, const ValueObject &value)
353 {
354     if (!CheckParameter("greaterThanOrEqualTo", field, { value })) {
355         return this;
356     }
357     hasSpecificField = hasSpecificField || IsSpecificField(field);
358     CheckIsNeedAnd();
359     whereClause += field + " <= ? ";
360     bindArgs.push_back(value);
361     return this;
362 }
363 
364 /**
365  * Restricts the ascending order of the return list. When there are several orders,
366  * the one close to the head has the highest priority.
367  */
OrderByAsc(const std::string & field)368 AbsPredicates *AbsPredicates::OrderByAsc(const std::string &field)
369 {
370     if (!CheckParameter("orderByAsc", field, {})) {
371         return this;
372     }
373     hasSpecificField = hasSpecificField || IsSpecificField(field);
374     if (isSorted) {
375         order += ',';
376     }
377     order += field + " ASC ";
378     isSorted = true;
379     return this;
380 }
381 
382 /**
383  * Restricts the descending order of the return list. When there are several orders,
384  * the one close to the head has the highest priority.
385  */
OrderByDesc(const std::string & field)386 AbsPredicates *AbsPredicates::OrderByDesc(const std::string &field)
387 {
388     if (!CheckParameter("orderByDesc", field, {})) {
389         return this;
390     }
391     hasSpecificField = hasSpecificField || IsSpecificField(field);
392     if (isSorted) {
393         order += ',';
394     }
395     order += field + " DESC ";
396     isSorted = true;
397     return this;
398 }
399 
Distinct()400 AbsPredicates *AbsPredicates::Distinct()
401 {
402     distinct = true;
403     return this;
404 }
405 
406 /**
407  * Restricts the max number of return records.
408  */
Limit(const int limit)409 AbsPredicates *AbsPredicates::Limit(const int limit)
410 {
411     this->limit = (limit <= 0) ? -1 : limit;
412     return this;
413 }
414 
415 /**
416  * Restricts the max number of return records.
417  */
Limit(const int offset,const int limit)418 AbsPredicates *AbsPredicates::Limit(const int offset, const int limit)
419 {
420     return this->Limit(limit)->Offset(offset);
421 }
422 
423 /**
424  * Configures to specify the start position of the returned result.
425  */
Offset(const int offset)426 AbsPredicates *AbsPredicates::Offset(const int offset)
427 {
428     this->offset = (offset < 0) ? -1 : offset;
429     return this;
430 }
431 
432 /**
433  * Configures {@code AbsPredicates} to group query results by specified columns.
434  */
GroupBy(const std::vector<std::string> & fields)435 AbsPredicates *AbsPredicates::GroupBy(const std::vector<std::string> &fields)
436 {
437     if (fields.empty()) {
438         LOG_WARN("GroupBy() fails because fields can't be null.");
439         return this;
440     }
441     for (auto &field : fields) {
442         if (!CheckParameter("GroupBy", field, {})) {
443             return this;
444         }
445         group += field + ",";
446     }
447     size_t pos = group.find_last_of(",");
448     if (pos != group.npos) {
449         group.erase(pos, 1);
450     }
451     return this;
452 }
453 
454 /**
455  * Configures {@code AbsPredicates} to specify the index column.
456  */
IndexedBy(const std::string & indexName)457 AbsPredicates *AbsPredicates::IndexedBy(const std::string &indexName)
458 {
459     if (!CheckParameter("indexedBy", indexName, {})) {
460         return this;
461     }
462     index = RemoveQuotes(indexName);
463     return this;
464 }
465 
In(const std::string & field,const std::vector<std::string> & values)466 AbsPredicates *AbsPredicates::In(const std::string &field, const std::vector<std::string> &values)
467 {
468     std::vector<ValueObject> bindArgs;
469     std::for_each(values.begin(), values.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
470     return In(field, bindArgs);
471 }
472 
473 /**
474  * Configures to match the specified field whose data type is String array and values are within a given range.
475  */
In(const std::string & field,const std::vector<ValueObject> & values)476 AbsPredicates *AbsPredicates::In(const std::string &field, const std::vector<ValueObject> &values)
477 {
478     bool chekParaFlag = CheckParameter("in", field, {});
479     if (!chekParaFlag) {
480         return this;
481     }
482 
483     CheckIsNeedAnd();
484 
485     std::vector<std::string> replaceValues(values.size(), "?");
486     bindArgs.insert(bindArgs.end(), values.begin(), values.end());
487     AppendWhereClauseWithInOrNotIn(" IN ", field, replaceValues);
488     return this;
489 }
490 
NotIn(const std::string & field,const std::vector<std::string> & values)491 AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector<std::string> &values)
492 {
493     std::vector<ValueObject> bindArgs;
494     std::for_each(values.begin(), values.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
495     return NotIn(field, bindArgs);
496 }
497 
498 /**
499  * Configures to match the specified field whose data type is String array and values are out of a given range.
500  */
NotIn(const std::string & field,const std::vector<ValueObject> & values)501 AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector<ValueObject> &values)
502 {
503     bool chekParaFlag = CheckParameter("notIn", field, {});
504     if (!chekParaFlag) {
505         return this;
506     }
507     CheckIsNeedAnd();
508     std::vector<std::string> replaceValues(values.size(), "?");
509     bindArgs.insert(bindArgs.end(), values.begin(), values.end());
510     AppendWhereClauseWithInOrNotIn(" NOT IN ", field, replaceValues);
511     return this;
512 }
513 
Having(const std::string & conditions,const std::vector<ValueObject> & values)514 AbsPredicates *AbsPredicates::Having(const std::string &conditions, const std::vector<ValueObject> &values)
515 {
516     if (!CheckParameter("having", conditions, {})) {
517         return this;
518     }
519     havingClause = conditions;
520     bindArgs.insert(bindArgs.end(), values.begin(), values.end());
521     return this;
522 }
523 
Initial()524 void AbsPredicates::Initial()
525 {
526     distinct = false;
527     isNeedAnd = false;
528     isSorted = false;
529     bindArgs.clear();
530     whereClause.clear();
531     order.clear();
532     group.clear();
533     index.clear();
534     limit = INIT_LIMIT_VALUE;
535     offset = INIT_OFFSET_VALUE;
536 }
537 
538 /**
539  * Check the parameter validity.
540  */
CheckParameter(const std::string & methodName,const std::string & field,const std::initializer_list<ValueObject> & args) const541 bool AbsPredicates::CheckParameter(
542     const std::string &methodName, const std::string &field, const std::initializer_list<ValueObject> &args) const
543 {
544     if (field.empty()) {
545         LOG_WARN("%{public}s: string 'field' is empty.", methodName.c_str());
546         return false;
547     }
548     for (auto &arg : args) {
549         if (auto pval = std::get_if<std::string>(&arg.value)) {
550             if ((*pval).empty()) {
551                 LOG_WARN("%{public}s: value is empty.", methodName.c_str());
552                 return false;
553             }
554         }
555     }
556     return true;
557 }
558 
RemoveQuotes(const std::string & source) const559 std::string AbsPredicates::RemoveQuotes(const std::string &source) const
560 {
561     std::string src = source;
562     if (source.empty()) {
563         return source;
564     }
565     src.erase(std::remove(src.begin(), src.end(), '\''), src.end());
566     src.erase(std::remove(src.begin(), src.end(), '\"'), src.end());
567     src.erase(std::remove(src.begin(), src.end(), '`'), src.end());
568     return src;
569 }
570 
CheckIsNeedAnd()571 void AbsPredicates::CheckIsNeedAnd()
572 {
573     if (isNeedAnd) {
574         whereClause += " AND ";
575     } else {
576         isNeedAnd = true;
577     }
578 }
579 
AppendWhereClauseWithInOrNotIn(const std::string & methodName,const std::string & field,const std::vector<std::string> & replaceValues)580 void AbsPredicates::AppendWhereClauseWithInOrNotIn(
581     const std::string &methodName, const std::string &field, const std::vector<std::string> &replaceValues)
582 {
583     whereClause += field + StringUtils::SurroundWithFunction(methodName, ",", replaceValues);
584 }
585 
GetStatement() const586 std::string AbsPredicates::GetStatement() const
587 {
588     return "";
589 }
590 
GetWhereClause() const591 std::string AbsPredicates::GetWhereClause() const
592 {
593     return whereClause;
594 }
595 
SetWhereClause(const std::string & whereClause)596 void AbsPredicates::SetWhereClause(const std::string &whereClause)
597 {
598     if (whereClause.empty()) {
599         return;
600     }
601     this->whereClause = whereClause;
602 }
603 
GetWhereArgs() const604 std::vector<std::string> AbsPredicates::GetWhereArgs() const
605 {
606     std::vector<std::string> whereArgs;
607     for (auto &arg : this->bindArgs) {
608         std::string temp;
609         if (!arg.GetString(temp)) {
610             LOG_DEBUG("No matching type, empty string instead.");
611         }
612         whereArgs.push_back(temp);
613     }
614     return whereArgs;
615 }
616 
SetWhereArgs(const std::vector<std::string> & whereArgs)617 void AbsPredicates::SetWhereArgs(const std::vector<std::string> &whereArgs)
618 {
619     this->bindArgs.clear();
620     std::for_each(whereArgs.begin(), whereArgs.end(), [this](const auto &it) { bindArgs.push_back(ValueObject(it)); });
621 }
622 
GetBindArgs() const623 std::vector<ValueObject> AbsPredicates::GetBindArgs() const
624 {
625     return bindArgs;
626 }
627 
SetBindArgs(const std::vector<ValueObject> & bindArgs)628 void AbsPredicates::SetBindArgs(const std::vector<ValueObject> &bindArgs)
629 {
630     this->bindArgs = bindArgs;
631 }
632 
GetOrder() const633 std::string AbsPredicates::GetOrder() const
634 {
635     return order;
636 }
637 
SetOrder(const std::string & order)638 void AbsPredicates::SetOrder(const std::string &order)
639 {
640     if (order.empty()) {
641         return;
642     }
643     this->order = order;
644 }
645 
GetLimit() const646 int AbsPredicates::GetLimit() const
647 {
648     return limit;
649 }
650 
GetOffset() const651 int AbsPredicates::GetOffset() const
652 {
653     return offset;
654 }
655 
IsDistinct() const656 bool AbsPredicates::IsDistinct() const
657 {
658     return distinct;
659 }
660 
IsSorted() const661 bool AbsPredicates::IsSorted() const
662 {
663     return isSorted;
664 }
665 
HasSpecificField() const666 bool AbsPredicates::HasSpecificField() const
667 {
668     return hasSpecificField;
669 }
670 
GetGroup() const671 std::string AbsPredicates::GetGroup() const
672 {
673     return group;
674 }
675 
GetIndex() const676 std::string AbsPredicates::GetIndex() const
677 {
678     return index;
679 }
680 
GetHaving() const681 std::string AbsPredicates::GetHaving() const
682 {
683     return havingClause;
684 }
685 } // namespace NativeRdb
686 } // namespace OHOS