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