• 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 #include "db_errno.h"
18 #include "get_query_info.h"
19 #include "log_print.h"
20 
21 namespace DistributedDB {
22 namespace {
23 const int INVALID_LIMIT = INT_MAX;
24 const int LIMIT_FIELD_VALUE_SIZE = 2;
25 }
26 
QueryObject()27 QueryObject::QueryObject()
28     : isValid_(true),
29       initialized_(false),
30       limit_(INVALID_LIMIT),
31       offset_(0),
32       hasOrderBy_(false),
33       hasLimit_(false),
34       hasPrefixKey_(false),
35       hasInKeys_(false),
36       orderByCounts_(0)
37 {
38 }
39 
GetAttrFromQueryObjNodes()40 void QueryObject::GetAttrFromQueryObjNodes()
41 {
42     for (const auto &iter : queryObjNodes_) {
43         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(iter.operFlag);
44         if (iter.operFlag == QueryObjType::LIMIT) {
45             hasLimit_ = true;
46             if (iter.fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
47                 limit_ = iter.fieldValue[0].integerValue;
48                 offset_ = iter.fieldValue[1].integerValue;
49             }
50         } else if (iter.operFlag == QueryObjType::ORDERBY) {
51             hasOrderBy_ = true;
52         } else if (symbolType == PREFIXKEY_SYMBOL) {
53             hasPrefixKey_ = true;
54         } else if (symbolType == IN_KEYS_SYMBOL) {
55             hasInKeys_ = true;
56         }
57     }
58 }
59 
QueryObject(const Query & query)60 QueryObject::QueryObject(const Query &query)
61     : initialized_(false),
62       limit_(INVALID_LIMIT),
63       offset_(0),
64       hasOrderBy_(false),
65       hasLimit_(false),
66       hasPrefixKey_(false),
67       hasInKeys_(false),
68       orderByCounts_(0)
69 {
70     QueryExpression queryExpressions = GetQueryInfo::GetQueryExpression(query);
71     queryObjNodes_ = queryExpressions.GetQueryExpression();
72     GetAttrFromQueryObjNodes();
73     isValid_ = queryExpressions.GetErrFlag();
74     prefixKey_ = queryExpressions.GetPreFixKey();
75     suggestIndex_ = queryExpressions.GetSuggestIndex();
76     tableName_ = queryExpressions.GetTableName();
77     isTableNameSpecified_ = queryExpressions.IsTableNameSpecified();
78     keys_ = queryExpressions.GetKeys();
79     sortType_ = static_cast<SortType>(queryExpressions.GetSortType());
80 }
81 
QueryObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)82 QueryObject::QueryObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
83     const std::set<Key> &keys)
84     : queryObjNodes_(queryObjNodes),
85       prefixKey_(prefixKey),
86       keys_(keys),
87       isValid_(true),
88       initialized_(false),
89       limit_(INVALID_LIMIT),
90       offset_(0),
91       hasOrderBy_(false),
92       hasLimit_(false),
93       hasPrefixKey_(false),
94       hasInKeys_(false),
95       orderByCounts_(0)
96 {
97     GetAttrFromQueryObjNodes();
98 }
99 
~QueryObject()100 QueryObject::~QueryObject()
101 {}
102 
Init()103 int QueryObject::Init()
104 {
105     if (initialized_) {
106         return E_OK;
107     }
108 
109     int errCode = Parse();
110     if (errCode != E_OK) {
111         LOGE("Parse query object err[%d]!", errCode);
112         return errCode;
113     }
114 
115     initialized_ = true;
116     return errCode;
117 }
118 
GetQueryHelper(int & errCode)119 SqliteQueryHelper QueryObject::GetQueryHelper(int &errCode)
120 {
121     errCode = Init();
122     if (errCode != E_OK) {
123         return SqliteQueryHelper(QueryObjInfo{});
124     }
125     QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, keys_,
126         orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_, isTableNameSpecified_, sortType_};
127     return SqliteQueryHelper {info}; // compiler RVO by default, and RVO is generally required after C++17
128 }
129 
IsValid()130 bool QueryObject::IsValid()
131 {
132     if (!initialized_) {
133         (void)Init();
134     }
135     return isValid_;
136 }
137 
HasLimit() const138 bool QueryObject::HasLimit() const
139 {
140     return hasLimit_;
141 }
142 
GetLimitVal(int & limit,int & offset) const143 void QueryObject::GetLimitVal(int &limit, int &offset) const
144 {
145     limit = limit_;
146     offset = offset_;
147 }
148 
SetSchema(const SchemaObject & schema)149 void QueryObject::SetSchema(const SchemaObject &schema)
150 {
151     schema_ = schema;
152 }
153 
IsCountValid() const154 bool QueryObject::IsCountValid() const
155 {
156     if (hasLimit_ || hasOrderBy_) {
157         LOGI("It is invalid for limit and orderby!");
158         return false;
159     }
160     return true;
161 }
162 
GetPrefixKey() const163 const std::vector<uint8_t> &QueryObject::GetPrefixKey() const
164 {
165     return prefixKey_;
166 }
167 
ClearNodesFlag()168 void QueryObject::ClearNodesFlag()
169 {
170     limit_ = INVALID_LIMIT;
171     offset_ = 0;
172     isValid_ = true;
173     hasOrderBy_ = false;
174     hasLimit_ = false;
175     hasPrefixKey_ = false;
176     hasInKeys_ = false;
177     orderByCounts_ = 0;
178 }
179 
Parse()180 int QueryObject::Parse()
181 {
182     if (!isValid_) {
183         LOGE("Invalid query object!");
184         return -E_INVALID_QUERY_FORMAT;
185     }
186     int errCode = ParseQueryObjNodes();
187     if (errCode != E_OK) {
188         LOGE("Check query object illegal!");
189         isValid_ = false;
190     }
191     return errCode;
192 }
193 
ParseQueryObjNodes()194 int QueryObject::ParseQueryObjNodes()
195 {
196     ClearNodesFlag();
197 
198     auto iter = queryObjNodes_.begin();
199     int errCode = E_OK;
200     while (iter != queryObjNodes_.end()) {
201         errCode = ParseNode(iter);
202         if (errCode != E_OK) {
203             return errCode;
204         }
205         iter++;
206     }
207     return errCode;
208 }
209 
ParseNode(const std::list<QueryObjNode>::iterator & iter)210 int QueryObject::ParseNode(const std::list<QueryObjNode>::iterator &iter)
211 {
212     // The object is newly instantiated in the connection, and there is no reentrancy problem.
213     if (!iter->IsValid()) {
214         return -E_INVALID_QUERY_FORMAT;
215     }
216 
217     switch (SqliteQueryHelper::GetSymbolType(iter->operFlag)) {
218         case COMPARE_SYMBOL:
219         case RELATIONAL_SYMBOL:
220         case RANGE_SYMBOL:
221             return CheckEqualFormat(iter);
222         case LINK_SYMBOL:
223             return CheckLinkerFormat(iter);
224         case PREFIXKEY_SYMBOL: {
225             if (hasPrefixKey_) {
226                 LOGE("Only filter by prefix key once!!");
227                 return -E_INVALID_QUERY_FORMAT;
228             }
229             hasPrefixKey_ = true;
230             if (prefixKey_.size() > DBConstant::MAX_KEY_SIZE) {
231                 return -E_INVALID_ARGS;
232             }
233             return E_OK;
234         }
235         case SUGGEST_INDEX_SYMBOL:
236             return CheckSuggestIndexFormat(iter);
237         case IN_KEYS_SYMBOL: {
238             if (hasInKeys_) {
239                 LOGE("Only filter by keys in once!!");
240                 return -E_INVALID_QUERY_FORMAT;
241             }
242             int errCode = CheckInKeys();
243             if (errCode != E_OK) {
244                 return errCode;
245             }
246             hasInKeys_ = true;
247             return E_OK;
248         }
249         default:
250             return ParseNodeByOperFlag(iter);
251     }
252     return E_OK;
253 }
254 
ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator & iter)255 int QueryObject::ParseNodeByOperFlag(const std::list<QueryObjNode>::iterator &iter)
256 {
257     switch (iter->operFlag) {
258         case QueryObjType::LIMIT:
259             hasLimit_ = true;
260             if (iter->fieldValue.size() == LIMIT_FIELD_VALUE_SIZE) {
261                 limit_ = iter->fieldValue[0].integerValue;
262                 offset_ = iter->fieldValue[1].integerValue;
263             }
264             return CheckLimitFormat(iter);
265         case QueryObjType::ORDERBY:
266             return CheckOrderByFormat(iter);
267         default:
268             return E_OK;
269     }
270     return E_OK;
271 }
272 
CheckLinkerBefore(const std::list<QueryObjNode>::iterator & iter) const273 int QueryObject::CheckLinkerBefore(const std::list<QueryObjNode>::iterator &iter) const
274 {
275     auto preIter = std::prev(iter, 1);
276     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(preIter->operFlag);
277     if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != LOGIC_SYMBOL &&
278         symbolType != RANGE_SYMBOL && symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) {
279         LOGE("Must be a comparison operation before the connective! operFlag = %s", VNAME(preIter->operFlag));
280         return -E_INVALID_QUERY_FORMAT;
281     }
282     return E_OK;
283 }
284 
IsRelationalQuery() const285 bool QueryObject::IsRelationalQuery() const
286 {
287     return isTableNameSpecified_;
288 }
289 
CheckEqualFormat(const std::list<QueryObjNode>::iterator & iter) const290 int QueryObject::CheckEqualFormat(const std::list<QueryObjNode>::iterator &iter) const
291 {
292     if (!schema_.IsSchemaValid()) {
293         LOGE("Schema is invalid!");
294         return -E_NOT_SUPPORT;
295     }
296 
297     FieldPath fieldPath;
298     int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath);
299     if (errCode != E_OK) {
300         return -E_INVALID_QUERY_FIELD;
301     }
302 
303     FieldType schemaFieldType = FieldType::LEAF_FIELD_BOOL;
304     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
305     if (errCode != E_OK) {
306         LOGE("Get field type fail when check compare format! errCode = %d, fieldType = %u",
307             errCode, static_cast<unsigned>(schemaFieldType));
308         return -E_INVALID_QUERY_FIELD;
309     }
310 
311     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL &&
312         SqliteQueryHelper::GetSymbolType(iter->operFlag) == COMPARE_SYMBOL &&
313         iter->operFlag != QueryObjType::EQUALTO && iter->operFlag != QueryObjType::NOT_EQUALTO) { // bool can == or !=
314         LOGE("Bool forbid compare!!!");
315         return -E_INVALID_QUERY_FORMAT;
316     }
317     auto nextIter = std::next(iter, 1);
318     if (nextIter != queryObjNodes_.end()) {
319         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
320         if (symbolType == RELATIONAL_SYMBOL || symbolType == COMPARE_SYMBOL || symbolType == RANGE_SYMBOL) {
321             LOGE("After Compare you need, You need the conjunction like and or for connecting!");
322             return -E_INVALID_QUERY_FORMAT;
323         }
324     }
325     return E_OK;
326 }
327 
CheckLinkerFormat(const std::list<QueryObjNode>::iterator & iter) const328 int QueryObject::CheckLinkerFormat(const std::list<QueryObjNode>::iterator &iter) const
329 {
330     auto itPre = iter;
331     for (; itPre != queryObjNodes_.begin(); itPre = std::prev(itPre, 1)) {
332         SymbolType symbolType = SqliteQueryHelper::GetSymbolType(std::prev(itPre, 1)->operFlag);
333         if (symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) {
334             break;
335         }
336     }
337     if (itPre == queryObjNodes_.begin()) {
338         LOGE("Connectives are not allowed in the first place!");
339         return -E_INVALID_QUERY_FORMAT;
340     }
341     auto nextIter = std::next(iter, 1);
342     if (nextIter == queryObjNodes_.end()) {
343         LOGE("Connectives are not allowed in the last place!");
344         return -E_INVALID_QUERY_FORMAT;
345     }
346     SymbolType symbolType = SqliteQueryHelper::GetSymbolType(nextIter->operFlag);
347     if (symbolType == INVALID_SYMBOL || symbolType == LINK_SYMBOL || symbolType == SPECIAL_SYMBOL) {
348         LOGE("Must be followed by comparison operation! operflag[%u], symbolType[%u]",
349             static_cast<unsigned>(nextIter->operFlag), static_cast<unsigned>(symbolType));
350         return -E_INVALID_QUERY_FORMAT;
351     }
352     return CheckLinkerBefore(iter);
353 }
354 
CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator & iter) const355 int QueryObject::CheckSuggestIndexFormat(const std::list<QueryObjNode>::iterator &iter) const
356 {
357     auto next = std::next(iter, 1);
358     if (next != queryObjNodes_.end()) {
359         LOGE("SuggestIndex only allowed once, and must appear at the end!");
360         return -E_INVALID_QUERY_FORMAT;
361     }
362     return E_OK;
363 }
364 
CheckOrderByFormat(const std::list<QueryObjNode>::iterator & iter)365 int QueryObject::CheckOrderByFormat(const std::list<QueryObjNode>::iterator &iter)
366 {
367     if (!schema_.IsSchemaValid()) {
368         return -E_NOT_SUPPORT;
369     }
370 
371     FieldType schemaFieldType;
372     FieldPath fieldPath;
373 
374     int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath);
375     if (errCode != E_OK) {
376         return -E_INVALID_QUERY_FIELD;
377     }
378     errCode = schema_.CheckQueryableAndGetFieldType(fieldPath, schemaFieldType);
379     if (errCode != E_OK) {
380         return -E_INVALID_QUERY_FIELD;
381     }
382     if (schemaFieldType == FieldType::LEAF_FIELD_BOOL) {
383         return -E_INVALID_QUERY_FORMAT;
384     }
385     hasOrderBy_ = true;
386     ++orderByCounts_;
387     LOGD("Need order by %d filed value!", orderByCounts_);
388     return E_OK;
389 }
390 
CheckLimitFormat(const std::list<QueryObjNode>::iterator & iter) const391 int QueryObject::CheckLimitFormat(const std::list<QueryObjNode>::iterator &iter) const
392 {
393     auto next = std::next(iter, 1);
394     if (next != queryObjNodes_.end() && SqliteQueryHelper::GetSymbolType(next->operFlag) != SUGGEST_INDEX_SYMBOL) {
395         LOGE("Limit should be last node or just before suggest-index node!");
396         return -E_INVALID_QUERY_FORMAT;
397     }
398     return E_OK;
399 }
400 
IsQueryOnlyByKey() const401 bool QueryObject::IsQueryOnlyByKey() const
402 {
403     return std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
404         return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX &&
405             node.operFlag != QueryObjType::IN_KEYS;
406     });
407 }
408 
IsQueryForRelationalDB() const409 bool QueryObject::IsQueryForRelationalDB() const
410 {
411     return isTableNameSpecified_ &&
412         std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) {
413         return node.operFlag != QueryObjType::EQUALTO && node.operFlag != QueryObjType::NOT_EQUALTO &&
414             node.operFlag != QueryObjType::AND && node.operFlag != QueryObjType::OR &&
415             node.operFlag != QueryObjType::ORDERBY && node.operFlag != QueryObjType::LIMIT;
416     });
417 }
418 
HasOrderBy() const419 bool QueryObject::HasOrderBy() const
420 {
421     return hasOrderBy_;
422 }
423 
Empty() const424 bool QueryObject::Empty() const
425 {
426     return queryObjNodes_.empty();
427 }
428 
CheckInKeys() const429 int QueryObject::CheckInKeys() const
430 {
431     if (keys_.empty()) {
432         LOGE("Inkeys cannot be empty.");
433         return -E_INVALID_ARGS;
434     }
435     if (keys_.size() > DBConstant::MAX_INKEYS_SIZE) {
436         LOGE("Inkeys cannot be over 128.");
437         return -E_MAX_LIMITS;
438     }
439     for (const auto &key : keys_) {
440         if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) {
441             LOGE("The key in Inkeys cannot be empty or overlong, size:%zu.", key.size());
442             return -E_INVALID_ARGS;
443         }
444     }
445     return E_OK;
446 }
447 
448 #ifdef RELATIONAL_STORE
SetSchema(const RelationalSchemaObject & schemaObj)449 int QueryObject::SetSchema(const RelationalSchemaObject &schemaObj)
450 {
451     if (!isTableNameSpecified_) {
452         return -E_INVALID_ARGS;
453     }
454     const auto &tableInfo = schemaObj.GetTable(tableName_);
455     SchemaObject schema(tableInfo);
456     schema_ = schema;
457     return E_OK;
458 }
459 #endif
460 }
461 
462