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