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