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