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