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