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 #include "query_object.h"
17 
18 #include "db_common.h"
19 #include "db_errno.h"
20 #include "get_query_info.h"
21 #include "log_print.h"
22 
23 namespace DistributedDB {
24 namespace {
25 const int INVALID_LIMIT = INT_MAX;
26 const int LIMIT_FIELD_VALUE_SIZE = 2;
27 }
28 
QueryObject()29 QueryObject::QueryObject()
30     : isValid_(true),
31       initialized_(false),
32       limit_(INVALID_LIMIT),
33       offset_(0),
34       hasOrderBy_(false),
35       hasLimit_(false),
36       hasPrefixKey_(false),
37       hasInKeys_(false),
38       orderByCounts_(0)
39 {
40 }
41 
SetAttrWithQueryObjNodes()42 void QueryObject::SetAttrWithQueryObjNodes()
43 {
44     for (const auto &iter : queryObjNodes_) {
45         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(iter.operFlag);
46         if (iter.operFlag == QueryObjType::LIMIT) {
47             hasLimit_ = true;
48             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
49                 limit_ = iter.fieldValue[0].integerValue;
50                 offset_ = iter.fieldValue[1].integerValue;
51             }
52         } else if (iter.operFlag == QueryObjType::ORDERBY) {
53             hasOrderBy_ = true;
54         } else if (symbolType == SymbolType::PREFIXKEY_SYMBOL) {
55             hasPrefixKey_ = true;
56         } else if (symbolType == SymbolType::IN_KEYS_SYMBOL) {
57             hasInKeys_ = true;
58         }
59     }
60 }
61 
QueryObject(const Query & query)62 QueryObject::QueryObject(const Query &query)
63     : QueryObject(GetQueryInfo::GetQueryExpression(query))
64 {
65 }
66 
QueryObject(const QueryExpression & queryExpression)67 QueryObject::QueryObject(const QueryExpression &queryExpression)
68     : initialized_(false),
69       limit_(INVALID_LIMIT),
70       offset_(0),
71       hasOrderBy_(false),
72       hasLimit_(false),
73       hasPrefixKey_(false),
74       hasInKeys_(false),
75       orderByCounts_(0)
76 {
77     QueryExpression queryExpressions = queryExpression;
78     queryObjNodes_ = queryExpressions.GetQueryExpression();
79     SetAttrWithQueryObjNodes();
80     isValid_ = queryExpressions.GetErrFlag();
81     prefixKey_ = queryExpressions.GetPreFixKey();
82     suggestIndex_ = queryExpressions.GetSuggestIndex();
83     tableName_ = queryExpressions.GetTableName();
84     isTableNameSpecified_ = queryExpressions.IsTableNameSpecified();
85     keys_ = queryExpressions.GetKeys();
86     sortType_ = static_cast<SortType>(queryExpressions.GetSortType());
87     tables_ = queryExpressions.GetTables();
88     validStatus = queryExpressions.GetExpressionStatus();
89 }
90 
QueryObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)91 QueryObject::QueryObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
92     const std::set<Key> &keys)
93     : queryObjNodes_(queryObjNodes),
94       prefixKey_(prefixKey),
95       keys_(keys),
96       isValid_(true),
97       initialized_(false),
98       limit_(INVALID_LIMIT),
99       offset_(0),
100       hasOrderBy_(false),
101       hasLimit_(false),
102       hasPrefixKey_(false),
103       hasInKeys_(false),
104       orderByCounts_(0)
105 {
106     SetAttrWithQueryObjNodes();
107 }
108 
~QueryObject()109 QueryObject::~QueryObject()
110 {}
111 
Init()112 int QueryObject::Init()
113 {
114     if (initialized_) {
115         return E_OK;
116     }
117 
118     int errCode = Parse();
119     if (errCode != E_OK) {
120         LOGE("Parse query object err[%d]!", errCode);
121         return errCode;
122     }
123 
124     initialized_ = true;
125     return errCode;
126 }
127 
GetQueryHelper(int & errCode)128 SqliteQueryHelper QueryObject::GetQueryHelper(int &errCode)
129 {
130     errCode = Init();
131     if (errCode != E_OK) {
132         return SqliteQueryHelper(QueryObjInfo{});
133     }
134     QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, keys_,
135         orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_, isTableNameSpecified_, sortType_};
136     return SqliteQueryHelper {info}; // compiler RVO by default, and RVO is generally required after C++17
137 }
138 
IsValid()139 bool QueryObject::IsValid()
140 {
141     if (!initialized_) {
142         (void)Init();
143     }
144     return isValid_;
145 }
146 
HasLimit() const147 bool QueryObject::HasLimit() const
148 {
149     return hasLimit_;
150 }
151 
GetLimitVal(int & limit,int & offset) const152 void QueryObject::GetLimitVal(int &limit, int &offset) const
153 {
154     limit = limit_;
155     offset = offset_;
156 }
157 
SetSchema(const SchemaObject & schema)158 void QueryObject::SetSchema(const SchemaObject &schema)
159 {
160     schema_ = schema;
161 }
162 
IsCountValid() const163 bool QueryObject::IsCountValid() const
164 {
165     if (hasLimit_ || hasOrderBy_) {
166         LOGI("It is invalid for limit and orderby!");
167         return false;
168     }
169     return true;
170 }
171 
GetPrefixKey() const172 const std::vector<uint8_t> &QueryObject::GetPrefixKey() const
173 {
174     return prefixKey_;
175 }
176 
ClearNodesFlag()177 void QueryObject::ClearNodesFlag()
178 {
179     limit_ = INVALID_LIMIT;
180     offset_ = 0;
181     isValid_ = true;
182     hasOrderBy_ = false;
183     hasLimit_ = false;
184     hasPrefixKey_ = false;
185     hasInKeys_ = false;
186     orderByCounts_ = 0;
187 }
188 
Parse()189 int QueryObject::Parse()
190 {
191     if (!isValid_) {
192         LOGE("Invalid query object!");
193         return -E_INVALID_QUERY_FORMAT;
194     }
195     int errCode = ParseQueryObjNodes();
196     if (errCode != E_OK) {
197         LOGE("Check query object illegal!");
198         isValid_ = false;
199     }
200     return errCode;
201 }
202 
ParseQueryObjNodes()203 int QueryObject::ParseQueryObjNodes()
204 {
205     ClearNodesFlag();
206 
207     auto iter = queryObjNodes_.begin();
208     int errCode = E_OK;
209     while (iter != queryObjNodes_.end()) {
210         errCode = ParseNode(iter);
211         if (errCode != E_OK) {
212             return errCode;
213         }
214         iter++;
215     }
216     return errCode;
217 }
218 
ParseNode(const std::list<QueryObjNode>::iterator & iter)219 int QueryObject::ParseNode(const std::list<QueryObjNode>::iterator &iter)
220 {
221     // The object is newly instantiated in the connection, and there is no reentrancy problem.
222     if (!iter->IsValid()) {
223         return -E_INVALID_QUERY_FORMAT;
224     }
225 
226     switch (SqliteQueryHelper::GetSymbolType(iter->operFlag)) {
227         case SymbolType::COMPARE_SYMBOL:
228         case SymbolType::RELATIONAL_SYMBOL:
229         case SymbolType::RANGE_SYMBOL:
230             return CheckEqualFormat(iter);
231         case SymbolType::LINK_SYMBOL:
232             return CheckLinkerFormat(iter);
233         case SymbolType::PREFIXKEY_SYMBOL: {
234             if (hasPrefixKey_) {
235                 LOGE("Only filter by prefix key once!!");
236                 return -E_INVALID_QUERY_FORMAT;
237             }
238             hasPrefixKey_ = true;
239             if (prefixKey_.size() > DBConstant::MAX_KEY_SIZE) {
240                 return -E_INVALID_ARGS;
241             }
242             return E_OK;
243         }
244         case SymbolType::SUGGEST_INDEX_SYMBOL:
245             return CheckSuggestIndexFormat(iter);
246         case SymbolType::IN_KEYS_SYMBOL: {
247             if (hasInKeys_) {
248                 LOGE("Only filter by keys in once!!");
249                 return -E_INVALID_QUERY_FORMAT;
250             }
251             int errCode = CheckInKeys();
252             if (errCode != E_OK) {
253                 return errCode;
254             }
255             hasInKeys_ = true;
256             return E_OK;
257         }
258         default:
259             return ParseNodeByOperFlag(iter);
260     }
261     return E_OK;
262 }
263 
ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator & iter)264 int QueryObject::ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator &iter)
265 {
266     switch (iter->operFlag) {
267         case QueryObjType::LIMIT:
268             hasLimit_ = true;
269             if (iter->fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
270                 limit_ = iter->fieldValue[0].integerValue;
271                 offset_ = iter->fieldValue[1].integerValue;
272             }
273             return CheckLimitFormat(iter);
274         case QueryObjType::ORDERBY:
275             return CheckOrderByFormat(iter);
276         default:
277             return E_OK;
278     }
279 }
280 
CheckLinkerBefore(const std::list<QueryObjNode>::iterator & iter) const281 int QueryObject::CheckLinkerBefore(const std::list<QueryObjNode>::iterator &iter) const
282 {
283     auto preIter = std::prev(iter, 1);
284     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(preIter->operFlag);
285     if (symbolType != SymbolType::COMPARE_SYMBOL && symbolType != SymbolType::RELATIONAL_SYMBOL &&
286         symbolType != SymbolType::LOGIC_SYMBOL && symbolType != SymbolType::RANGE_SYMBOL &&
287         symbolType != SymbolType::PREFIXKEY_SYMBOL && symbolType != SymbolType::IN_KEYS_SYMBOL) {
288         LOGE("Must be a comparison operation before the connective! operFlag = %s", VNAME(preIter->operFlag));
289         return -E_INVALID_QUERY_FORMAT;
290     }
291     return E_OK;
292 }
293 
CheckEqualFormat(const std::list<QueryObjNode>::iterator & iter) const294 int QueryObject::CheckEqualFormat(const std::list<QueryObjNode>::iterator &iter) const
295 {
296     if (!schema_.IsSchemaValid()) {
297         LOGE("Schema is invalid!");
298         return -E_NOT_SUPPORT;
299     }
300 
301     // use lower case in relational schema
302     std::string inPathString = isTableNameSpecified_ ? DBCommon::ToLowerCase(iter->fieldName) : iter->fieldName;
303 
304     FieldPath fieldPath;
305     int errCode = SchemaUtils::ParseAndCheckFieldPath(inPathString, fieldPath);
306     if (errCode != E_OK) {
307         return -E_INVALID_QUERY_FIELD;
308     }
309 
310     FieldType schemaFieldType = FieldType::LEAF_FIELD_BOOL;
311     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
312     if (errCode != E_OK) {
313         LOGE("Get field type fail when check compare format! errCode = %d, fieldType = %u",
314             errCode, static_cast<unsigned>(schemaFieldType));
315         return -E_INVALID_QUERY_FIELD;
316     }
317 
318     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL &&
319         SqliteQueryHelper::GetSymbolType(iter->operFlag) == SymbolType::COMPARE_SYMBOL &&
320         iter->operFlag != QueryObjType::EQUALTO && iter->operFlag != QueryObjType::NOT_EQUALTO) { // bool can == or !=
321         LOGE("Bool forbid compare!!!");
322         return -E_INVALID_QUERY_FORMAT;
323     }
324     auto nextIter = std::next(iter, 1);
325     if (nextIter != queryObjNodes_.end()) {
326         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
327         if (symbolType == SymbolType::RELATIONAL_SYMBOL || symbolType == SymbolType::COMPARE_SYMBOL ||
328             symbolType == SymbolType::RANGE_SYMBOL) {
329             LOGE("After Compare you need, You need the conjunction like and or for connecting!");
330             return -E_INVALID_QUERY_FORMAT;
331         }
332     }
333     return E_OK;
334 }
335 
CheckLinkerFormat(const std::list<QueryObjNode>::iterator & iter) const336 int QueryObject::CheckLinkerFormat(const std::list<QueryObjNode>::iterator &iter) const
337 {
338     auto itPre = iter;
339     for (; itPre != queryObjNodes_.begin(); itPre = std::prev(itPre, 1)) {
340         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(std::prev(itPre, 1)->operFlag);
341         if (symbolType != SymbolType::PREFIXKEY_SYMBOL && symbolType != SymbolType::IN_KEYS_SYMBOL) {
342             break;
343         }
344     }
345     if (itPre == queryObjNodes_.begin()) {
346         LOGE("Connectives are not allowed in the first place!");
347         return -E_INVALID_QUERY_FORMAT;
348     }
349     auto nextIter = std::next(iter, 1);
350     if (nextIter == queryObjNodes_.end()) {
351         LOGE("Connectives are not allowed in the last place!");
352         return -E_INVALID_QUERY_FORMAT;
353     }
354     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
355     if (symbolType == SymbolType::INVALID_SYMBOL || symbolType == SymbolType::LINK_SYMBOL ||
356         symbolType == SymbolType::SPECIAL_SYMBOL) {
357         LOGE("Must be followed by comparison operation! operflag[%u], symbolType[%u]",
358             static_cast<unsigned>(nextIter->operFlag), static_cast<unsigned>(symbolType));
359         return -E_INVALID_QUERY_FORMAT;
360     }
361     return CheckLinkerBefore(iter);
362 }
363 
CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator & iter) const364 int QueryObject::CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator &iter) const
365 {
366     auto next = std::next(iter, 1);
367     if (next != queryObjNodes_.end()) {
368         LOGE("SuggestIndex only allowed once, and must appear at the end!");
369         return -E_INVALID_QUERY_FORMAT;
370     }
371     return E_OK;
372 }
373 
CheckOrderByFormat(const std::list<QueryObjNode>::iterator & iter)374 int QueryObject::CheckOrderByFormat(const std::list<QueryObjNode>::iterator &iter)
375 {
376     if (!schema_.IsSchemaValid()) {
377         return -E_NOT_SUPPORT;
378     }
379 
380     FieldType schemaFieldType;
381     FieldPath fieldPath;
382 
383     int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath);
384     if (errCode != E_OK) {
385         return -E_INVALID_QUERY_FIELD;
386     }
387     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
388     if (errCode != E_OK) {
389         return -E_INVALID_QUERY_FIELD;
390     }
391     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL) {
392         return -E_INVALID_QUERY_FORMAT;
393     }
394     hasOrderBy_ = true;
395     ++orderByCounts_;
396     LOGD("Need order by %d filed value!", orderByCounts_);
397     return E_OK;
398 }
399 
CheckLimitFormat(const std::list<QueryObjNode>::iterator & iter) const400 int QueryObject::CheckLimitFormat(const std::list<QueryObjNode>::iterator &iter) const
401 {
402     auto next = std::next(iter, 1);
403     if (next != queryObjNodes_.end() && SqliteQueryHelper::GetSymbolType(next->operFlag) !=
404         SymbolType::SUGGEST_INDEX_SYMBOL) {
405         LOGE("Limit should be last node or just before suggest-index node!");
406         return -E_INVALID_QUERY_FORMAT;
407     }
408     return E_OK;
409 }
410 
IsQueryOnlyByKey() const411 bool QueryObject::IsQueryOnlyByKey() const
412 {
413     return std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
414         return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX &&
415             node.operFlag != QueryObjType::IN_KEYS;
416     });
417 }
418 
IsQueryByRange() const419 bool QueryObject::IsQueryByRange() const
420 {
421     return std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
422         return node.operFlag == QueryObjType::KEY_RANGE;
423     });
424 }
425 
IsQueryForRelationalDB() const426 bool QueryObject::IsQueryForRelationalDB() const
427 {
428     return isTableNameSpecified_ &&
429         std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
430         return node.operFlag != QueryObjType::EQUALTO && node.operFlag != QueryObjType::NOT_EQUALTO &&
431             node.operFlag != QueryObjType::AND && node.operFlag != QueryObjType::OR &&
432             node.operFlag != QueryObjType::ORDERBY && node.operFlag != QueryObjType::LIMIT;
433     });
434 }
435 
HasOrderBy() const436 bool QueryObject::HasOrderBy() const
437 {
438     return hasOrderBy_;
439 }
440 
Empty() const441 bool QueryObject::Empty() const
442 {
443     return queryObjNodes_.empty();
444 }
445 
CheckInKeys() const446 int QueryObject::CheckInKeys() const
447 {
448     if (keys_.empty()) {
449         LOGE("Inkeys cannot be empty.");
450         return -E_INVALID_ARGS;
451     }
452     if (keys_.size() > DBConstant::MAX_INKEYS_SIZE) {
453         LOGE("Inkeys cannot be over 128.");
454         return -E_MAX_LIMITS;
455     }
456     for (const auto &key : keys_) {
457         if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) {
458             LOGE("The key in Inkeys cannot be empty or overlong, size:%zu.", key.size());
459             return -E_INVALID_ARGS;
460         }
461     }
462     return E_OK;
463 }
464 
465 #ifdef RELATIONAL_STORE
SetSchema(const RelationalSchemaObject & schemaObj)466 int QueryObject::SetSchema(const RelationalSchemaObject &schemaObj)
467 {
468     if (!isTableNameSpecified_) {
469         return -E_INVALID_ARGS;
470     }
471     const auto &tableInfo = schemaObj.GetTable(tableName_);
472     SchemaObject schema(tableInfo);
473     schema_ = schema;
474     return E_OK;
475 }
476 #endif
477 
SetLimit(int limit,int offset)478 void QueryObject::SetLimit(int limit, int offset)
479 {
480     limit_ = limit;
481     offset_ = offset;
482     for (auto &iter : queryObjNodes_) {
483         if (iter.operFlag == QueryObjType::LIMIT) {
484             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
485                 iter.fieldValue[0].integerValue = limit_;
486                 iter.fieldValue[1].integerValue = offset_;
487                 break; // only one limit node
488             }
489         }
490     }
491 }
492 
SetTableName(const std::string & tableName)493 void QueryObject::SetTableName(const std::string &tableName)
494 {
495     tableName_ = tableName;
496     isTableNameSpecified_ = true;
497 }
498 
GetTableName() const499 const std::string &QueryObject::GetTableName() const
500 {
501     return tableName_;
502 }
503 
HasInKeys() const504 bool QueryObject::HasInKeys() const
505 {
506     return hasInKeys_;
507 }
508 
SetSortType(SortType sortType)509 void QueryObject::SetSortType(SortType sortType)
510 {
511     sortType_ = sortType;
512 }
513 
GetSortType() const514 SortType QueryObject::GetSortType() const
515 {
516     return sortType_;
517 }
518 
CheckPrimaryKey(const std::map<int,FieldName> & primaryKeyMap) const519 int QueryObject::CheckPrimaryKey(const std::map<int, FieldName> &primaryKeyMap) const
520 {
521     // 1 primary key and name is "rowid" means no user-defined rowid
522     if (primaryKeyMap.size() == 1 && primaryKeyMap.begin()->second == "rowid") {
523         return -E_NOT_SUPPORT;
524     }
525     std::set<std::string> pkSet;
526     for (const auto &item : primaryKeyMap) {
527         std::string pk = item.second;
528         std::transform(pk.begin(), pk.end(), pk.begin(), ::tolower);
529         pkSet.insert(pk);
530     }
531     std::set<std::string> queryPkSet;
532     for (const auto &queryObjNode : queryObjNodes_) {
533         if (queryObjNode.operFlag != QueryObjType::IN && queryObjNode.operFlag != QueryObjType::EQUALTO) {
534             continue;
535         }
536         std::string field = queryObjNode.fieldName;
537         std::transform(field.begin(), field.end(), field.begin(), ::tolower);
538         if (pkSet.find(field) == pkSet.end()) {
539             LOGE("[Query] query without pk!");
540             return -E_NOT_SUPPORT;
541         }
542         if (queryObjNode.type == QueryValueType::VALUE_TYPE_DOUBLE) {
543             LOGE("[Query] query with pk double!");
544             return -E_NOT_SUPPORT;
545         }
546         queryPkSet.insert(field);
547     }
548     if (queryPkSet.size() != pkSet.size()) {
549         LOGE("[Query] pk count is different! query %zu schema %zu", queryPkSet.size(), pkSet.size());
550         return -E_NOT_SUPPORT;
551     }
552     return E_OK;
553 }
554 
GetQueryExpressions(const Query & query)555 std::vector<QueryExpression> QueryObject::GetQueryExpressions(const Query &query)
556 {
557     return GetQueryInfo::GetQueryExpression(query).GetQueryExpressions();
558 }
559 }
560 
561