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