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 "QueryHelper"
16  #include "query_helper.h"
17  #include <regex>
18  #include <sstream>
19  #include "data_query.h"
20  #include "device_manager_adapter.h"
21  #include "kvstore_utils.h"
22  #include "log_print.h"
23  #include "types.h"
24  namespace OHOS::DistributedKv {
25  constexpr int QUERY_SKIP_SIZE = 1;
26  constexpr int QUERY_WORD_SIZE = 2;
27  constexpr int MAX_QUERY_LENGTH = 5 * 1024; // Max query string length 5k
28  constexpr int MAX_QUERY_COMPLEXITY = 500;  // Max query complexity 500
29  bool QueryHelper::hasPrefixKey_ = false;
30  std::string QueryHelper::deviceId_;
31  
StringToDbQuery(const std::string & query,bool & isSuccess)32  DistributedDB::Query QueryHelper::StringToDbQuery(const std::string &query, bool &isSuccess)
33  {
34      ZLOGI("query string length:%{public}zu", query.length());
35      DBQuery dbQuery = DBQuery::Select();
36      if (query.empty()) {
37          ZLOGD("Query string is empty.");
38          isSuccess = true;
39          return dbQuery;
40      }
41      if (query.size() > MAX_QUERY_LENGTH) {
42          ZLOGE("Query string is too long.");
43          isSuccess = false;
44          return dbQuery;
45      }
46      deviceId_.clear();
47      hasPrefixKey_ = (query.find(DataQuery::KEY_PREFIX) != std::string::npos);
48      size_t pos = query.find_first_not_of(DataQuery::SPACE);
49      std::string inputTrim = (pos == std::string::npos) ? "" : query.substr(pos);
50      std::regex regex(" ");
51      // regex split string by space
52      std::vector<std::string> words(std::sregex_token_iterator(inputTrim.begin(), inputTrim.end(), regex, -1),
53          std::sregex_token_iterator());
54  
55      if (words.empty()) {
56          ZLOGE("not enough params.");
57          return dbQuery;
58      }
59      int pointer = 0;            // Read pointer starts at 0
60      int end = words.size() - 1; // Read pointer ends at size - 1
61      // Counts how many keywords has been handled
62      for (int count = 0; pointer <= end && count <= MAX_QUERY_COMPLEXITY; ++count) {
63          std::string keyword = words.at(pointer);
64          if (keyword == DataQuery::EQUAL_TO) {
65              isSuccess = HandleEqualTo(words, pointer, end, dbQuery);
66          } else if (keyword == DataQuery::NOT_EQUAL_TO) {
67              isSuccess = HandleNotEqualTo(words, pointer, end, dbQuery);
68          } else if (keyword == DataQuery::GREATER_THAN) {
69              isSuccess = HandleGreaterThan(words, pointer, end, dbQuery);
70          } else if (keyword == DataQuery::LESS_THAN) {
71              isSuccess = HandleLessThan(words, pointer, end, dbQuery);
72          } else if (keyword == DataQuery::GREATER_THAN_OR_EQUAL_TO) {
73              isSuccess = HandleGreaterThanOrEqualTo(words, pointer, end, dbQuery);
74          } else if (keyword == DataQuery::LESS_THAN_OR_EQUAL_TO) {
75              isSuccess = HandleLessThanOrEqualTo(words, pointer, end, dbQuery);
76          } else {
77              isSuccess = Handle(words, pointer, end, dbQuery);
78          }
79          if (!isSuccess) {
80              ZLOGE("Invalid params.");
81              return DBQuery::Select();
82          }
83      }
84      return dbQuery;
85  }
86  
Handle(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)87  bool QueryHelper::Handle(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
88  {
89      std::string keyword = words.at(pointer);
90      if (keyword == DataQuery::IS_NULL) {
91          return HandleIsNull(words, pointer, end, dbQuery);
92      } else if (keyword == DataQuery::IN) {
93          return HandleIn(words, pointer, end, dbQuery);
94      } else if (keyword == DataQuery::NOT_IN) {
95          return HandleNotIn(words, pointer, end, dbQuery);
96      } else if (keyword == DataQuery::LIKE) {
97          return HandleLike(words, pointer, end, dbQuery);
98      } else if (keyword == DataQuery::NOT_LIKE) {
99          return HandleNotLike(words, pointer, end, dbQuery);
100      } else if (keyword == DataQuery::AND) {
101          return HandleAnd(words, pointer, end, dbQuery);
102      } else if (keyword == DataQuery::OR) {
103          return HandleOr(words, pointer, end, dbQuery);
104      } else if (keyword == DataQuery::ORDER_BY_ASC) {
105          return HandleOrderByAsc(words, pointer, end, dbQuery);
106      } else if (keyword == DataQuery::ORDER_BY_DESC) {
107          return HandleOrderByDesc(words, pointer, end, dbQuery);
108      } else if (keyword == DataQuery::ORDER_BY_WRITE_TIME) {
109          return HandleOrderByWriteTime(words, pointer, end, dbQuery);
110      } else if (keyword == DataQuery::LIMIT) {
111          return HandleLimit(words, pointer, end, dbQuery);
112      } else {
113          return HandleExtra(words, pointer, end, dbQuery);
114      }
115  }
116  
HandleExtra(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)117  bool QueryHelper::HandleExtra(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
118  {
119      std::string keyword = words.at(pointer);
120      if (keyword == DataQuery::BEGIN_GROUP) {
121          return HandleBeginGroup(words, pointer, end, dbQuery);
122      } else if (keyword == DataQuery::END_GROUP) {
123          return HandleEndGroup(words, pointer, end, dbQuery);
124      } else if (keyword == DataQuery::KEY_PREFIX) {
125          return HandleKeyPrefix(words, pointer, end, dbQuery);
126      } else if (keyword == DataQuery::IS_NOT_NULL) {
127          return HandleIsNotNull(words, pointer, end, dbQuery);
128      } else if (keyword == DataQuery::DEVICE_ID) {
129          return HandleDeviceId(words, pointer, end, dbQuery);
130      } else if (keyword == DataQuery::SUGGEST_INDEX) {
131          return HandleSetSuggestIndex(words, pointer, end, dbQuery);
132      } else if (keyword == DataQuery::IN_KEYS) {
133          return HandleInKeys(words, pointer, end, dbQuery);
134      }
135      ZLOGE("Invalid keyword.");
136      return false;
137  }
138  
HandleEqualTo(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)139  bool QueryHelper::HandleEqualTo(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
140  {
141      if (pointer + 3 > end) { // This keyword has 3 following params
142          ZLOGE("EqualTo not enough params.");
143          return false;
144      }
145      const std::string &fieldType = words.at(pointer + 1);  // fieldType
146      const std::string &fieldName = words.at(pointer + 2);  // fieldName
147      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
148      if (fieldType == DataQuery::TYPE_INTEGER) {
149          dbQuery.EqualTo(StringToString(fieldName), StringToInt(fieldValue));
150      } else if (fieldType == DataQuery::TYPE_LONG) {
151          dbQuery.EqualTo(StringToString(fieldName), StringToLong(fieldValue));
152      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
153          dbQuery.EqualTo(StringToString(fieldName), StringToDouble(fieldValue));
154      } else if (fieldType == DataQuery::TYPE_BOOLEAN) {
155          dbQuery.EqualTo(StringToString(fieldName), StringToBoolean(fieldValue));
156      } else if (fieldType == DataQuery::TYPE_STRING) {
157          dbQuery.EqualTo(StringToString(fieldName), StringToString(fieldValue));
158      } else {
159          ZLOGE("EqualTo wrong type.");
160          return false;
161      }
162      pointer += 4; // 4 Pointer goes to next keyword
163      return true;
164  }
165  
HandleNotEqualTo(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)166  bool QueryHelper::HandleNotEqualTo(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
167  {
168      if (pointer + 3 > end) { // This keyword has 3 following params
169          ZLOGE("NotEqualTo not enough params.");
170          return false;
171      }
172      const std::string &fieldType = words.at(pointer + 1);  // fieldType
173      const std::string &fieldName = words.at(pointer + 2);  // fieldName
174      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
175      if (fieldType == DataQuery::TYPE_INTEGER) {
176          dbQuery.NotEqualTo(StringToString(fieldName), StringToInt(fieldValue));
177      } else if (fieldType == DataQuery::TYPE_LONG) {
178          dbQuery.NotEqualTo(StringToString(fieldName), StringToLong(fieldValue));
179      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
180          dbQuery.NotEqualTo(StringToString(fieldName), StringToDouble(fieldValue));
181      } else if (fieldType == DataQuery::TYPE_BOOLEAN) {
182          dbQuery.NotEqualTo(StringToString(fieldName), StringToBoolean(fieldValue));
183      } else if (fieldType == DataQuery::TYPE_STRING) {
184          dbQuery.NotEqualTo(StringToString(fieldName), StringToString(fieldValue));
185      } else {
186          ZLOGE("NotEqualTo wrong type.");
187          return false;
188      }
189      pointer += 4; // 4 Pointer goes to next keyword
190      return true;
191  }
192  
HandleGreaterThan(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)193  bool QueryHelper::HandleGreaterThan(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
194  {
195      if (pointer + 3 > end) { // This keyword has 3 following params
196          ZLOGE("GreaterThan not enough params.");
197          return false;
198      }
199      const std::string &fieldType = words.at(pointer + 1);  // fieldType
200      const std::string &fieldName = words.at(pointer + 2);  // fieldName
201      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
202      if (fieldType == DataQuery::TYPE_INTEGER) {
203          dbQuery.GreaterThan(StringToString(fieldName), StringToInt(fieldValue));
204      } else if (fieldType == DataQuery::TYPE_LONG) {
205          dbQuery.GreaterThan(StringToString(fieldName), StringToLong(fieldValue));
206      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
207          dbQuery.GreaterThan(StringToString(fieldName), StringToDouble(fieldValue));
208      } else if (fieldType == DataQuery::TYPE_STRING) {
209          dbQuery.GreaterThan(StringToString(fieldName), StringToString(fieldValue));
210      } else {
211          ZLOGE("GreaterThan wrong type.");
212          return false;
213      }
214      pointer += 4; // 4 Pointer goes to next keyword
215      return true;
216  }
217  
HandleLessThan(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)218  bool QueryHelper::HandleLessThan(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
219  {
220      if (pointer + 3 > end) { // This keyword has 3 following params
221          ZLOGE("LessThan not enough params.");
222          return false;
223      }
224      const std::string &fieldType = words.at(pointer + 1);  // fieldType
225      const std::string &fieldName = words.at(pointer + 2);  // fieldName
226      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
227      if (fieldType == DataQuery::TYPE_INTEGER) {
228          dbQuery.LessThan(StringToString(fieldName), StringToInt(fieldValue));
229      } else if (fieldType == DataQuery::TYPE_LONG) {
230          dbQuery.LessThan(StringToString(fieldName), StringToLong(fieldValue));
231      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
232          dbQuery.LessThan(StringToString(fieldName), StringToDouble(fieldValue));
233      } else if (fieldType == DataQuery::TYPE_STRING) {
234          dbQuery.LessThan(StringToString(fieldName), StringToString(fieldValue));
235      } else {
236          ZLOGE("LessThan wrong type.");
237          return false;
238      }
239      pointer += 4; // 4 Pointer goes to next keyword
240      return true;
241  }
242  
HandleGreaterThanOrEqualTo(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)243  bool QueryHelper::HandleGreaterThanOrEqualTo(
244      const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
245  {
246      if (pointer + 3 > end) { // This keyword has 3 following params
247          ZLOGE("GreaterThanOrEqualTo not enough params.");
248          return false;
249      }
250      const std::string &fieldType = words.at(pointer + 1);  // fieldType
251      const std::string &fieldName = words.at(pointer + 2);  // fieldName
252      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
253      if (fieldType == DataQuery::TYPE_INTEGER) {
254          dbQuery.GreaterThanOrEqualTo(StringToString(fieldName), StringToInt(fieldValue));
255      } else if (fieldType == DataQuery::TYPE_LONG) {
256          dbQuery.GreaterThanOrEqualTo(StringToString(fieldName), StringToLong(fieldValue));
257      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
258          dbQuery.GreaterThanOrEqualTo(StringToString(fieldName), StringToDouble(fieldValue));
259      } else if (fieldType == DataQuery::TYPE_STRING) {
260          dbQuery.GreaterThanOrEqualTo(StringToString(fieldName), StringToString(fieldValue));
261      } else {
262          ZLOGE("GreaterThanOrEqualTo wrong type.");
263          return false;
264      }
265      pointer += 4; // 4 Pointer goes to next keyword
266      return true;
267  }
268  
HandleLessThanOrEqualTo(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)269  bool QueryHelper::HandleLessThanOrEqualTo(
270      const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
271  {
272      if (pointer + 3 > end) { // This keyword has 3 following params
273          ZLOGE("LessThanOrEqualTo not enough params.");
274          return false;
275      }
276      const std::string &fieldType = words.at(pointer + 1);  // fieldType
277      const std::string &fieldName = words.at(pointer + 2);  // fieldName
278      const std::string &fieldValue = words.at(pointer + 3); // fieldValue
279      if (fieldType == DataQuery::TYPE_INTEGER) {
280          dbQuery.LessThanOrEqualTo(StringToString(fieldName), StringToInt(fieldValue));
281      } else if (fieldType == DataQuery::TYPE_LONG) {
282          dbQuery.LessThanOrEqualTo(StringToString(fieldName), StringToLong(fieldValue));
283      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
284          dbQuery.LessThanOrEqualTo(StringToString(fieldName), StringToDouble(fieldValue));
285      } else if (fieldType == DataQuery::TYPE_STRING) {
286          dbQuery.LessThanOrEqualTo(StringToString(fieldName), StringToString(fieldValue));
287      } else {
288          ZLOGE("LessThanOrEqualTo wrong type.");
289          return false;
290      }
291      pointer += 4; // 4 Pointer goes to next keyword
292      return true;
293  }
294  
HandleIsNull(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)295  bool QueryHelper::HandleIsNull(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
296  {
297      if (pointer + 1 > end) { // This keyword has 1 following params
298          ZLOGE("IsNull not enough params.");
299          return false;
300      }
301      const std::string &fieldName = words.at(pointer + 1); // fieldName
302      dbQuery.IsNull(StringToString(fieldName));
303      pointer += 2; // 2 Pointer goes to next keyword
304      return true;
305  }
306  
HandleIsNotNull(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)307  bool QueryHelper::HandleIsNotNull(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
308  {
309      if (pointer + 1 > end) { // This keyword has 1 following params
310          ZLOGE("IsNotNull not enough params.");
311          return false;
312      }
313      const std::string &fieldName = words.at(pointer + 1); // fieldName
314      dbQuery.IsNotNull(StringToString(fieldName));
315      pointer += 2; // 2 Pointer goes to next keyword
316      return true;
317  }
318  
HandleIn(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)319  bool QueryHelper::HandleIn(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
320  {
321      //       | <-------------------------4---------------------------->|
322      // words [ DataQuery::IN, fieldType, fieldName, DataQuery::START_IN, ...valueList, DataQuery::END_IN ]
323      // index [ -------0-----, ----1----, ----2----, ---------3---------,      ...    , ---------n--------]
324      //                ^                                                                                  ^
325      //                |                                                                                  |
326      //              pointer                                                                             end
327      // first fieldValue, or END if list is empty
328      if (pointer + 4 > end || words.at(pointer + 3) != DataQuery::START_IN) {
329          ZLOGE("In not enough params.");
330          return false;
331      }
332      const std::string &fieldType = words.at(pointer + 1); // fieldType
333      const std::string &fieldName = words.at(pointer + 2); // fieldName
334      int elementPointer = pointer + 4;                     // first fieldValue, or END if list is empty
335      if (fieldType == DataQuery::TYPE_INTEGER) {
336          const std::vector<int> intValueList = GetIntegerList(words, elementPointer, end);
337          dbQuery.In(StringToString(fieldName), intValueList);
338      } else if (fieldType == DataQuery::TYPE_LONG) {
339          const std::vector<int64_t> longValueList = GetLongList(words, elementPointer, end);
340          dbQuery.In(StringToString(fieldName), longValueList);
341      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
342          const std::vector<double> doubleValueList = GetDoubleList(words, elementPointer, end);
343          dbQuery.In(StringToString(fieldName), doubleValueList);
344      } else if (fieldType == DataQuery::TYPE_STRING) {
345          const std::vector<std::string> stringValueList = GetStringList(words, elementPointer, end);
346          dbQuery.In(StringToString(fieldName), stringValueList);
347      } else {
348          ZLOGE("In wrong type.");
349          return false;
350      }
351      pointer = elementPointer + 1; // Pointer goes to next keyword
352      return true;
353  }
354  
HandleNotIn(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)355  bool QueryHelper::HandleNotIn(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
356  {
357      //       |<--------------------------4-------------------------------->|
358      // words [ DataQuery::NOT_IN, fieldType, fieldName, DataQuery::START_IN, ...valueList, DataQuery::END_IN ]
359      // index [ --------0--------, ----1----, ----2----, ---------3---------,      ...    , ---------n--------]
360      //                 ^                                                                                     ^
361      //                 |                                                                                     |
362      //               pointer                                                                                end
363      // first fieldValue, or END if list is empty
364      if (pointer + 4 > end || words.at(pointer + 3) != DataQuery::START_IN) {
365          ZLOGE("NotIn not enough params.");
366          return false;
367      }
368      const std::string &fieldType = words.at(pointer + 1); // fieldType
369      const std::string &fieldName = words.at(pointer + 2); // fieldName
370      int elementPointer = pointer + 4;                     // first fieldValue, or END if list is empty
371      if (fieldType == DataQuery::TYPE_INTEGER) {
372          const std::vector<int> intValueList = GetIntegerList(words, elementPointer, end);
373          dbQuery.NotIn(StringToString(fieldName), intValueList);
374      } else if (fieldType == DataQuery::TYPE_LONG) {
375          const std::vector<int64_t> longValueList = GetLongList(words, elementPointer, end);
376          dbQuery.NotIn(StringToString(fieldName), longValueList);
377      } else if (fieldType == DataQuery::TYPE_DOUBLE) {
378          const std::vector<double> doubleValueList = GetDoubleList(words, elementPointer, end);
379          dbQuery.NotIn(StringToString(fieldName), doubleValueList);
380      } else if (fieldType == DataQuery::TYPE_STRING) {
381          const std::vector<std::string> stringValueList = GetStringList(words, elementPointer, end);
382          dbQuery.NotIn(StringToString(fieldName), stringValueList);
383      } else {
384          ZLOGE("NotIn wrong type.");
385          return false;
386      }
387      pointer = elementPointer + 1; // Pointer goes to next keyword
388      return true;
389  }
390  
HandleLike(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)391  bool QueryHelper::HandleLike(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
392  {
393      if (pointer + 2 > end) { // This keyword has 2 following params
394          ZLOGE("Like not enough params.");
395          return false;
396      }
397      const std::string &fieldName = words.at(pointer + 1);  // fieldName
398      const std::string &fieldValue = words.at(pointer + 2); // fieldValue
399      dbQuery.Like(StringToString(fieldName), StringToString(fieldValue));
400      pointer += 3; // 3 Pointer goes to next keyword
401      return true;
402  }
403  
HandleNotLike(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)404  bool QueryHelper::HandleNotLike(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
405  {
406      if (pointer + 2 > end) { // This keyword has 2 following params
407          ZLOGE("NotLike not enough params.");
408          return false;
409      }
410      const std::string &fieldName = words.at(pointer + 1);  // fieldName
411      const std::string &fieldValue = words.at(pointer + 2); // fieldValue
412      dbQuery.NotLike(StringToString(fieldName), StringToString(fieldValue));
413      pointer += 3; // 3 Pointer goes to next keyword
414      return true;
415  }
416  
HandleAnd(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)417  bool QueryHelper::HandleAnd(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
418  {
419      dbQuery.And();
420      pointer += 1; // Pointer goes to next keyword
421      return true;
422  }
423  
HandleOr(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)424  bool QueryHelper::HandleOr(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
425  {
426      dbQuery.Or();
427      pointer += 1; // Pointer goes to next keyword
428      return true;
429  }
430  
HandleOrderByAsc(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)431  bool QueryHelper::HandleOrderByAsc(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
432  {
433      if (pointer + 1 > end) { // This keyword has 1 following params
434          ZLOGE("OrderByAsc not enough params.");
435          return false;
436      }
437      const std::string &fieldName = words.at(pointer + 1); // fieldName
438      dbQuery.OrderBy(StringToString(fieldName), true);
439      pointer += 2; // 2 Pointer goes to next keyword
440      return true;
441  }
442  
HandleOrderByDesc(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)443  bool QueryHelper::HandleOrderByDesc(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
444  {
445      if (pointer + 1 > end) { // This keyword has 1 following params
446          ZLOGE("OrderByDesc not enough params.");
447          return false;
448      }
449      const std::string &fieldName = words.at(pointer + 1); // fieldName
450      dbQuery.OrderBy(StringToString(fieldName), false);
451      pointer += 2; // 2 Pointer goes to next keyword
452      return true;
453  }
454  
HandleOrderByWriteTime(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)455  bool QueryHelper::HandleOrderByWriteTime(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
456  {
457      if (pointer + 1 > end) { // This keyword has 1 following params
458          ZLOGE("HandleOrderByWriteTime not enough params.");
459          return false;
460      }
461      const std::string isAsc = words.at(pointer + 1); // isASC
462  
463      dbQuery.OrderByWriteTime(isAsc == DataQuery::IS_ASC);
464      pointer += 2; // 2 Pointer goes to next keyword
465      return true;
466  }
467  
HandleLimit(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)468  bool QueryHelper::HandleLimit(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
469  {
470      if (pointer + 2 > end) { // This keyword has 2 following params
471          ZLOGE("Limit not enough params.");
472          return false;
473      }
474      const int number = StringToInt(words.at(pointer + 1)); // number
475      const int offset = StringToInt(words.at(pointer + 2)); // offset
476      dbQuery.Limit(number, offset);
477      pointer += 3; // 3 Pointer goes to next keyword
478      return true;
479  }
480  
HandleBeginGroup(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)481  bool QueryHelper::HandleBeginGroup(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
482  {
483      dbQuery.BeginGroup();
484      pointer += 1; // Pointer goes to next keyword
485      return true;
486  }
487  
HandleEndGroup(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)488  bool QueryHelper::HandleEndGroup(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
489  {
490      dbQuery.EndGroup();
491      pointer += 1; // Pointer goes to next keyword
492      return true;
493  }
494  
HandleKeyPrefix(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)495  bool QueryHelper::HandleKeyPrefix(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
496  {
497      if (pointer + 1 > end) { // This keyword has 1 following params
498          ZLOGE("KeyPrefix not enough params.");
499          return false;
500      }
501      const std::string &prefix = deviceId_ + StringToString(words.at(pointer + 1)); // prefix
502      const std::vector<uint8_t> prefixVector(prefix.begin(), prefix.end());
503      dbQuery.PrefixKey(prefixVector);
504      pointer += 2; // 2 Pointer goes to next keyword
505      return true;
506  }
507  
HandleInKeys(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)508  bool QueryHelper::HandleInKeys(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
509  {
510      // pointer points at keyword "IN_KEYS", (pointer + 1) points at keyword "START_IN"
511      int startInOffSet = pointer + 1;
512      int queryLen = end - pointer;
513      if (queryLen < 2 || words.at(startInOffSet) != DataQuery::START_IN) { // This keyword has at least 2 params
514          ZLOGE("In not enough params.");
515          return false;
516      }
517      int inkeyOffSet = startInOffSet + 1; // inkeyOffSet points at the first inkey value
518      const std::vector<std::string> inKeys = GetStringList(words, inkeyOffSet, end);
519      std::set<std::vector<uint8_t>> inDbKeys;
520      for (const std::string &inKey : inKeys) {
521          ZLOGI("inKey=%{public}s", inKey.c_str());
522          std::vector<uint8_t> dbKey;
523          dbKey.assign(inKey.begin(), inKey.end());
524          inDbKeys.insert(dbKey);
525      }
526      int size = inDbKeys.size();
527      ZLOGI("size of inKeys=%{public}d", size);
528      dbQuery.InKeys(inDbKeys);
529      int endOffSet = inkeyOffSet;
530      pointer = endOffSet + 1; // endOffSet points at keyword "END", Pointer goes to next keyword
531      return true;
532  }
533  
HandleSetSuggestIndex(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)534  bool QueryHelper::HandleSetSuggestIndex(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
535  {
536      if (pointer + QUERY_SKIP_SIZE > end) {
537          ZLOGE("HandleSetSuggestIndex not enough params.");
538          return false;
539      }
540      std::string index = StringToString(words.at(pointer + QUERY_SKIP_SIZE));
541      dbQuery.SuggestIndex(index);
542      pointer += QUERY_WORD_SIZE;
543      return true;
544  }
545  
HandleDeviceId(const std::vector<std::string> & words,int & pointer,int end,DBQuery & dbQuery)546  bool QueryHelper::HandleDeviceId(const std::vector<std::string> &words, int &pointer, int end, DBQuery &dbQuery)
547  {
548      if (pointer + 1 > end) { // This keyword has 1 following params
549          ZLOGE("DeviceId not enough params.");
550          return false;
551      }
552      deviceId_ = StringToString(words.at(pointer + 1)); // deviceId
553      ZLOGI("query devId string length:%zu", deviceId_.length());
554      deviceId_ = DistributedData::DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(deviceId_); // convert to UUId
555      ZLOGI("query converted devId string length:%zu", deviceId_.length());
556      if (!hasPrefixKey_) {
557          ZLOGD("DeviceId as the only prefixKey.");
558          const std::vector<uint8_t> prefixVector(deviceId_.begin(), deviceId_.end());
559          dbQuery.PrefixKey(prefixVector);
560      } else {
561          ZLOGD("Join deviceId with user specified prefixkey later.");
562      }
563      pointer += 2; // 2 Pointer goes to next keyword
564      return true;
565  }
566  
StringToInt(const std::string & word)567  int QueryHelper::StringToInt(const std::string &word)
568  {
569      int result;
570      std::istringstream(word) >> result;
571      return result;
572  }
573  
StringToLong(const std::string & word)574  int64_t QueryHelper::StringToLong(const std::string &word)
575  {
576      int64_t result;
577      std::istringstream(word) >> result;
578      return result;
579  }
580  
StringToDouble(const std::string & word)581  double QueryHelper::StringToDouble(const std::string &word)
582  {
583      double result;
584      std::istringstream(word) >> result;
585      return result;
586  }
587  
StringToBoolean(const std::string & word)588  bool QueryHelper::StringToBoolean(const std::string &word)
589  {
590      if (word == DataQuery::VALUE_TRUE) {
591          return true;
592      } else if (word == DataQuery::VALUE_FALSE) {
593          return false;
594      } else {
595          ZLOGE("StringToBoolean wrong value.");
596          return false;
597      }
598  }
599  
StringToString(const std::string & word)600  std::string QueryHelper::StringToString(const std::string &word)
601  {
602      std::string result = word;
603      if (result.compare(DataQuery::EMPTY_STRING) == 0) {
604          result = "";
605          return result;
606      }
607      size_t index = 0; // search from the beginning of the string
608      while (true) {
609          index = result.find(DataQuery::SPACE_ESCAPE, index);
610          if (index == std::string::npos) {
611              break;
612          }
613          result.replace(index, 2, DataQuery::SPACE); // 2 chars to be replaced
614          index += 1;                                 // replaced with 1 char, keep searching the remaining string
615      }
616      index = 0; // search from the beginning of the string
617      while (true) {
618          index = result.find(DataQuery::SPECIAL_ESCAPE, index);
619          if (index == std::string::npos) {
620              break;
621          }
622          result.replace(index, 3, DataQuery::SPECIAL); // 3 chars to be replaced
623          index += 1;                                   // replaced with 1 char, keep searching the remaining string
624      }
625      return result;
626  }
627  
GetIntegerList(const std::vector<std::string> & words,int & elementPointer,int end)628  std::vector<int> QueryHelper::GetIntegerList(const std::vector<std::string> &words, int &elementPointer, int end)
629  {
630      std::vector<int> valueList;
631      bool isEndFound = false;
632      while (elementPointer <= end) {
633          if (words.at(elementPointer) == DataQuery::END_IN) {
634              isEndFound = true;
635              break;
636          }
637          valueList.push_back(StringToInt(words.at(elementPointer)));
638          elementPointer++;
639      }
640      if (isEndFound) {
641          return valueList;
642      } else {
643          ZLOGE("GetIntegerList failed.");
644          return std::vector<int>();
645      }
646  }
647  
GetLongList(const std::vector<std::string> & words,int & elementPointer,int end)648  std::vector<int64_t> QueryHelper::GetLongList(const std::vector<std::string> &words, int &elementPointer, int end)
649  {
650      std::vector<int64_t> valueList;
651      bool isEndFound = false;
652      while (elementPointer <= end) {
653          if (words.at(elementPointer) == DataQuery::END_IN) {
654              isEndFound = true;
655              break;
656          }
657          valueList.push_back(StringToLong(words.at(elementPointer)));
658          elementPointer++;
659      }
660      if (isEndFound) {
661          return valueList;
662      } else {
663          ZLOGE("GetLongList failed.");
664          return std::vector<int64_t>();
665      }
666  }
667  
GetDoubleList(const std::vector<std::string> & words,int & elementPointer,int end)668  std::vector<double> QueryHelper::GetDoubleList(const std::vector<std::string> &words, int &elementPointer, int end)
669  {
670      std::vector<double> valueList;
671      bool isEndFound = false;
672      while (elementPointer <= end) {
673          if (words.at(elementPointer) == DataQuery::END_IN) {
674              isEndFound = true;
675              break;
676          }
677          valueList.push_back(StringToDouble(words.at(elementPointer)));
678          elementPointer++;
679      }
680      if (isEndFound) {
681          return valueList;
682      } else {
683          ZLOGE("GetDoubleList failed.");
684          return std::vector<double>();
685      }
686  }
687  
GetStringList(const std::vector<std::string> & words,int & elementPointer,int end)688  std::vector<std::string> QueryHelper::GetStringList(const std::vector<std::string> &words, int &elementPointer, int end)
689  {
690      std::vector<std::string> valueList;
691      bool isEndFound = false;
692      while (elementPointer <= end) {
693          if (words.at(elementPointer) == DataQuery::END_IN) {
694              isEndFound = true;
695              break;
696          }
697          valueList.push_back(StringToString(words.at(elementPointer)));
698          elementPointer++;
699      }
700      if (isEndFound) {
701          return valueList;
702      } else {
703          ZLOGE("GetStringList failed.");
704          return std::vector<std::string>();
705      }
706  }
707  } // namespace OHOS::DistributedKv
708