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