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