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