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