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