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