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