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 #include "query_expression.h"
16 #include "log_print.h"
17 #include "schema_utils.h"
18 #include "db_errno.h"
19 
20 namespace DistributedDB {
21 namespace {
22     const int MAX_OPR_TIMES = 256;
23 } // namespace
24 
AssemblyQueryInfo(const QueryObjType queryOperType,const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values,bool isNeedFieldPath=true)25 void QueryExpression::AssemblyQueryInfo(const QueryObjType queryOperType, const std::string& field,
26     const QueryValueType type, const std::vector<FieldValue> &values, bool isNeedFieldPath = true)
27 {
28     if (useFromTable_) {
29         expressions_[fromTable_].AssemblyQueryInfo(queryOperType, field, type, values, isNeedFieldPath);
30         SetNotSupportIfNeed(queryOperType);
31         return;
32     }
33     if (!tables_.empty()) {
34         validStatus_ = -E_NOT_SUPPORT;
35     }
36     if (queryInfo_.size() > MAX_OPR_TIMES) {
37         SetErrFlag(false);
38         LOGE("Operate too much times!");
39         return;
40     }
41 
42     if (!GetErrFlag()) {
43         LOGE("Illegal data node!");
44         return;
45     }
46 
47     FieldPath outPath;
48     if (isNeedFieldPath) {
49         if (SchemaUtils::ParseAndCheckFieldPath(field, outPath) != E_OK) {
50             SetErrFlag(false);
51             LOGE("Field path illegal!");
52             return;
53         }
54     }
55     std::string formatedField;
56     if (isTableNameSpecified_) { // remove '$.' prefix in relational query
57         for (auto it = outPath.begin(); it < outPath.end(); ++it) {
58             if (it != outPath.begin()) {
59                 formatedField += ".";
60             }
61             formatedField += *it;
62         }
63     } else {
64         formatedField = field;
65     }
66     if (!queryInfo_.empty() && queryInfo_.back().operFlag == queryOperType) {
67         validStatus_ = -E_INVALID_ARGS;
68     }
69     queryInfo_.emplace_back(QueryObjNode{queryOperType, formatedField, type, values});
70 }
71 
QueryExpression()72 QueryExpression::QueryExpression()
73     : errFlag_(true),
74       tableName_("sync_data"), // default kv type store table name
75       isTableNameSpecified_(false) // default no specify for kv type store table name
76 {}
77 
EqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)78 void QueryExpression::EqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
79 {
80     std::vector<FieldValue> fieldValues{value};
81     AssemblyQueryInfo(QueryObjType::EQUALTO, field, type, fieldValues);
82 }
83 
NotEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)84 void QueryExpression::NotEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
85 {
86     std::vector<FieldValue> fieldValues{value};
87     AssemblyQueryInfo(QueryObjType::NOT_EQUALTO, field, type, fieldValues);
88 }
89 
GreaterThan(const std::string & field,const QueryValueType type,const FieldValue & value)90 void QueryExpression::GreaterThan(const std::string& field, const QueryValueType type, const FieldValue &value)
91 {
92     if (type == QueryValueType::VALUE_TYPE_BOOL) {
93         LOGD("Prohibit the use of bool for comparison!");
94         SetErrFlag(false);
95     }
96     std::vector<FieldValue> fieldValues{value};
97     AssemblyQueryInfo(QueryObjType::GREATER_THAN, field, type, fieldValues);
98 }
99 
LessThan(const std::string & field,const QueryValueType type,const FieldValue & value)100 void QueryExpression::LessThan(const std::string& field, const QueryValueType type, const FieldValue &value)
101 {
102     if (type == QueryValueType::VALUE_TYPE_BOOL) {
103         LOGD("Prohibit the use of bool for comparison!");
104         SetErrFlag(false);
105     }
106     std::vector<FieldValue> fieldValues{value};
107     AssemblyQueryInfo(QueryObjType::LESS_THAN, field, type, fieldValues);
108 }
109 
GreaterThanOrEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)110 void QueryExpression::GreaterThanOrEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
111 {
112     if (type == QueryValueType::VALUE_TYPE_BOOL) {
113         LOGD("Prohibit the use of bool for comparison!");
114         SetErrFlag(false);
115     }
116     std::vector<FieldValue> fieldValues{value};
117     AssemblyQueryInfo(QueryObjType::GREATER_THAN_OR_EQUALTO, field, type, fieldValues);
118 }
119 
LessThanOrEqualTo(const std::string & field,const QueryValueType type,const FieldValue & value)120 void QueryExpression::LessThanOrEqualTo(const std::string& field, const QueryValueType type, const FieldValue &value)
121 {
122     if (type == QueryValueType::VALUE_TYPE_BOOL) {
123         LOGD("Prohibit the use of bool for comparison!");
124         SetErrFlag(false);
125     }
126     std::vector<FieldValue> fieldValues{value};
127     AssemblyQueryInfo(QueryObjType::LESS_THAN_OR_EQUALTO, field, type, fieldValues);
128 }
129 
OrderBy(const std::string & field,bool isAsc)130 void QueryExpression::OrderBy(const std::string& field, bool isAsc)
131 {
132     FieldValue fieldValue;
133     fieldValue.boolValue = isAsc;
134     std::vector<FieldValue> fieldValues{fieldValue};
135     AssemblyQueryInfo(QueryObjType::ORDERBY, field, QueryValueType::VALUE_TYPE_BOOL, fieldValues);
136 }
137 
Like(const std::string & field,const std::string & value)138 void QueryExpression::Like(const std::string& field, const std::string &value)
139 {
140     FieldValue fieldValue;
141     fieldValue.stringValue = value;
142     std::vector<FieldValue> fieldValues{fieldValue};
143     AssemblyQueryInfo(QueryObjType::LIKE, field, QueryValueType::VALUE_TYPE_STRING, fieldValues);
144 }
145 
NotLike(const std::string & field,const std::string & value)146 void QueryExpression::NotLike(const std::string& field, const std::string &value)
147 {
148     FieldValue fieldValue;
149     fieldValue.stringValue = value;
150     std::vector<FieldValue> fieldValues{fieldValue};
151     AssemblyQueryInfo(QueryObjType::NOT_LIKE, field, QueryValueType::VALUE_TYPE_STRING, fieldValues);
152 }
153 
Limit(int number,int offset)154 void QueryExpression::Limit(int number, int offset)
155 {
156     FieldValue fieldNumber;
157     fieldNumber.integerValue = number;
158     FieldValue fieldOffset;
159     fieldOffset.integerValue = offset;
160     std::vector<FieldValue> fieldValues{fieldNumber, fieldOffset};
161     AssemblyQueryInfo(QueryObjType::LIMIT, std::string(), QueryValueType::VALUE_TYPE_INTEGER, fieldValues, false);
162 }
163 
IsNull(const std::string & field)164 void QueryExpression::IsNull(const std::string& field)
165 {
166     AssemblyQueryInfo(QueryObjType::IS_NULL, field, QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>());
167 }
168 
IsNotNull(const std::string & field)169 void QueryExpression::IsNotNull(const std::string& field)
170 {
171     AssemblyQueryInfo(QueryObjType::IS_NOT_NULL, field, QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>());
172 }
173 
In(const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values)174 void QueryExpression::In(const std::string& field, const QueryValueType type, const std::vector<FieldValue> &values)
175 {
176     AssemblyQueryInfo(QueryObjType::IN, field, type, values);
177 }
178 
NotIn(const std::string & field,const QueryValueType type,const std::vector<FieldValue> & values)179 void QueryExpression::NotIn(const std::string& field, const QueryValueType type, const std::vector<FieldValue> &values)
180 {
181     AssemblyQueryInfo(QueryObjType::NOT_IN, field, type, values);
182 }
183 
And()184 void QueryExpression::And()
185 {
186     AssemblyQueryInfo(QueryObjType::AND, std::string(), QueryValueType::VALUE_TYPE_NULL,
187         std::vector<FieldValue>(), false);
188 }
189 
Or()190 void QueryExpression::Or()
191 {
192     AssemblyQueryInfo(QueryObjType::OR, std::string(), QueryValueType::VALUE_TYPE_NULL,
193         std::vector<FieldValue>(), false);
194 }
195 
QueryByPrefixKey(const std::vector<uint8_t> & key)196 void QueryExpression::QueryByPrefixKey(const std::vector<uint8_t> &key)
197 {
198     if (useFromTable_) {
199         expressions_[fromTable_].QueryByPrefixKey(key);
200         validStatus_ = -E_NOT_SUPPORT;
201         return;
202     }
203     SetNotSupportIfFromTables();
204     queryInfo_.emplace_front(QueryObjNode{QueryObjType::QUERY_BY_KEY_PREFIX, std::string(),
205         QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
206     prefixKey_ = key;
207 }
208 
QueryByKeyRange(const std::vector<uint8_t> & keyBegin,const std::vector<uint8_t> & keyEnd)209 void QueryExpression::QueryByKeyRange(const std::vector<uint8_t> &keyBegin, const std::vector<uint8_t> &keyEnd)
210 {
211     if (useFromTable_) {
212         expressions_[fromTable_].QueryByKeyRange(keyBegin, keyEnd);
213         validStatus_ = -E_NOT_SUPPORT;
214         return;
215     }
216     SetNotSupportIfFromTables();
217     queryInfo_.emplace_front(QueryObjNode{QueryObjType::KEY_RANGE, std::string(),
218         QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
219     beginKey_ = keyBegin;
220     endKey_ = keyEnd;
221 }
222 
QueryBySuggestIndex(const std::string & indexName)223 void QueryExpression::QueryBySuggestIndex(const std::string &indexName)
224 {
225     if (useFromTable_) {
226         expressions_[fromTable_].QueryBySuggestIndex(indexName);
227         validStatus_ = -E_NOT_SUPPORT;
228         return;
229     }
230     SetNotSupportIfFromTables();
231     queryInfo_.emplace_back(QueryObjNode{QueryObjType::SUGGEST_INDEX, indexName,
232         QueryValueType::VALUE_TYPE_STRING, std::vector<FieldValue>()});
233     suggestIndex_ = indexName;
234 }
235 
InKeys(const std::set<Key> & keys)236 void QueryExpression::InKeys(const std::set<Key> &keys)
237 {
238     if (useFromTable_) {
239         expressions_[fromTable_].InKeys(keys);
240         validStatus_ = -E_NOT_SUPPORT;
241         return;
242     }
243     SetNotSupportIfFromTables();
244     queryInfo_.emplace_front(QueryObjNode{QueryObjType::IN_KEYS, std::string(), QueryValueType::VALUE_TYPE_NULL,
245         std::vector<FieldValue>()});
246     keys_ = keys;
247 }
248 
GetQueryExpression()249 const std::list<QueryObjNode> &QueryExpression::GetQueryExpression()
250 {
251     if (!GetErrFlag()) {
252         queryInfo_.clear();
253         queryInfo_.emplace_back(QueryObjNode{QueryObjType::OPER_ILLEGAL});
254         LOGE("Query operate illegal!");
255     }
256     return queryInfo_;
257 }
258 
GetBeginKey() const259 std::vector<uint8_t> QueryExpression::GetBeginKey() const
260 {
261     return beginKey_;
262 }
263 
GetEndKey() const264 std::vector<uint8_t> QueryExpression::GetEndKey() const
265 {
266     return endKey_;
267 }
268 
GetPreFixKey() const269 std::vector<uint8_t> QueryExpression::GetPreFixKey() const
270 {
271     return prefixKey_;
272 }
273 
SetTableName(const std::string & tableName)274 void QueryExpression::SetTableName(const std::string &tableName)
275 {
276     tableName_ = tableName;
277     isTableNameSpecified_ = true;
278 }
279 
GetTableName()280 const std::string &QueryExpression::GetTableName()
281 {
282     return tableName_;
283 }
284 
IsTableNameSpecified() const285 bool QueryExpression::IsTableNameSpecified() const
286 {
287     return isTableNameSpecified_;
288 }
289 
GetSuggestIndex() const290 std::string QueryExpression::GetSuggestIndex() const
291 {
292     return suggestIndex_;
293 }
294 
GetKeys() const295 const std::set<Key> &QueryExpression::GetKeys() const
296 {
297     return keys_;
298 }
299 
BeginGroup()300 void QueryExpression::BeginGroup()
301 {
302     if (useFromTable_) {
303         expressions_[fromTable_].BeginGroup();
304         return;
305     }
306     SetNotSupportIfFromTables();
307     queryInfo_.emplace_back(QueryObjNode{QueryObjType::BEGIN_GROUP, std::string(),
308         QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
309 }
310 
EndGroup()311 void QueryExpression::EndGroup()
312 {
313     if (useFromTable_) {
314         expressions_[fromTable_].EndGroup();
315         return;
316     }
317     SetNotSupportIfFromTables();
318     queryInfo_.emplace_back(QueryObjNode{QueryObjType::END_GROUP, std::string(),
319         QueryValueType::VALUE_TYPE_NULL, std::vector<FieldValue>()});
320 }
321 
Reset()322 void QueryExpression::Reset()
323 {
324     errFlag_ = true;
325     queryInfo_.clear();
326     prefixKey_.clear();
327     prefixKey_.shrink_to_fit();
328     suggestIndex_.clear();
329     keys_.clear();
330 }
331 
SetErrFlag(bool flag)332 void QueryExpression::SetErrFlag(bool flag)
333 {
334     errFlag_ = flag;
335 }
336 
GetErrFlag()337 bool QueryExpression::GetErrFlag()
338 {
339     return errFlag_;
340 }
341 
GetSortType() const342 int QueryExpression::GetSortType() const
343 {
344     return sortType_;
345 }
346 
SetSortType(bool isAsc)347 void QueryExpression::SetSortType(bool isAsc)
348 {
349     if (useFromTable_) {
350         expressions_[fromTable_].SetSortType(isAsc);
351         validStatus_ = -E_NOT_SUPPORT;
352         return;
353     }
354     SetNotSupportIfFromTables();
355     WriteTimeSort sortType = isAsc ? WriteTimeSort::TIMESTAMP_ASC : WriteTimeSort::TIMESTAMP_DESC;
356     sortType_ = static_cast<int>(sortType);
357 }
358 
GetTables()359 std::vector<std::string> QueryExpression::GetTables()
360 {
361     return tables_;
362 }
363 
SetTables(const std::vector<std::string> & tableNames)364 void QueryExpression::SetTables(const std::vector<std::string> &tableNames)
365 {
366     // filter same table
367     std::vector<std::string> syncTable;
368     std::set<std::string> addTable;
369     for (const auto &table: tableNames) {
370         if (addTable.find(table) == addTable.end()) {
371             addTable.insert(table);
372             syncTable.push_back(table);
373         }
374     }
375     tables_ = syncTable;
376     if (useFromTable_) {
377         validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_NOT_SUPPORT;
378     }
379     SetNotSupportIfCondition();
380 }
381 
From(const std::string & tableName)382 void QueryExpression::From(const std::string &tableName)
383 {
384     useFromTable_ = true;
385     fromTable_ = tableName;
386     for (const auto &item: tableSequence_) {
387         if (item == tableName) {
388             return;
389         }
390     }
391     tableSequence_.push_back(fromTable_);
392     expressions_[fromTable_].SetTableName(fromTable_);
393     if (tableName.empty()) {
394         validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_INVALID_ARGS;
395     } else if (!tables_.empty()) {
396         validStatus_ = validStatus_ != E_OK ? validStatus_ : -E_NOT_SUPPORT;
397     }
398     SetNotSupportIfFromTables();
399     SetNotSupportIfCondition();
400 }
401 
GetExpressionStatus() const402 int QueryExpression::GetExpressionStatus() const
403 {
404     return validStatus_;
405 }
406 
GetQueryExpressions() const407 std::vector<QueryExpression> QueryExpression::GetQueryExpressions() const
408 {
409     if (!useFromTable_) {
410         return {};
411     }
412     std::vector<QueryExpression> res;
413     for (const auto &item : tableSequence_) {
414         res.push_back(expressions_.at(item));
415     }
416     return res;
417 }
418 
SetNotSupportIfFromTables()419 void QueryExpression::SetNotSupportIfFromTables()
420 {
421     if (validStatus_ != E_OK) {
422         return;
423     }
424     if (!tables_.empty()) {
425         validStatus_ = -E_NOT_SUPPORT;
426     }
427 }
428 
SetNotSupportIfCondition()429 void QueryExpression::SetNotSupportIfCondition()
430 {
431     if (validStatus_ != E_OK) {
432         return;
433     }
434     if (!queryInfo_.empty()) {
435         validStatus_ = -E_NOT_SUPPORT;
436     }
437 }
438 
SetNotSupportIfNeed(QueryObjType type)439 void QueryExpression::SetNotSupportIfNeed(QueryObjType type)
440 {
441     if (validStatus_ != E_OK) {
442         return;
443     }
444     if (type != QueryObjType::IN && type != QueryObjType::EQUALTO && type != QueryObjType::AND &&
445         type != QueryObjType::OR) {
446         validStatus_ = -E_NOT_SUPPORT;
447     }
448     if (validStatus_ != E_OK) {
449         return;
450     }
451     for (const auto &item: queryInfo_) {
452         if (((item.operFlag == QueryObjType::EQUALTO) && (type == QueryObjType::IN)) ||
453             ((item.operFlag == QueryObjType::IN) && (type == QueryObjType::EQUALTO))) {
454             validStatus_ = -E_NOT_SUPPORT;
455             LOGW("[Query] Not support use in and equal to at same time when use from table");
456             break;
457         }
458     }
459 }
460 
RangeParamCheck() const461 int QueryExpression::RangeParamCheck() const
462 {
463     if (queryInfo_.size() != 1) { // the query filter must have 1 filter and only the Range query.
464         return -E_INVALID_ARGS;
465     }
466     for (const auto &queryObjNode : queryInfo_) {
467         if (queryObjNode.operFlag != QueryObjType::KEY_RANGE) {
468             return -E_INVALID_ARGS;
469         }
470     }
471     if (this->beginKey_.size() > DBConstant::MAX_KEY_SIZE ||
472         this->endKey_.size() > DBConstant::MAX_KEY_SIZE) {
473         return -E_INVALID_ARGS;
474     }
475     return E_OK;
476 }
477 } // namespace DistributedDB
478