• 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 "db_common.h"
19 #include "db_errno.h"
20 #include "log_print.h"
21 #include "version.h"
22 
23 namespace DistributedDB {
24 namespace {
25 const std::string MAGIC = "remote query";
26 // Max value size of each QueryObjNode, current is In & NotIn predicate which is 128
27 const int MAX_VALUE_SIZE = 128;
28 const int MAX_QUERY_NODE_SIZE = 256;
29 
SerializeDataObjNode(Parcel & parcel,const QueryObjNode & objNode)30 int SerializeDataObjNode(Parcel &parcel, const QueryObjNode &objNode)
31 {
32     if (objNode.operFlag == QueryObjType::OPER_ILLEGAL) {
33         return -E_INVALID_QUERY_FORMAT;
34     }
35     (void)parcel.WriteUInt32(static_cast<uint32_t>(objNode.operFlag));
36     parcel.EightByteAlign();
37     (void)parcel.WriteString(objNode.fieldName);
38     (void)parcel.WriteInt(static_cast<int32_t>(objNode.type));
39     (void)parcel.WriteUInt32(objNode.fieldValue.size());
40 
41     for (const FieldValue &value : objNode.fieldValue) {
42         (void)parcel.WriteString(value.stringValue);
43 
44         // string may not closely arranged continuously
45         // longValue is maximum length in union
46         (void)parcel.WriteInt64(value.longValue);
47     }
48     if (parcel.IsError()) {
49         return -E_INVALID_ARGS;
50     }
51     return E_OK;
52 }
53 
DeSerializeDataObjNode(Parcel & parcel,QueryObjNode & objNode)54 int DeSerializeDataObjNode(Parcel &parcel, QueryObjNode &objNode)
55 {
56     uint32_t readOperFlag = 0;
57     (void)parcel.ReadUInt32(readOperFlag);
58     objNode.operFlag = static_cast<QueryObjType>(readOperFlag);
59     parcel.EightByteAlign();
60 
61     (void)parcel.ReadString(objNode.fieldName);
62 
63     int readInt = -1;
64     (void)parcel.ReadInt(readInt);
65     objNode.type = static_cast<QueryValueType>(readInt);
66 
67     uint32_t valueSize = 0;
68     (void)parcel.ReadUInt32(valueSize);
69     if (parcel.IsError() || valueSize > MAX_VALUE_SIZE) {
70         return -E_INVALID_ARGS;
71     }
72 
73     for (size_t i = 0; i < valueSize; i++) {
74         FieldValue value;
75         (void)parcel.ReadString(value.stringValue);
76 
77         (void)parcel.ReadInt64(value.longValue);
78         if (parcel.IsError()) {
79             return -E_INVALID_ARGS;
80         }
81         objNode.fieldValue.push_back(value);
82     }
83     return E_OK;
84 }
85 }
86 
QuerySyncObject()87 QuerySyncObject::QuerySyncObject()
88 {}
89 
QuerySyncObject(const std::list<QueryObjNode> & queryObjNodes,const std::vector<uint8_t> & prefixKey,const std::set<Key> & keys)90 QuerySyncObject::QuerySyncObject(const std::list<QueryObjNode> &queryObjNodes, const std::vector<uint8_t> &prefixKey,
91     const std::set<Key> &keys)
92     : QueryObject(queryObjNodes, prefixKey, keys)
93 {}
94 
QuerySyncObject(const Query & query)95 QuerySyncObject::QuerySyncObject(const Query &query)
96     : QueryObject(query)
97 {}
98 
~QuerySyncObject()99 QuerySyncObject::~QuerySyncObject()
100 {}
101 
GetVersion() const102 uint32_t QuerySyncObject::GetVersion() const
103 {
104     uint32_t version = QUERY_SYNC_OBJECT_VERSION_0;
105     if (isTableNameSpecified_ || !keys_.empty()) {
106         version = QUERY_SYNC_OBJECT_VERSION_1;
107     }
108     return version;
109 }
110 
GetObjContext(ObjContext & objContext) const111 int QuerySyncObject::GetObjContext(ObjContext &objContext) const
112 {
113     if (!isValid_) {
114         return -E_INVALID_QUERY_FORMAT;
115     }
116     objContext.version = GetVersion();
117     objContext.prefixKey.assign(prefixKey_.begin(), prefixKey_.end());
118     objContext.suggestIndex = suggestIndex_;
119     objContext.queryObjNodes = queryObjNodes_;
120     return E_OK;
121 }
122 
CalculateIdentifyLen() const123 uint32_t QuerySyncObject::CalculateIdentifyLen() const
124 {
125     uint64_t len = Parcel::GetVectorCharLen(prefixKey_);
126     for (const QueryObjNode &node : queryObjNodes_) {
127         if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY ||
128             node.operFlag == QueryObjType::SUGGEST_INDEX) {
129             continue;
130         }
131         // operFlag and valueType is int
132         len += Parcel::GetUInt32Len() + Parcel::GetIntLen() + Parcel::GetStringLen(node.fieldName);
133         for (const FieldValue &value : node.fieldValue) {
134             len += Parcel::GetStringLen(value.stringValue) + Parcel::GetInt64Len();
135         }
136     }
137 
138     // QUERY_SYNC_OBJECT_VERSION_1 added.
139     len += isTableNameSpecified_ ? Parcel::GetStringLen(tableName_) : 0;
140     for (const auto &key : keys_) {
141         len += Parcel::GetVectorCharLen(key);
142     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
143     return len;
144 }
145 
GetIdentify() const146 std::string QuerySyncObject::GetIdentify() const
147 {
148     if (!isValid_) {
149         return std::string();
150     }
151     if (!identify_.empty()) {
152         return identify_;
153     }
154     // suggestionIndex is local attribute, do not need to be propagated to remote
155     uint64_t len = CalculateIdentifyLen();
156     std::vector<uint8_t> buff(len, 0); // It will affect the hash result, the default value cannot be modified
157     Parcel parcel(buff.data(), len);
158 
159     // The order needs to be consistent, otherwise it will affect the hash result
160     (void)parcel.WriteVectorChar(prefixKey_);
161     for (const QueryObjNode &node : queryObjNodes_) {
162         if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY ||
163             node.operFlag == QueryObjType::SUGGEST_INDEX) {
164             continue;
165         }
166         (void)parcel.WriteUInt32(static_cast<uint32_t>(node.operFlag));
167         (void)parcel.WriteInt(static_cast<int32_t>(node.type));
168         (void)parcel.WriteString(node.fieldName);
169         for (const FieldValue &value : node.fieldValue) {
170             (void)parcel.WriteInt64(value.longValue);
171             (void)parcel.WriteString(value.stringValue);
172         }
173     }
174 
175     // QUERY_SYNC_OBJECT_VERSION_1 added.
176     if (isTableNameSpecified_) {
177         (void)parcel.WriteString(tableName_);
178     }
179     for (const auto &key : keys_) {
180         (void)parcel.WriteVectorChar(key);
181     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
182 
183     std::vector<uint8_t> hashBuff;
184     if (parcel.IsError() || DBCommon::CalcValueHash(buff, hashBuff) != E_OK) {
185         return std::string();
186     }
187     identify_ = DBCommon::VectorToHexString(hashBuff);
188     return identify_;
189 }
190 
CalculateParcelLen(uint32_t softWareVersion) const191 uint32_t QuerySyncObject::CalculateParcelLen(uint32_t softWareVersion) const
192 {
193     if (softWareVersion == SOFTWARE_VERSION_CURRENT) {
194         return CalculateLen();
195     }
196     LOGE("current not support!");
197     return 0;
198 }
199 
SerializeData(Parcel & parcel,uint32_t softWareVersion)200 int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion)
201 {
202     ObjContext context;
203     int errCode = GetObjContext(context);
204     if (errCode != E_OK) {
205         return errCode;
206     }
207     (void)parcel.WriteString(MAGIC);
208     (void)parcel.WriteUInt32(context.version);
209     (void)parcel.WriteVectorChar(context.prefixKey);
210     (void)parcel.WriteString(context.suggestIndex);
211     (void)parcel.WriteUInt32(context.queryObjNodes.size());
212     parcel.EightByteAlign();
213     if (parcel.IsError()) {
214         return -E_INVALID_ARGS;
215     }
216     for (const QueryObjNode &node : context.queryObjNodes) {
217         errCode = SerializeDataObjNode(parcel, node);
218         if (errCode != E_OK) {
219             return errCode;
220         }
221     }
222 
223     // QUERY_SYNC_OBJECT_VERSION_1 added.
224     if (context.version >= QUERY_SYNC_OBJECT_VERSION_1) {
225         (void)parcel.WriteUInt32(static_cast<uint32_t>(isTableNameSpecified_));
226         if (isTableNameSpecified_) {
227             (void)parcel.WriteString(tableName_);
228         }
229         (void)parcel.WriteUInt32(keys_.size());
230         for (const auto &key : keys_) {
231             (void)parcel.WriteVectorChar(key);
232         }
233     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
234     parcel.EightByteAlign();
235     if (parcel.IsError()) { // parcel almost success
236         return -E_INVALID_ARGS;
237     }
238     return E_OK;
239 }
240 
241 namespace {
DeSerializeVersion1Data(uint32_t version,Parcel & parcel,std::string & tableName,std::set<Key> & keys)242 int DeSerializeVersion1Data(uint32_t version, Parcel &parcel, std::string &tableName, std::set<Key> &keys)
243 {
244     if (version >= QUERY_SYNC_OBJECT_VERSION_1) {
245         uint32_t isTblNameExist = 0;
246         (void)parcel.ReadUInt32(isTblNameExist);
247         if (isTblNameExist) {
248             (void)parcel.ReadString(tableName);
249         }
250         uint32_t keysSize = 0;
251         (void)parcel.ReadUInt32(keysSize);
252         if (keysSize > DBConstant::MAX_INKEYS_SIZE) {
253             return -E_PARSE_FAIL;
254         }
255         for (uint32_t i = 0; i < keysSize; ++i) {
256             Key key;
257             (void)parcel.ReadVector(key);
258             keys.emplace(key);
259         }
260     }
261     return E_OK;
262 }
263 }
264 
DeSerializeData(Parcel & parcel,QuerySyncObject & queryObj)265 int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj)
266 {
267     std::string magic;
268     (void)parcel.ReadString(magic);
269     if (magic != MAGIC) {
270         return -E_INVALID_ARGS;
271     }
272 
273     ObjContext context;
274     (void)parcel.ReadUInt32(context.version);
275     if (context.version > QUERY_SYNC_OBJECT_VERSION_CURRENT) {
276         LOGE("Parcel version and deserialize version not matched! ver=%u", context.version);
277         return -E_VERSION_NOT_SUPPORT;
278     }
279 
280     (void)parcel.ReadVectorChar(context.prefixKey);
281     (void)parcel.ReadString(context.suggestIndex);
282 
283     uint32_t nodesSize = 0;
284     (void)parcel.ReadUInt32(nodesSize);
285     parcel.EightByteAlign();
286     // Due to historical reasons, the limit of query node size was incorrectly set to MAX_QUERY_NODE_SIZE + 1
287     if (parcel.IsError() || nodesSize > MAX_QUERY_NODE_SIZE + 1) { // almost success
288         return -E_INVALID_ARGS;
289     }
290     for (size_t i = 0; i < nodesSize; i++) {
291         QueryObjNode node;
292         int errCode = DeSerializeDataObjNode(parcel, node);
293         if (errCode != E_OK) {
294             return errCode;
295         }
296         context.queryObjNodes.emplace_back(node);
297     }
298 
299     // QUERY_SYNC_OBJECT_VERSION_1 added.
300     std::string tableName;
301     std::set<Key> keys;
302     int errCode = DeSerializeVersion1Data(context.version, parcel, tableName, keys);
303     if (errCode != E_OK) {
304         return errCode;
305     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
306 
307     if (parcel.IsError()) { // almost success
308         return -E_INVALID_ARGS;
309     }
310     queryObj = QuerySyncObject(context.queryObjNodes, context.prefixKey, keys);
311     if (!tableName.empty()) {
312         queryObj.SetTableName(tableName);
313     }
314     return E_OK;
315 }
316 
CalculateLen() const317 uint32_t QuerySyncObject::CalculateLen() const
318 {
319     uint64_t len = Parcel::GetStringLen(MAGIC);
320     len += Parcel::GetUInt32Len(); // version
321     len += Parcel::GetVectorCharLen(prefixKey_);
322     len += Parcel::GetStringLen(suggestIndex_);
323     len += Parcel::GetUInt32Len(); // nodes size
324     len = Parcel::GetEightByteAlign(len);
325     for (const QueryObjNode &node : queryObjNodes_) {
326         if (node.operFlag == QueryObjType::OPER_ILLEGAL) {
327             LOGE("contain illegal operator for query sync!");
328             return 0;
329         }
330         // operflag, fieldName, query value type, value size, union max size, string value
331         len += Parcel::GetUInt32Len();
332         len = Parcel::GetEightByteAlign(len);
333         len += Parcel::GetStringLen(node.fieldName) +
334             Parcel::GetIntLen() + Parcel::GetUInt32Len();
335         for (size_t i = 0; i < node.fieldValue.size(); i++) {
336             len += Parcel::GetInt64Len() + Parcel::GetStringLen(node.fieldValue[i].stringValue);
337         }
338     }
339 
340     // QUERY_SYNC_OBJECT_VERSION_1 added.
341     len += Parcel::GetUInt32Len(); // whether the table name exists.
342     if (isTableNameSpecified_) {
343         len += Parcel::GetStringLen(tableName_);
344     }
345     len += Parcel::GetUInt32Len(); // size of keys_
346     for (const auto &key : keys_) {
347         len += Parcel::GetVectorCharLen(key);
348     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
349 
350     len = Parcel::GetEightByteAlign(len);
351     if (len > INT32_MAX) {
352         return 0;
353     }
354     return static_cast<uint32_t>(len);
355 }
356 
GetRelationTableName() const357 std::string QuerySyncObject::GetRelationTableName() const
358 {
359     if (!isTableNameSpecified_) {
360         return {};
361     }
362     return tableName_;
363 }
364 
GetRelationTableNames() const365 std::vector<std::string> QuerySyncObject::GetRelationTableNames() const
366 {
367     return tables_;
368 }
369 
GetIsDeviceSyncQuery() const370 bool QuerySyncObject::GetIsDeviceSyncQuery() const
371 {
372     return isWithDeviceSyncQuery_;
373 }
374 } // namespace DistributedDB