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