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