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