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