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