• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 == PREFIXKEY_SYMBOL) {
55             hasPrefixKey_ = true;
56         } else if (symbolType == IN_KEYS_SYMBOL) {
57             hasInKeys_ = true;
58         }
59     }
60 }
61 
QueryObject(const Query & query)62 QueryObject::QueryObject(const Query &query)
63     : initialized_(false),
64       limit_(INVALID_LIMIT),
65       offset_(0),
66       hasOrderBy_(false),
67       hasLimit_(false),
68       hasPrefixKey_(false),
69       hasInKeys_(false),
70       orderByCounts_(0)
71 {
72     QueryExpression queryExpressions = GetQueryInfo::GetQueryExpression(query);
73     queryObjNodes_ = queryExpressions.GetQueryExpression();
74     SetAttrWithQueryObjNodes();
75     isValid_ = queryExpressions.GetErrFlag();
76     prefixKey_ = queryExpressions.GetPreFixKey();
77     suggestIndex_ = queryExpressions.GetSuggestIndex();
78     tableName_ = queryExpressions.GetTableName();
79     isTableNameSpecified_ = queryExpressions.IsTableNameSpecified();
80     keys_ = queryExpressions.GetKeys();
81     sortType_ = static_cast<SortType>(queryExpressions.GetSortType());
82     tables_ = queryExpressions.GetTables();
83     isWithDeviceSyncQuery_ = queryExpressions.GetIsDeviceSyncQuery();
84 }
85 
QueryObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)86 QueryObject::QueryObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
87     const std::set<Key> &keys)
88     : queryObjNodes_(queryObjNodes),
89       prefixKey_(prefixKey),
90       keys_(keys),
91       isValid_(true),
92       initialized_(false),
93       limit_(INVALID_LIMIT),
94       offset_(0),
95       hasOrderBy_(false),
96       hasLimit_(false),
97       hasPrefixKey_(false),
98       hasInKeys_(false),
99       orderByCounts_(0)
100 {
101     SetAttrWithQueryObjNodes();
102 }
103 
~QueryObject()104 QueryObject::~QueryObject()
105 {}
106 
Init()107 int QueryObject::Init()
108 {
109     if (initialized_) {
110         return E_OK;
111     }
112 
113     int errCode = Parse();
114     if (errCode != E_OK) {
115         LOGE("Parse query object err[%d]!", errCode);
116         return errCode;
117     }
118 
119     initialized_ = true;
120     return errCode;
121 }
122 
GetQueryHelper(int & errCode)123 SqliteQueryHelper QueryObject::GetQueryHelper(int &errCode)
124 {
125     errCode = Init();
126     if (errCode != E_OK) {
127         return SqliteQueryHelper(QueryObjInfo{});
128     }
129     QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, keys_,
130         orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_, isTableNameSpecified_, sortType_};
131     return SqliteQueryHelper {info}; // compiler RVO by default, and RVO is generally required after C++17
132 }
133 
IsValid()134 bool QueryObject::IsValid()
135 {
136     if (!initialized_) {
137         (void)Init();
138     }
139     return isValid_;
140 }
141 
HasLimit() const142 bool QueryObject::HasLimit() const
143 {
144     return hasLimit_;
145 }
146 
GetLimitVal(int & limit,int & offset) const147 void QueryObject::GetLimitVal(int &limit, int &offset) const
148 {
149     limit = limit_;
150     offset = offset_;
151 }
152 
SetSchema(const SchemaObject & schema)153 void QueryObject::SetSchema(const SchemaObject &schema)
154 {
155     schema_ = schema;
156 }
157 
IsCountValid() const158 bool QueryObject::IsCountValid() const
159 {
160     if (hasLimit_ || hasOrderBy_) {
161         LOGI("It is invalid for limit and orderby!");
162         return false;
163     }
164     return true;
165 }
166 
GetPrefixKey() const167 const std::vector<uint8_t> &QueryObject::GetPrefixKey() const
168 {
169     return prefixKey_;
170 }
171 
ClearNodesFlag()172 void QueryObject::ClearNodesFlag()
173 {
174     limit_ = INVALID_LIMIT;
175     offset_ = 0;
176     isValid_ = true;
177     hasOrderBy_ = false;
178     hasLimit_ = false;
179     hasPrefixKey_ = false;
180     hasInKeys_ = false;
181     orderByCounts_ = 0;
182 }
183 
Parse()184 int QueryObject::Parse()
185 {
186     if (!isValid_) {
187         LOGE("Invalid query object!");
188         return -E_INVALID_QUERY_FORMAT;
189     }
190     int errCode = ParseQueryObjNodes();
191     if (errCode != E_OK) {
192         LOGE("Check query object illegal!");
193         isValid_ = false;
194     }
195     return errCode;
196 }
197 
ParseQueryObjNodes()198 int QueryObject::ParseQueryObjNodes()
199 {
200     ClearNodesFlag();
201 
202     auto iter = queryObjNodes_.begin();
203     int errCode = E_OK;
204     while (iter != queryObjNodes_.end()) {
205         errCode = ParseNode(iter);
206         if (errCode != E_OK) {
207             return errCode;
208         }
209         iter++;
210     }
211     return errCode;
212 }
213 
ParseNode(const std::list<QueryObjNode>::iterator & iter)214 int QueryObject::ParseNode(const std::list<QueryObjNode>::iterator &iter)
215 {
216     // The object is newly instantiated in the connection, and there is no reentrancy problem.
217     if (!iter->IsValid()) {
218         return -E_INVALID_QUERY_FORMAT;
219     }
220 
221     switch (SqliteQueryHelper::GetSymbolType(iter->operFlag)) {
222         case COMPARE_SYMBOL:
223         case RELATIONAL_SYMBOL:
224         case RANGE_SYMBOL:
225             return CheckEqualFormat(iter);
226         case LINK_SYMBOL:
227             return CheckLinkerFormat(iter);
228         case PREFIXKEY_SYMBOL: {
229             if (hasPrefixKey_) {
230                 LOGE("Only filter by prefix key once!!");
231                 return -E_INVALID_QUERY_FORMAT;
232             }
233             hasPrefixKey_ = true;
234             if (prefixKey_.size() > DBConstant::MAX_KEY_SIZE) {
235                 return -E_INVALID_ARGS;
236             }
237             return E_OK;
238         }
239         case SUGGEST_INDEX_SYMBOL:
240             return CheckSuggestIndexFormat(iter);
241         case IN_KEYS_SYMBOL: {
242             if (hasInKeys_) {
243                 LOGE("Only filter by keys in once!!");
244                 return -E_INVALID_QUERY_FORMAT;
245             }
246             int errCode = CheckInKeys();
247             if (errCode != E_OK) {
248                 return errCode;
249             }
250             hasInKeys_ = true;
251             return E_OK;
252         }
253         default:
254             return ParseNodeByOperFlag(iter);
255     }
256     return E_OK;
257 }
258 
ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator & iter)259 int QueryObject::ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator &iter)
260 {
261     switch (iter->operFlag) {
262         case QueryObjType::LIMIT:
263             hasLimit_ = true;
264             if (iter->fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
265                 limit_ = iter->fieldValue[0].integerValue;
266                 offset_ = iter->fieldValue[1].integerValue;
267             }
268             return CheckLimitFormat(iter);
269         case QueryObjType::ORDERBY:
270             return CheckOrderByFormat(iter);
271         default:
272             return E_OK;
273     }
274 }
275 
CheckLinkerBefore(const std::list<QueryObjNode>::iterator & iter) const276 int QueryObject::CheckLinkerBefore(const std::list<QueryObjNode>::iterator &iter) const
277 {
278     auto preIter = std::prev(iter, 1);
279     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(preIter->operFlag);
280     if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != LOGIC_SYMBOL &&
281         symbolType != RANGE_SYMBOL && symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) {
282         LOGE("Must be a comparison operation before the connective! operFlag = %s", VNAME(preIter->operFlag));
283         return -E_INVALID_QUERY_FORMAT;
284     }
285     return E_OK;
286 }
287 
CheckEqualFormat(const std::list<QueryObjNode>::iterator & iter) const288 int QueryObject::CheckEqualFormat(const std::list<QueryObjNode>::iterator &iter) const
289 {
290     if (!schema_.IsSchemaValid()) {
291         LOGE("Schema is invalid!");
292         return -E_NOT_SUPPORT;
293     }
294 
295     // use lower case in relational schema
296     std::string inPathString = isTableNameSpecified_ ? DBCommon::ToLowerCase(iter->fieldName) : iter->fieldName;
297 
298     FieldPath fieldPath;
299     int errCode = SchemaUtils::ParseAndCheckFieldPath(inPathString, fieldPath);
300     if (errCode != E_OK) {
301         return -E_INVALID_QUERY_FIELD;
302     }
303 
304     FieldType schemaFieldType = FieldType::LEAF_FIELD_BOOL;
305     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
306     if (errCode != E_OK) {
307         LOGE("Get field type fail when check compare format! errCode = %d, fieldType = %u",
308             errCode, static_cast<unsigned>(schemaFieldType));
309         return -E_INVALID_QUERY_FIELD;
310     }
311 
312     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL &&
313         SqliteQueryHelper::GetSymbolType(iter->operFlag) == COMPARE_SYMBOL &&
314         iter->operFlag != QueryObjType::EQUALTO && iter->operFlag != QueryObjType::NOT_EQUALTO) { // bool can == or !=
315         LOGE("Bool forbid compare!!!");
316         return -E_INVALID_QUERY_FORMAT;
317     }
318     auto nextIter = std::next(iter, 1);
319     if (nextIter != queryObjNodes_.end()) {
320         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
321         if (symbolType == RELATIONAL_SYMBOL || symbolType == COMPARE_SYMBOL || symbolType == RANGE_SYMBOL) {
322             LOGE("After Compare you need, You need the conjunction like and or for connecting!");
323             return -E_INVALID_QUERY_FORMAT;
324         }
325     }
326     return E_OK;
327 }
328 
CheckLinkerFormat(const std::list<QueryObjNode>::iterator & iter) const329 int QueryObject::CheckLinkerFormat(const std::list<QueryObjNode>::iterator &iter) const
330 {
331     auto itPre = iter;
332     for (; itPre != queryObjNodes_.begin(); itPre = std::prev(itPre, 1)) {
333         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(std::prev(itPre, 1)->operFlag);
334         if (symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) {
335             break;
336         }
337     }
338     if (itPre == queryObjNodes_.begin()) {
339         LOGE("Connectives are not allowed in the first place!");
340         return -E_INVALID_QUERY_FORMAT;
341     }
342     auto nextIter = std::next(iter, 1);
343     if (nextIter == queryObjNodes_.end()) {
344         LOGE("Connectives are not allowed in the last place!");
345         return -E_INVALID_QUERY_FORMAT;
346     }
347     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
348     if (symbolType == INVALID_SYMBOL || symbolType == LINK_SYMBOL || symbolType == SPECIAL_SYMBOL) {
349         LOGE("Must be followed by comparison operation! operflag[%u], symbolType[%u]",
350             static_cast<unsigned>(nextIter->operFlag), static_cast<unsigned>(symbolType));
351         return -E_INVALID_QUERY_FORMAT;
352     }
353     return CheckLinkerBefore(iter);
354 }
355 
CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator & iter) const356 int QueryObject::CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator &iter) const
357 {
358     auto next = std::next(iter, 1);
359     if (next != queryObjNodes_.end()) {
360         LOGE("SuggestIndex only allowed once, and must appear at the end!");
361         return -E_INVALID_QUERY_FORMAT;
362     }
363     return E_OK;
364 }
365 
CheckOrderByFormat(const std::list<QueryObjNode>::iterator & iter)366 int QueryObject::CheckOrderByFormat(const std::list<QueryObjNode>::iterator &iter)
367 {
368     if (!schema_.IsSchemaValid()) {
369         return -E_NOT_SUPPORT;
370     }
371 
372     FieldType schemaFieldType;
373     FieldPath fieldPath;
374 
375     int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath);
376     if (errCode != E_OK) {
377         return -E_INVALID_QUERY_FIELD;
378     }
379     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
380     if (errCode != E_OK) {
381         return -E_INVALID_QUERY_FIELD;
382     }
383     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL) {
384         return -E_INVALID_QUERY_FORMAT;
385     }
386     hasOrderBy_ = true;
387     ++orderByCounts_;
388     LOGD("Need order by %d filed value!", orderByCounts_);
389     return E_OK;
390 }
391 
CheckLimitFormat(const std::list<QueryObjNode>::iterator & iter) const392 int QueryObject::CheckLimitFormat(const std::list<QueryObjNode>::iterator &iter) const
393 {
394     auto next = std::next(iter, 1);
395     if (next != queryObjNodes_.end() && SqliteQueryHelper::GetSymbolType(next->operFlag) != SUGGEST_INDEX_SYMBOL) {
396         LOGE("Limit should be last node or just before suggest-index node!");
397         return -E_INVALID_QUERY_FORMAT;
398     }
399     return E_OK;
400 }
401 
IsQueryOnlyByKey() const402 bool QueryObject::IsQueryOnlyByKey() const
403 {
404     return std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
405         return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX &&
406             node.operFlag != QueryObjType::IN_KEYS;
407     });
408 }
409 
IsQueryForRelationalDB() const410 bool QueryObject::IsQueryForRelationalDB() const
411 {
412     return isTableNameSpecified_ &&
413         std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
414         return node.operFlag != QueryObjType::EQUALTO && node.operFlag != QueryObjType::NOT_EQUALTO &&
415             node.operFlag != QueryObjType::AND && node.operFlag != QueryObjType::OR &&
416             node.operFlag != QueryObjType::ORDERBY && node.operFlag != QueryObjType::LIMIT;
417     });
418 }
419 
HasOrderBy() const420 bool QueryObject::HasOrderBy() const
421 {
422     return hasOrderBy_;
423 }
424 
Empty() const425 bool QueryObject::Empty() const
426 {
427     return queryObjNodes_.empty();
428 }
429 
CheckInKeys() const430 int QueryObject::CheckInKeys() const
431 {
432     if (keys_.empty()) {
433         LOGE("Inkeys cannot be empty.");
434         return -E_INVALID_ARGS;
435     }
436     if (keys_.size() > DBConstant::MAX_INKEYS_SIZE) {
437         LOGE("Inkeys cannot be over 128.");
438         return -E_MAX_LIMITS;
439     }
440     for (const auto &key : keys_) {
441         if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) {
442             LOGE("The key in Inkeys cannot be empty or overlong, size:%zu.", key.size());
443             return -E_INVALID_ARGS;
444         }
445     }
446     return E_OK;
447 }
448 
449 #ifdef RELATIONAL_STORE
SetSchema(const RelationalSchemaObject & schemaObj)450 int QueryObject::SetSchema(const RelationalSchemaObject &schemaObj)
451 {
452     if (!isTableNameSpecified_) {
453         return -E_INVALID_ARGS;
454     }
455     const auto &tableInfo = schemaObj.GetTable(tableName_);
456     SchemaObject schema(tableInfo);
457     schema_ = schema;
458     return E_OK;
459 }
460 #endif
461 
SetLimit(int limit,int offset)462 void QueryObject::SetLimit(int limit, int offset)
463 {
464     limit_ = limit;
465     offset_ = offset;
466     for (auto &iter : queryObjNodes_) {
467         if (iter.operFlag == QueryObjType::LIMIT) {
468             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
469                 iter.fieldValue[0].integerValue = limit_;
470                 iter.fieldValue[1].integerValue = offset_;
471                 break; // only one limit node
472             }
473         }
474     }
475 }
476 
SetTableName(const std::string & tableName)477 void QueryObject::SetTableName(const std::string &tableName)
478 {
479     tableName_ = tableName;
480     isTableNameSpecified_ = true;
481 }
482 
GetTableName() const483 const std::string &QueryObject::GetTableName() const
484 {
485     return tableName_;
486 }
487 
HasInKeys() const488 bool QueryObject::HasInKeys() const
489 {
490     return hasInKeys_;
491 }
492 
SetSortType(SortType sortType)493 void QueryObject::SetSortType(SortType sortType)
494 {
495     sortType_ = sortType;
496 }
497 
GetSortType() const498 SortType QueryObject::GetSortType() const
499 {
500     return sortType_;
501 }
502 }
503 
504