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