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