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 #include "query_expression.h"
16 #include "log_print.h"
17 #include "schema_utils.h"
18 #include "db_errno.h"
19
20 namespace DistributedDB {
21 namespace {
22 const int MAX_OPR_TIMES = 256;
23 } // namespace
24
AssemblyQueryInfo(const QueryObjType queryOperType,const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values,bool isNeedFieldPath=true)25 void QueryExpression::AssemblyQueryInfo(const QueryObjType queryOperType, const std::string& field,
26 const QueryValueType type, const std::vector<FieldValue> &values, bool isNeedFieldPath = true)
27 {
28 if (useFromTable_) {
29 expressions_[fromTable_].AssemblyQueryInfo(queryOperType, field, type, values, isNeedFieldPath);
30 SetNotSupportIfNeed(queryOperType);
31 return;
32 }
33 if (!tables_.empty()) {
34 validStatus_ = -E_NOT_SUPPORT;
35 }
36 if (queryInfo_.size() > MAX_OPR_TIMES) {
37 SetErrFlag(false);
38 LOGE("Operate too much times!");
39 return;
40 }
41
42 if (!GetErrFlag()) {
43 LOGE("Illegal data node!");
44 return;
45 }
46
47 FieldPath outPath;
48 if (isNeedFieldPath) {
49 if (SchemaUtils::ParseAndCheckFieldPath(field, outPath) != E_OK) {
50 SetErrFlag(false);
51 LOGE("Field path illegal!");
52 return;
53 }
54 }
55 std::string formatedField;
56 if (isTableNameSpecified_) { // remove '$.' prefix in relational query
57 for (auto it = outPath.begin(); it < outPath.end(); ++it) {
58 if (it != outPath.begin()) {
59 formatedField += ".";
60 }
61 formatedField += *it;
62 }
63 } else {
64 formatedField = field;
65 }
66 if (!queryInfo_.empty() && queryInfo_.back().operFlag == queryOperType) {
67 validStatus_ = -E_INVALID_ARGS;
68 }
69 queryInfo_.emplace_back(QueryObjNode{queryOperType, formatedField, type, values});
70 }
71
QueryExpression()72 QueryExpression::QueryExpression()
73 : errFlag_(true),
74 tableName_("sync_data"), // default kv type store table name
75 isTableNameSpecified_(false) // default no specify for kv type store table name
76 {}
77
EqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)78 void QueryExpression::EqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
79 {
80 std::vector<FieldValue> fieldValues{value};
81 AssemblyQueryInfo(QueryObjType::EQUALTO, field, type, fieldValues);
82 }
83
NotEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)84 void QueryExpression::NotEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
85 {
86 std::vector<FieldValue> fieldValues{value};
87 AssemblyQueryInfo(QueryObjType::NOT_EQUALTO, field, type, fieldValues);
88 }
89
GreaterThan(const std::string & field,const QueryValueType type,const FieldValue & value)90 void QueryExpression::GreaterThan(const std::string& field, const QueryValueType type, const FieldValue &value)
91 {
92 if (type == QueryValueType::VALUE_TYPE_BOOL) {
93 LOGD("Prohibit the use of bool for comparison!");
94 SetErrFlag(false);
95 }
96 std::vector<FieldValue> fieldValues{value};
97 AssemblyQueryInfo(QueryObjType::GREATER_THAN, field, type, fieldValues);
98 }
99
LessThan(const std::string & field,const QueryValueType type,const FieldValue & value)100 void QueryExpression::LessThan(const std::string& field, const QueryValueType type, const FieldValue &value)
101 {
102 if (type == QueryValueType::VALUE_TYPE_BOOL) {
103 LOGD("Prohibit the use of bool for comparison!");
104 SetErrFlag(false);
105 }
106 std::vector<FieldValue> fieldValues{value};
107 AssemblyQueryInfo(QueryObjType::LESS_THAN, field, type, fieldValues);
108 }
109
GreaterThanOrEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)110 void QueryExpression::GreaterThanOrEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
111 {
112 if (type == QueryValueType::VALUE_TYPE_BOOL) {
113 LOGD("Prohibit the use of bool for comparison!");
114 SetErrFlag(false);
115 }
116 std::vector<FieldValue> fieldValues{value};
117 AssemblyQueryInfo(QueryObjType::GREATER_THAN_OR_EQUALTO, field, type, fieldValues);
118 }
119
LessThanOrEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)120 void QueryExpression::LessThanOrEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
121 {
122 if (type == QueryValueType::VALUE_TYPE_BOOL) {
123 LOGD("Prohibit the use of bool for comparison!");
124 SetErrFlag(false);
125 }
126 std::vector<FieldValue> fieldValues{value};
127 AssemblyQueryInfo(QueryObjType::LESS_THAN_OR_EQUALTO, field, type, fieldValues);
128 }
129
OrderBy(const std::string & field,bool isAsc)130 void QueryExpression::OrderBy(const std::string& field, bool isAsc)
131 {
132 FieldValue fieldValue;
133 fieldValue.boolValue = isAsc;
134 std::vector<FieldValue> fieldValues{fieldValue};
135 AssemblyQueryInfo(QueryObjType::ORDERBY, field, QueryValueType::VALUE_TYPE_BOOL, fieldValues);
136 }
137
Like(const std::string & field,const std::string & value)138 void QueryExpression::Like(const std::string& field, const std::string &value)
139 {
140 FieldValue fieldValue;
141 fieldValue.stringValue = value;
142 std::vector<FieldValue> fieldValues{fieldValue};
143 AssemblyQueryInfo(QueryObjType::LIKE, field, QueryValueType::VALUE_TYPE_STRING, fieldValues);
144 }
145
NotLike(const std::string & field,const std::string & value)146 void QueryExpression::NotLike(const std::string& field, const std::string &value)
147 {
148 FieldValue fieldValue;
149 fieldValue.stringValue = value;
150 std::vector<FieldValue> fieldValues{fieldValue};
151 AssemblyQueryInfo(QueryObjType::NOT_LIKE, field, QueryValueType::VALUE_TYPE_STRING, fieldValues);
152 }
153
Limit(int number,int offset)154 void QueryExpression::Limit(int number, int offset)
155 {
156 FieldValue fieldNumber;
157 fieldNumber.integerValue = number;
158 FieldValue fieldOffset;
159 fieldOffset.integerValue = offset;
160 std::vector<FieldValue> fieldValues{fieldNumber, fieldOffset};
161 AssemblyQueryInfo(QueryObjType::LIMIT, std::string(), QueryValueType::VALUE_TYPE_INTEGER, fieldValues, false);
162 }
163
IsNull(const std::string & field)164 void QueryExpression::IsNull(const std::string& field)
165 {
166 AssemblyQueryInfo(QueryObjType::IS_NULL, field, QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>());
167 }
168
IsNotNull(const std::string & field)169 void QueryExpression::IsNotNull(const std::string& field)
170 {
171 AssemblyQueryInfo(QueryObjType::IS_NOT_NULL, field, QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>());
172 }
173
In(const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values)174 void QueryExpression::In(const std::string& field, const QueryValueType type, const std::vector<FieldValue> &values)
175 {
176 AssemblyQueryInfo(QueryObjType::IN, field, type, values);
177 }
178
NotIn(const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values)179 void QueryExpression::NotIn(const std::string& field, const QueryValueType type, const std::vector<FieldValue> &values)
180 {
181 AssemblyQueryInfo(QueryObjType::NOT_IN, field, type, values);
182 }
183
And()184 void QueryExpression::And()
185 {
186 AssemblyQueryInfo(QueryObjType::AND, std::string(), QueryValueType::VALUE_TYPE_NULL,
187 std::vector<FieldValue>(), false);
188 }
189
Or()190 void QueryExpression::Or()
191 {
192 AssemblyQueryInfo(QueryObjType::OR, std::string(), QueryValueType::VALUE_TYPE_NULL,
193 std::vector<FieldValue>(), false);
194 }
195
QueryByPrefixKey(const std::vector<uint8_t> & key)196 void QueryExpression::QueryByPrefixKey(const std::vector<uint8_t> &key)
197 {
198 if (useFromTable_) {
199 expressions_[fromTable_].QueryByPrefixKey(key);
200 validStatus_ = -E_NOT_SUPPORT;
201 return;
202 }
203 SetNotSupportIfFromTables();
204 queryInfo_.emplace_front(QueryObjNode{QueryObjType::QUERY_BY_KEY_PREFIX, std::string(),
205 QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
206 prefixKey_ = key;
207 }
208
QueryByKeyRange(const std::vector<uint8_t> & keyBegin,const std::vector<uint8_t> & keyEnd)209 void QueryExpression::QueryByKeyRange(const std::vector<uint8_t> &keyBegin, const std::vector<uint8_t> &keyEnd)
210 {
211 if (useFromTable_) {
212 expressions_[fromTable_].QueryByKeyRange(keyBegin, keyEnd);
213 validStatus_ = -E_NOT_SUPPORT;
214 return;
215 }
216 SetNotSupportIfFromTables();
217 queryInfo_.emplace_front(QueryObjNode{QueryObjType::KEY_RANGE, std::string(),
218 QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
219 beginKey_ = keyBegin;
220 endKey_ = keyEnd;
221 }
222
SetAssetsOnlyValidStatusIfNeed(int status)223 void QueryExpression::SetAssetsOnlyValidStatusIfNeed(int status)
224 {
225 if (validStatusForAssetsOnly_ != E_OK && validStatusForAssetsOnly_ == -E_INVALID_ARGS) {
226 return;
227 }
228 validStatusForAssetsOnly_ = status;
229 }
230
QueryAssetsOnly(const AssetsMap & assets)231 void QueryExpression::QueryAssetsOnly(const AssetsMap &assets)
232 {
233 isAssetsOnly_ = true;
234 if (useFromTable_) {
235 expressions_[fromTable_].QueryAssetsOnly(assets);
236 SetAssetsOnlyValidStatusIfNeed(expressions_[fromTable_].GetExpressionStatusForAssetsOnly());
237 return;
238 }
239 if (queryInfo_.empty()) {
240 LOGE("[QueryExpression] the QueryAssetsOnly option must be connected with And.");
241 SetAssetsOnlyValidStatusIfNeed(-E_INVALID_ARGS);
242 return;
243 } else if (queryInfo_.back().operFlag != QueryObjType::AND) {
244 LOGE("[QueryExpression] the QueryAssetsOnly option must be connected with And.");
245 SetAssetsOnlyValidStatusIfNeed(-E_INVALID_ARGS);
246 return;
247 } else {
248 queryInfo_.pop_back();
249 }
250 if (assetsGroupMap_.find(groupNum_) != assetsGroupMap_.end()) {
251 LOGE("[QueryExpression]assets only already set!");
252 SetAssetsOnlyValidStatusIfNeed(-E_NOT_SUPPORT);
253 return;
254 }
255 if (assets.empty()) {
256 LOGE("[QueryExpression]assets map can not be empty!");
257 SetAssetsOnlyValidStatusIfNeed(-E_NOT_SUPPORT);
258 return;
259 }
260 for (const auto &item : assets) {
261 if (item.second.empty() && item.first.empty()) {
262 LOGE("[QueryExpression]assets filed or asset name can not be empty!");
263 SetAssetsOnlyValidStatusIfNeed(-E_NOT_SUPPORT);
264 return;
265 }
266 }
267 assetsGroupMap_[groupNum_] = assets;
268 for (uint32_t i = 0; i <= groupNum_; i++) {
269 if (assetsGroupMap_.find(i) == assetsGroupMap_.end()) {
270 LOGE("[QueryExpression]asset group " PRIu32 " not found, may be AssetsOnly interface use in wrong way.", i);
271 SetAssetsOnlyValidStatusIfNeed(-E_NOT_SUPPORT);
272 return;
273 }
274 }
275 }
276
QueryBySuggestIndex(const std::string & indexName)277 void QueryExpression::QueryBySuggestIndex(const std::string &indexName)
278 {
279 if (useFromTable_) {
280 expressions_[fromTable_].QueryBySuggestIndex(indexName);
281 validStatus_ = -E_NOT_SUPPORT;
282 return;
283 }
284 SetNotSupportIfFromTables();
285 queryInfo_.emplace_back(QueryObjNode{QueryObjType::SUGGEST_INDEX, indexName,
286 QueryValueType::VALUE_TYPE_STRING, std::vector<FieldValue>()});
287 suggestIndex_ = indexName;
288 }
289
InKeys(const std::set<Key> & keys)290 void QueryExpression::InKeys(const std::set<Key> &keys)
291 {
292 if (useFromTable_) {
293 expressions_[fromTable_].InKeys(keys);
294 validStatus_ = -E_NOT_SUPPORT;
295 return;
296 }
297 SetNotSupportIfFromTables();
298 queryInfo_.emplace_front(QueryObjNode{QueryObjType::IN_KEYS, std::string(), QueryValueType::VALUE_TYPE_NULL,
299 std::vector<FieldValue>()});
300 keys_ = keys;
301 }
302
GetQueryExpression()303 const std::list<QueryObjNode> &QueryExpression::GetQueryExpression()
304 {
305 if (!GetErrFlag()) {
306 queryInfo_.clear();
307 queryInfo_.emplace_back(QueryObjNode{QueryObjType::OPER_ILLEGAL});
308 LOGE("Query operate illegal!");
309 }
310 return queryInfo_;
311 }
312
GetBeginKey() const313 std::vector<uint8_t> QueryExpression::GetBeginKey() const
314 {
315 return beginKey_;
316 }
317
GetEndKey() const318 std::vector<uint8_t> QueryExpression::GetEndKey() const
319 {
320 return endKey_;
321 }
322
GetPreFixKey() const323 std::vector<uint8_t> QueryExpression::GetPreFixKey() const
324 {
325 return prefixKey_;
326 }
327
SetTableName(const std::string & tableName)328 void QueryExpression::SetTableName(const std::string &tableName)
329 {
330 tableName_ = tableName;
331 isTableNameSpecified_ = true;
332 }
333
GetTableName()334 const std::string &QueryExpression::GetTableName()
335 {
336 return tableName_;
337 }
338
IsTableNameSpecified() const339 bool QueryExpression::IsTableNameSpecified() const
340 {
341 return isTableNameSpecified_;
342 }
343
GetSuggestIndex() const344 std::string QueryExpression::GetSuggestIndex() const
345 {
346 return suggestIndex_;
347 }
348
GetKeys() const349 const std::set<Key> &QueryExpression::GetKeys() const
350 {
351 return keys_;
352 }
353
BeginGroup()354 void QueryExpression::BeginGroup()
355 {
356 if (useFromTable_) {
357 expressions_[fromTable_].BeginGroup();
358 return;
359 }
360 if (isAssetsOnly_) {
361 auto iter = queryInfo_.rbegin();
362 if (iter != queryInfo_.rend() && (*iter).operFlag != QueryObjType::OR) {
363 validStatusForAssetsOnly_ = -E_NOT_SUPPORT;
364 }
365 }
366 SetNotSupportIfFromTables();
367 queryInfo_.emplace_back(QueryObjNode{QueryObjType::BEGIN_GROUP, std::string(),
368 QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
369 }
370
EndGroup()371 void QueryExpression::EndGroup()
372 {
373 if (useFromTable_) {
374 expressions_[fromTable_].EndGroup();
375 return;
376 }
377 SetNotSupportIfFromTables();
378 groupNum_++;
379 queryInfo_.emplace_back(QueryObjNode{QueryObjType::END_GROUP, std::string(),
380 QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
381 }
382
Reset()383 void QueryExpression::Reset()
384 {
385 errFlag_ = true;
386 queryInfo_.clear();
387 prefixKey_.clear();
388 prefixKey_.shrink_to_fit();
389 suggestIndex_.clear();
390 keys_.clear();
391 }
392
SetErrFlag(bool flag)393 void QueryExpression::SetErrFlag(bool flag)
394 {
395 errFlag_ = flag;
396 }
397
GetErrFlag()398 bool QueryExpression::GetErrFlag()
399 {
400 return errFlag_;
401 }
402
GetSortType() const403 int QueryExpression::GetSortType() const
404 {
405 return sortType_;
406 }
407
SetSortType(bool isAsc)408 void QueryExpression::SetSortType(bool isAsc)
409 {
410 if (useFromTable_) {
411 expressions_[fromTable_].SetSortType(isAsc);
412 validStatus_ = -E_NOT_SUPPORT;
413 return;
414 }
415 SetNotSupportIfFromTables();
416 WriteTimeSort sortType = isAsc ? WriteTimeSort::TIMESTAMP_ASC : WriteTimeSort::TIMESTAMP_DESC;
417 sortType_ = static_cast<int>(sortType);
418 }
419
GetTables()420 std::vector<std::string> QueryExpression::GetTables()
421 {
422 return tables_;
423 }
424
SetTables(const std::vector<std::string> & tableNames)425 void QueryExpression::SetTables(const std::vector<std::string> &tableNames)
426 {
427 // filter same table
428 std::vector<std::string> syncTable;
429 std::set<std::string> addTable;
430 for (const auto &table: tableNames) {
431 if (addTable.find(table) == addTable.end()) {
432 addTable.insert(table);
433 syncTable.push_back(table);
434 }
435 }
436 tables_ = syncTable;
437 isUseFromTables_ = true;
438 if (useFromTable_) {
439 validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_NOT_SUPPORT;
440 }
441 SetNotSupportIfCondition();
442 }
443
From(const std::string & tableName)444 void QueryExpression::From(const std::string &tableName)
445 {
446 useFromTable_ = true;
447 fromTable_ = tableName;
448 for (const auto &item: tableSequence_) {
449 if (item == tableName) {
450 return;
451 }
452 }
453 tableSequence_.push_back(fromTable_);
454 expressions_[fromTable_].SetTableName(fromTable_);
455 if (tableName.empty()) {
456 validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_INVALID_ARGS;
457 } else if (!tables_.empty()) {
458 validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_NOT_SUPPORT;
459 }
460 SetNotSupportIfFromTables();
461 SetNotSupportIfCondition();
462 }
463
GetExpressionStatus() const464 int QueryExpression::GetExpressionStatus() const
465 {
466 return validStatus_;
467 }
468
GetExpressionStatusForAssetsOnly() const469 int QueryExpression::GetExpressionStatusForAssetsOnly() const
470 {
471 return validStatusForAssetsOnly_;
472 }
473
GetQueryExpressions() const474 std::vector<QueryExpression> QueryExpression::GetQueryExpressions() const
475 {
476 if (!useFromTable_) {
477 return {};
478 }
479 std::vector<QueryExpression> res;
480 for (const auto &item : tableSequence_) {
481 res.push_back(expressions_.at(item));
482 }
483 return res;
484 }
485
SetNotSupportIfFromTables()486 void QueryExpression::SetNotSupportIfFromTables()
487 {
488 if (validStatus_ != E_OK) {
489 return;
490 }
491 if (!tables_.empty()) {
492 validStatus_ = -E_NOT_SUPPORT;
493 }
494 }
495
SetNotSupportIfCondition()496 void QueryExpression::SetNotSupportIfCondition()
497 {
498 if (validStatus_ != E_OK) {
499 return;
500 }
501 if (!queryInfo_.empty()) {
502 validStatus_ = -E_NOT_SUPPORT;
503 }
504 }
505
SetNotSupportIfNeed(QueryObjType type)506 void QueryExpression::SetNotSupportIfNeed(QueryObjType type)
507 {
508 if (validStatus_ != E_OK) {
509 return;
510 }
511 if (type != QueryObjType::IN && type != QueryObjType::EQUALTO && type != QueryObjType::AND &&
512 type != QueryObjType::OR) {
513 validStatus_ = -E_NOT_SUPPORT;
514 }
515 if (validStatus_ != E_OK) {
516 return;
517 }
518 for (const auto &item: queryInfo_) {
519 if (((item.operFlag == QueryObjType::EQUALTO) && (type == QueryObjType::IN)) ||
520 ((item.operFlag == QueryObjType::IN) && (type == QueryObjType::EQUALTO))) {
521 validStatus_ = -E_NOT_SUPPORT;
522 LOGW("[Query] Not support use in and equal to at same time when use from table");
523 break;
524 }
525 }
526 }
527
RangeParamCheck() const528 int QueryExpression::RangeParamCheck() const
529 {
530 if (queryInfo_.size() != 1) { // the query filter must have 1 filter and only the Range query.
531 return -E_INVALID_ARGS;
532 }
533 for (const auto &queryObjNode : queryInfo_) {
534 if (queryObjNode.operFlag != QueryObjType::KEY_RANGE) {
535 return -E_INVALID_ARGS;
536 }
537 }
538 if (this->beginKey_.size() > DBConstant::MAX_KEY_SIZE ||
539 this->endKey_.size() > DBConstant::MAX_KEY_SIZE) {
540 return -E_INVALID_ARGS;
541 }
542 return E_OK;
543 }
544
IsAssetsOnly() const545 bool QueryExpression::IsAssetsOnly() const
546 {
547 return isAssetsOnly_;
548 }
549
GetAssetsOnlyGroupMap() const550 AssetsGroupMap QueryExpression::GetAssetsOnlyGroupMap() const
551 {
552 return assetsGroupMap_;
553 }
554
GetGroupNum() const555 uint32_t QueryExpression::GetGroupNum() const
556 {
557 return groupNum_;
558 }
559
IsUseFromTables() const560 bool QueryExpression::IsUseFromTables() const
561 {
562 return isUseFromTables_;
563 }
564 } // namespace DistributedDB
565