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