• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_sync_object.h"
17 
18 #include "cloud/cloud_db_constant.h"
19 #include "db_common.h"
20 #include "db_errno.h"
21 #include "log_print.h"
22 #include "version.h"
23 
24 namespace DistributedDB {
25 namespace {
26 const std::string MAGIC = "remote query";
27 // Max value size of each QueryObjNode, current is In & NotIn predicate which is 128
28 const int MAX_VALUE_SIZE = 128;
29 const int MAX_QUERY_NODE_SIZE = 256;
30 
SerializeDataObjNode(Parcel & parcel,const QueryObjNode & objNode)31 int SerializeDataObjNode(Parcel &parcel, const QueryObjNode &objNode)
32 {
33     if (objNode.operFlag == QueryObjType::OPER_ILLEGAL) {
34         return -E_INVALID_QUERY_FORMAT;
35     }
36     (void)parcel.WriteUInt32(static_cast<uint32_t>(objNode.operFlag));
37     parcel.EightByteAlign();
38     (void)parcel.WriteString(objNode.fieldName);
39     (void)parcel.WriteInt(static_cast<int32_t>(objNode.type));
40     (void)parcel.WriteUInt32(objNode.fieldValue.size());
41 
42     for (const FieldValue &value : objNode.fieldValue) {
43         (void)parcel.WriteString(value.stringValue);
44 
45         // string may not closely arranged continuously
46         // longValue is maximum length in union
47         (void)parcel.WriteInt64(value.longValue);
48     }
49     if (parcel.IsError()) {
50         return -E_INVALID_ARGS;
51     }
52     return E_OK;
53 }
54 
DeSerializeDataObjNode(Parcel & parcel,QueryObjNode & objNode)55 int DeSerializeDataObjNode(Parcel &parcel, QueryObjNode &objNode)
56 {
57     uint32_t readOperFlag = 0;
58     (void)parcel.ReadUInt32(readOperFlag);
59     objNode.operFlag = static_cast<QueryObjType>(readOperFlag);
60     parcel.EightByteAlign();
61 
62     (void)parcel.ReadString(objNode.fieldName);
63 
64     int readInt = -1;
65     (void)parcel.ReadInt(readInt);
66     objNode.type = static_cast<QueryValueType>(readInt);
67 
68     uint32_t valueSize = 0;
69     (void)parcel.ReadUInt32(valueSize);
70     if (parcel.IsError() || valueSize > MAX_VALUE_SIZE) {
71         return -E_INVALID_ARGS;
72     }
73 
74     for (size_t i = 0; i < valueSize; i++) {
75         FieldValue value;
76         (void)parcel.ReadString(value.stringValue);
77 
78         (void)parcel.ReadInt64(value.longValue);
79         if (parcel.IsError()) {
80             return -E_INVALID_ARGS;
81         }
82         objNode.fieldValue.push_back(value);
83     }
84     return E_OK;
85 }
86 }
87 
QuerySyncObject()88 QuerySyncObject::QuerySyncObject()
89 {}
90 
QuerySyncObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)91 QuerySyncObject::QuerySyncObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
92     const std::set<Key> &keys)
93     : QueryObject(queryObjNodes, prefixKey, keys)
94 {}
95 
QuerySyncObject(const Query & query)96 QuerySyncObject::QuerySyncObject(const Query &query)
97     : QueryObject(query)
98 {}
99 
QuerySyncObject(const DistributedDB::QueryExpression & expression)100 QuerySyncObject::QuerySyncObject(const DistributedDB::QueryExpression &expression)
101     : QueryObject(expression)
102 {}
103 
~QuerySyncObject()104 QuerySyncObject::~QuerySyncObject()
105 {}
106 
GetVersion() const107 uint32_t QuerySyncObject::GetVersion() const
108 {
109     uint32_t version = QUERY_SYNC_OBJECT_VERSION_0;
110     if (isTableNameSpecified_ || !keys_.empty()) {
111         version = QUERY_SYNC_OBJECT_VERSION_1;
112     }
113     return version;
114 }
115 
GetObjContext(ObjContext & objContext) const116 int QuerySyncObject::GetObjContext(ObjContext &objContext) const
117 {
118     if (!isValid_) {
119         return -E_INVALID_QUERY_FORMAT;
120     }
121     objContext.version = GetVersion();
122     objContext.prefixKey.assign(prefixKey_.begin(), prefixKey_.end());
123     objContext.suggestIndex = suggestIndex_;
124     objContext.queryObjNodes = queryObjNodes_;
125     return E_OK;
126 }
127 
CalculateIdentifyLen() const128 uint32_t QuerySyncObject::CalculateIdentifyLen() const
129 {
130     uint64_t len = Parcel::GetVectorCharLen(prefixKey_);
131     for (const QueryObjNode &node : queryObjNodes_) {
132         if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY ||
133             node.operFlag == QueryObjType::SUGGEST_INDEX) {
134             continue;
135         }
136         // operFlag and valueType is int
137         len += Parcel::GetUInt32Len() + Parcel::GetIntLen() + Parcel::GetStringLen(node.fieldName);
138         for (const FieldValue &value : node.fieldValue) {
139             len += Parcel::GetStringLen(value.stringValue) + Parcel::GetInt64Len();
140         }
141     }
142 
143     // QUERY_SYNC_OBJECT_VERSION_1 added.
144     len += isTableNameSpecified_ ? Parcel::GetStringLen(tableName_) : 0;
145     for (const auto &key : keys_) {
146         len += Parcel::GetVectorCharLen(key);
147     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
148     return len;
149 }
150 
GetIdentify() const151 std::string QuerySyncObject::GetIdentify() const
152 {
153     if (!isValid_) {
154         return std::string();
155     }
156     if (!identify_.empty()) {
157         return identify_;
158     }
159     // suggestionIndex is local attribute, do not need to be propagated to remote
160     uint64_t len = CalculateIdentifyLen();
161     std::vector<uint8_t> buff(len, 0); // It will affect the hash result, the default value cannot be modified
162     Parcel parcel(buff.data(), len);
163 
164     // The order needs to be consistent, otherwise it will affect the hash result
165     (void)parcel.WriteVectorChar(prefixKey_);
166     for (const QueryObjNode &node : queryObjNodes_) {
167         if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY ||
168             node.operFlag == QueryObjType::SUGGEST_INDEX) {
169             continue;
170         }
171         (void)parcel.WriteUInt32(static_cast<uint32_t>(node.operFlag));
172         (void)parcel.WriteInt(static_cast<int32_t>(node.type));
173         (void)parcel.WriteString(node.fieldName);
174         for (const FieldValue &value : node.fieldValue) {
175             (void)parcel.WriteInt64(value.longValue);
176             (void)parcel.WriteString(value.stringValue);
177         }
178     }
179 
180     // QUERY_SYNC_OBJECT_VERSION_1 added.
181     if (isTableNameSpecified_) {
182         (void)parcel.WriteString(tableName_);
183     }
184     for (const auto &key : keys_) {
185         (void)parcel.WriteVectorChar(key);
186     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
187 
188     std::vector<uint8_t> hashBuff;
189     if (parcel.IsError() || DBCommon::CalcValueHash(buff, hashBuff) != E_OK) {
190         return std::string();
191     }
192     identify_ = DBCommon::VectorToHexString(hashBuff);
193     return identify_;
194 }
195 
CalculateParcelLen(uint32_t softWareVersion) const196 uint32_t QuerySyncObject::CalculateParcelLen(uint32_t softWareVersion) const
197 {
198     if (softWareVersion == SOFTWARE_VERSION_CURRENT) {
199         return CalculateLen();
200     }
201     LOGE("current not support!");
202     return 0;
203 }
204 
SerializeData(Parcel & parcel,uint32_t softWareVersion)205 int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion)
206 {
207     ObjContext context;
208     int errCode = GetObjContext(context);
209     if (errCode != E_OK) {
210         return errCode;
211     }
212     (void)parcel.WriteString(MAGIC);
213     (void)parcel.WriteUInt32(context.version);
214     (void)parcel.WriteVectorChar(context.prefixKey);
215     (void)parcel.WriteString(context.suggestIndex);
216     (void)parcel.WriteUInt32(context.queryObjNodes.size());
217     parcel.EightByteAlign();
218     if (parcel.IsError()) {
219         LOGE("[QuerySyncObject] [SerializeData] parcel is error.");
220         return -E_INVALID_ARGS;
221     }
222     for (const QueryObjNode &node : context.queryObjNodes) {
223         errCode = SerializeDataObjNode(parcel, node);
224         if (errCode != E_OK) {
225             return errCode;
226         }
227     }
228 
229     // QUERY_SYNC_OBJECT_VERSION_1 added.
230     if (context.version >= QUERY_SYNC_OBJECT_VERSION_1) {
231         (void)parcel.WriteUInt32(static_cast<uint32_t>(isTableNameSpecified_));
232         if (isTableNameSpecified_) {
233             (void)parcel.WriteString(tableName_);
234         }
235         (void)parcel.WriteUInt32(keys_.size());
236         for (const auto &key : keys_) {
237             (void)parcel.WriteVectorChar(key);
238         }
239     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
240     parcel.EightByteAlign();
241     if (parcel.IsError()) { // parcel almost success
242         LOGE("[QuerySyncObject] [SerializeData] After version 1, parcel is error.");
243         return -E_INVALID_ARGS;
244     }
245     return E_OK;
246 }
247 
SetCloudGid(const std::vector<std::string> & cloudGid)248 void QuerySyncObject::SetCloudGid(const std::vector<std::string> &cloudGid)
249 {
250     int emptyGidCount = 0;
251     for (size_t i = 0; i < cloudGid.size(); i+= MAX_VALUE_SIZE) {
252         size_t end = std::min(i + MAX_VALUE_SIZE, cloudGid.size());
253         if (!queryObjNodes_.empty()) {
254             QueryObjNode operateNode;
255             operateNode.operFlag = QueryObjType::OR;
256             operateNode.type = QueryValueType::VALUE_TYPE_NULL;
257             queryObjNodes_.emplace_back(operateNode);
258         }
259 
260         QueryObjNode objNode;
261         objNode.operFlag = QueryObjType::IN;
262         objNode.fieldName = CloudDbConstant::GID_FIELD;
263         objNode.type = QueryValueType::VALUE_TYPE_STRING;
264         std::vector<std::string> subCloudGid(cloudGid.begin() + i, cloudGid.begin() + end);
265         for (const auto &gid : subCloudGid) {
266             if (gid.empty()) {
267                 emptyGidCount++;
268                 continue;
269             }
270             FieldValue fieldValue;
271             fieldValue.stringValue = gid;
272             objNode.fieldValue.emplace_back(fieldValue);
273         }
274         queryObjNodes_.emplace_back(objNode);
275     }
276     LOGI("[QuerySyncObject] [SetCloudGid] gid empty count is %d", emptyGidCount);
277 }
278 
279 namespace {
DeSerializeVersion1Data(uint32_t version,Parcel & parcel,std::string & tableName,std::set<Key> & keys)280 int DeSerializeVersion1Data(uint32_t version, Parcel &parcel, std::string &tableName, std::set<Key> &keys)
281 {
282     if (version >= QUERY_SYNC_OBJECT_VERSION_1) {
283         uint32_t isTblNameExist = 0;
284         (void)parcel.ReadUInt32(isTblNameExist);
285         if (isTblNameExist) {
286             (void)parcel.ReadString(tableName);
287         }
288         uint32_t keysSize = 0;
289         (void)parcel.ReadUInt32(keysSize);
290         if (keysSize > DBConstant::MAX_INKEYS_SIZE) {
291             LOGE("[DeSerializeVersion1Data] keys size %" PRIu32 " is too large", keysSize);
292             return -E_PARSE_FAIL;
293         }
294         for (uint32_t i = 0; i < keysSize; ++i) {
295             Key key;
296             (void)parcel.ReadVector(key);
297             keys.emplace(key);
298         }
299     }
300     return E_OK;
301 }
302 }
303 
DeSerializeData(Parcel & parcel,QuerySyncObject & queryObj)304 int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj)
305 {
306     std::string magic;
307     (void)parcel.ReadString(magic);
308     if (magic != MAGIC) {
309         return -E_INVALID_ARGS;
310     }
311 
312     ObjContext context;
313     (void)parcel.ReadUInt32(context.version);
314     if (context.version > QUERY_SYNC_OBJECT_VERSION_CURRENT) {
315         LOGE("Parcel version and deserialize version not matched! ver=%u", context.version);
316         return -E_VERSION_NOT_SUPPORT;
317     }
318 
319     (void)parcel.ReadVectorChar(context.prefixKey);
320     (void)parcel.ReadString(context.suggestIndex);
321 
322     uint32_t nodesSize = 0;
323     (void)parcel.ReadUInt32(nodesSize);
324     parcel.EightByteAlign();
325     // Due to historical reasons, the limit of query node size was incorrectly set to MAX_QUERY_NODE_SIZE + 1
326     if (parcel.IsError() || nodesSize > MAX_QUERY_NODE_SIZE + 1) { // almost success
327         LOGE("[QuerySyncObject] [DeSerializeData] parcel is error or nodes size is too large.");
328         return -E_INVALID_ARGS;
329     }
330     for (size_t i = 0; i < nodesSize; i++) {
331         QueryObjNode node;
332         int errCode = DeSerializeDataObjNode(parcel, node);
333         if (errCode != E_OK) {
334             return errCode;
335         }
336         context.queryObjNodes.emplace_back(node);
337     }
338 
339     // QUERY_SYNC_OBJECT_VERSION_1 added.
340     std::string tableName;
341     std::set<Key> keys;
342     int errCode = DeSerializeVersion1Data(context.version, parcel, tableName, keys);
343     if (errCode != E_OK) {
344         return errCode;
345     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
346 
347     if (parcel.IsError()) { // almost success
348         LOGE("[QuerySyncObject] [DeSerializeData] After version 1, parcel is error.");
349         return -E_INVALID_ARGS;
350     }
351     queryObj = QuerySyncObject(context.queryObjNodes, context.prefixKey, keys);
352     if (!tableName.empty()) {
353         queryObj.SetTableName(tableName);
354     }
355     return E_OK;
356 }
357 
CalculateLen() const358 uint32_t QuerySyncObject::CalculateLen() const
359 {
360     uint64_t len = Parcel::GetStringLen(MAGIC);
361     len += Parcel::GetUInt32Len(); // version
362     len += Parcel::GetVectorCharLen(prefixKey_);
363     len += Parcel::GetStringLen(suggestIndex_);
364     len += Parcel::GetUInt32Len(); // nodes size
365     len = Parcel::GetEightByteAlign(len);
366     for (const QueryObjNode &node : queryObjNodes_) {
367         if (node.operFlag == QueryObjType::OPER_ILLEGAL) {
368             LOGE("contain illegal operator for query sync!");
369             return 0;
370         }
371         // operflag, fieldName, query value type, value size, union max size, string value
372         len += Parcel::GetUInt32Len();
373         len = Parcel::GetEightByteAlign(len);
374         len += Parcel::GetStringLen(node.fieldName) +
375             Parcel::GetIntLen() + Parcel::GetUInt32Len();
376         for (size_t i = 0; i < node.fieldValue.size(); i++) {
377             len += Parcel::GetInt64Len() + Parcel::GetStringLen(node.fieldValue[i].stringValue);
378         }
379     }
380 
381     // QUERY_SYNC_OBJECT_VERSION_1 added.
382     len += Parcel::GetUInt32Len(); // whether the table name exists.
383     if (isTableNameSpecified_) {
384         len += Parcel::GetStringLen(tableName_);
385     }
386     len += Parcel::GetUInt32Len(); // size of keys_
387     for (const auto &key : keys_) {
388         len += Parcel::GetVectorCharLen(key);
389     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
390 
391     len = Parcel::GetEightByteAlign(len);
392     if (len > INT32_MAX) {
393         return 0;
394     }
395     return static_cast<uint32_t>(len);
396 }
397 
GetRelationTableName() const398 std::string QuerySyncObject::GetRelationTableName() const
399 {
400     if (!isTableNameSpecified_) {
401         return {};
402     }
403     return tableName_;
404 }
405 
GetRelationTableNames() const406 std::vector<std::string> QuerySyncObject::GetRelationTableNames() const
407 {
408     return tables_;
409 }
410 
GetValidStatus() const411 int QuerySyncObject::GetValidStatus() const
412 {
413     return validStatus;
414 }
415 
IsContainQueryNodes() const416 bool QuerySyncObject::IsContainQueryNodes() const
417 {
418     return !queryObjNodes_.empty();
419 }
420 
IsInValueOutOfLimit() const421 bool QuerySyncObject::IsInValueOutOfLimit() const
422 {
423     for (const auto &queryObjNode : queryObjNodes_) {
424         if ((queryObjNode.operFlag == QueryObjType::IN) &&
425             (queryObjNode.fieldValue.size() > DBConstant::MAX_IN_COUNT)) {
426             return false;
427         }
428     }
429     return true;
430 }
431 
GetQuerySyncObject(const DistributedDB::Query & query)432 std::vector<QuerySyncObject> QuerySyncObject::GetQuerySyncObject(const DistributedDB::Query &query)
433 {
434     std::vector<QuerySyncObject> res;
435     const auto &expressions = QueryObject::GetQueryExpressions(query);
436     for (const auto &item : expressions) {
437         res.push_back(QuerySyncObject(item));
438     }
439     return res;
440 }
441 
ParserQueryNodes(const Bytes & bytes,std::vector<QueryNode> & queryNodes)442 int QuerySyncObject::ParserQueryNodes(const Bytes &bytes, std::vector<QueryNode> &queryNodes)
443 {
444     QuerySyncObject tmp;
445     Bytes parcelBytes = bytes;
446     Parcel parcel(parcelBytes.data(), parcelBytes.size());
447     int errCode = DeSerializeData(parcel, tmp);
448     if (errCode != E_OK) {
449         return errCode;
450     }
451     for (const auto &objNode: tmp.queryObjNodes_) {
452         QueryNode node;
453         errCode = TransformToQueryNode(objNode, node);
454         if (errCode != E_OK) {
455             return errCode;
456         }
457         queryNodes.push_back(std::move(node));
458     }
459     return E_OK;
460 }
461 
TransformToQueryNode(const QueryObjNode & objNode,QueryNode & node)462 int QuerySyncObject::TransformToQueryNode(const QueryObjNode &objNode, QueryNode &node)
463 {
464     int errCode = TransformValueToType(objNode, node.fieldValue);
465     if (errCode != E_OK) {
466         LOGE("[Query] transform value to type failed %d", errCode);
467         return errCode;
468     }
469     node.fieldName = objNode.fieldName;
470     return TransformNodeType(objNode, node);
471 }
472 
TransformValueToType(const QueryObjNode & objNode,std::vector<Type> & types)473 int QuerySyncObject::TransformValueToType(const QueryObjNode &objNode, std::vector<Type> &types)
474 {
475     for (const auto &value: objNode.fieldValue) {
476         switch (objNode.type) {
477             case QueryValueType::VALUE_TYPE_STRING:
478                 types.emplace_back(value.stringValue);
479                 break;
480             case QueryValueType::VALUE_TYPE_BOOL:
481                 types.emplace_back(value.boolValue);
482                 break;
483             case QueryValueType::VALUE_TYPE_NULL:
484                 types.emplace_back(Nil());
485                 break;
486             case QueryValueType::VALUE_TYPE_INTEGER:
487             case QueryValueType::VALUE_TYPE_LONG:
488                 types.emplace_back(static_cast<int64_t>(value.integerValue));
489                 break;
490             case QueryValueType::VALUE_TYPE_DOUBLE:
491                 types.emplace_back(value.doubleValue);
492                 break;
493             case QueryValueType::VALUE_TYPE_INVALID:
494                 return -E_INVALID_ARGS;
495         }
496     }
497     return E_OK;
498 }
499 
TransformNodeType(const QueryObjNode & objNode,QueryNode & node)500 int QuerySyncObject::TransformNodeType(const QueryObjNode &objNode, QueryNode &node)
501 {
502     int errCode = E_OK;
503     switch (objNode.operFlag) {
504         case QueryObjType::IN:
505             node.type = QueryNodeType::IN;
506             break;
507         case QueryObjType::OR:
508             node.type = QueryNodeType::OR;
509             break;
510         case QueryObjType::AND:
511             node.type = QueryNodeType::AND;
512             break;
513         case QueryObjType::EQUALTO:
514             node.type = QueryNodeType::EQUAL_TO;
515             break;
516         case QueryObjType::BEGIN_GROUP:
517             node.type = QueryNodeType::BEGIN_GROUP;
518             break;
519         case QueryObjType::END_GROUP:
520             node.type = QueryNodeType::END_GROUP;
521             break;
522         case QueryObjType::IN_KEYS:
523             node.fieldName = CloudDbConstant::CLOUD_KV_FIELD_KEY;
524             node.type = QueryNodeType::IN;
525             break;
526         default:
527             LOGE("[Query] not support type %d", static_cast<int>(objNode.operFlag));
528             errCode = -E_NOT_SUPPORT;
529             node.type = QueryNodeType::ILLEGAL;
530     }
531     return errCode;
532 }
533 
GetQuerySyncObjectFromGroup(int64_t groupId,QuerySyncObject & obj)534 int QuerySyncObject::GetQuerySyncObjectFromGroup(int64_t groupId, QuerySyncObject &obj)
535 {
536     obj = *this;
537     if (groupNum_ <= 1) {
538         return E_OK;
539     }
540     // find the begin group node
541     bool isFindBeginGroup = false;
542     int64_t beginGroupIndex = 0;
543     for (auto iter = obj.queryObjNodes_.begin(); iter != obj.queryObjNodes_.end();) {
544         if ((*iter).operFlag != QueryObjType::BEGIN_GROUP) {
545             // eraes the node which is before the begin group node
546             iter = obj.queryObjNodes_.erase(iter);
547             continue;
548         } else if (beginGroupIndex != groupId) {
549             // eraes the node which is before the begin group node
550             iter = obj.queryObjNodes_.erase(iter);
551             beginGroupIndex++;
552             continue;
553         } else {
554             isFindBeginGroup = true;
555             break;
556         }
557     }
558     if (!isFindBeginGroup) {
559         LOGE("can not find the begin group node, groupid %u", groupId);
560         return -E_INVALID_ARGS;
561     }
562 
563     // find the end group node
564     bool isFindEndGroup = false;
565     for (auto iter = obj.queryObjNodes_.begin(); iter != obj.queryObjNodes_.end();) {
566         if (isFindEndGroup) {
567             // eraes the node which is behind the end group node
568             iter = obj.queryObjNodes_.erase(iter);
569             continue;
570         } else if ((*iter).operFlag == QueryObjType::END_GROUP) {
571             isFindEndGroup = true;
572         }
573         ++iter;
574     }
575     if (!isFindEndGroup) {
576         LOGE("can not find the end group node, groupid %u", groupId);
577         return -E_INVALID_ARGS;
578     }
579     return E_OK;
580 }
581 } // namespace DistributedDB