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