• 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 
197     (void)parcel.WriteString(MAGIC);
198     (void)parcel.WriteUInt32(context.version);
199     (void)parcel.WriteVectorChar(context.prefixKey);
200     (void)parcel.WriteString(context.suggestIndex);
201     (void)parcel.WriteUInt32(context.queryObjNodes.size());
202 
203     parcel.EightByteAlign();
204 
205     for (const QueryObjNode &node : context.queryObjNodes) {
206         errCode = SerializeDataObjNode(parcel, node);
207         if (errCode != E_OK) {
208             return errCode;
209         }
210     }
211 
212     // QUERY_SYNC_OBJECT_VERSION_1 added.
213     if (context.version >= QUERY_SYNC_OBJECT_VERSION_1) {
214         (void)parcel.WriteUInt32(static_cast<uint32_t>(isTableNameSpecified_));
215         if (isTableNameSpecified_) {
216             (void)parcel.WriteString(tableName_);
217         }
218         (void)parcel.WriteUInt32(keys_.size());
219         for (const auto &key : keys_) {
220             (void)parcel.WriteVectorChar(key);
221         }
222     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
223 
224     if (parcel.IsError()) { // parcel almost success
225         return -E_INVALID_ARGS;
226     }
227     parcel.EightByteAlign();
228     return E_OK;
229 }
230 
231 namespace {
DeSerializeVersion1Data(uint32_t version,Parcel & parcel,std::string & tableName,std::set<Key> & keys)232 int DeSerializeVersion1Data(uint32_t version, Parcel &parcel, std::string &tableName, std::set<Key> &keys)
233 {
234     if (version >= QUERY_SYNC_OBJECT_VERSION_1) {
235         uint32_t isTblNameExist = 0;
236         (void)parcel.ReadUInt32(isTblNameExist);
237         if (isTblNameExist) {
238             (void)parcel.ReadString(tableName);
239         }
240         uint32_t keysSize = 0;
241         (void)parcel.ReadUInt32(keysSize);
242         if (keysSize > DBConstant::MAX_INKEYS_SIZE) {
243             return -E_PARSE_FAIL;
244         }
245         for (uint32_t i = 0; i < keysSize; ++i) {
246             Key key;
247             (void)parcel.ReadVector(key);
248             keys.emplace(key);
249         }
250     }
251     return E_OK;
252 }
253 }
254 
DeSerializeData(Parcel & parcel,QuerySyncObject & queryObj)255 int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj)
256 {
257     std::string magic;
258     (void)parcel.ReadString(magic);
259     if (magic != MAGIC) {
260         return -E_INVALID_ARGS;
261     }
262 
263     ObjContext context;
264     (void)parcel.ReadUInt32(context.version);
265     if (context.version > QUERY_SYNC_OBJECT_VERSION_CURRENT) {
266         LOGE("Parcel version and deserialize version not matched! ver=%u", context.version);
267         return -E_VERSION_NOT_SUPPORT;
268     }
269 
270     (void)parcel.ReadVectorChar(context.prefixKey);
271     (void)parcel.ReadString(context.suggestIndex);
272 
273     uint32_t nodesSize = 0;
274     (void)parcel.ReadUInt32(nodesSize);
275     if (parcel.IsError()) { // almost success
276         return -E_INVALID_ARGS;
277     }
278     parcel.EightByteAlign();
279     for (size_t i = 0; i < nodesSize; i++) {
280         QueryObjNode node;
281         int errCode = DeSerializeDataObjNode(parcel, node);
282         if (errCode != E_OK) {
283             return errCode;
284         }
285         context.queryObjNodes.emplace_back(node);
286     }
287 
288     // QUERY_SYNC_OBJECT_VERSION_1 added.
289     std::string tableName;
290     std::set<Key> keys;
291     int errCode = DeSerializeVersion1Data(context.version, parcel, tableName, keys);
292     if (errCode != E_OK) {
293         return errCode;
294     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
295 
296     if (parcel.IsError()) { // almost success
297         return -E_INVALID_ARGS;
298     }
299     queryObj = QuerySyncObject(context.queryObjNodes, context.prefixKey, keys);
300     if (!tableName.empty()) {
301         queryObj.SetTableName(tableName);
302     }
303     return E_OK;
304 }
305 
CalculateLen() const306 uint32_t QuerySyncObject::CalculateLen() const
307 {
308     uint64_t len = Parcel::GetStringLen(MAGIC);
309     len += Parcel::GetUInt32Len(); // version
310     len += Parcel::GetVectorCharLen(prefixKey_);
311     len += Parcel::GetStringLen(suggestIndex_);
312     len += Parcel::GetUInt32Len(); // nodes size
313     len = Parcel::GetEightByteAlign(len);
314     for (const QueryObjNode &node : queryObjNodes_) {
315         if (node.operFlag == QueryObjType::OPER_ILLEGAL) {
316             LOGE("contain illegal operator for query sync!");
317             return 0;
318         }
319         // operflag, fieldName, query value type, value size, union max size, string value
320         len += Parcel::GetUInt32Len();
321         len = Parcel::GetEightByteAlign(len);
322         len += Parcel::GetStringLen(node.fieldName) +
323             Parcel::GetIntLen() + Parcel::GetUInt32Len();
324         for (size_t i = 0; i < node.fieldValue.size(); i++) {
325             len += Parcel::GetInt64Len() + Parcel::GetStringLen(node.fieldValue[i].stringValue);
326         }
327     }
328 
329     // QUERY_SYNC_OBJECT_VERSION_1 added.
330     len += Parcel::GetUInt32Len(); // whether the table name exists.
331     if (isTableNameSpecified_) {
332         len += Parcel::GetStringLen(tableName_);
333     }
334     len += Parcel::GetUInt32Len(); // size of keys_
335     for (const auto &key : keys_) {
336         len += Parcel::GetVectorCharLen(key);
337     }  // QUERY_SYNC_OBJECT_VERSION_1 end.
338 
339     len = Parcel::GetEightByteAlign(len);
340     if (len > INT32_MAX) {
341         return 0;
342     }
343     return static_cast<uint32_t>(len);
344 }
345 
GetRelationTableName() const346 std::string QuerySyncObject::GetRelationTableName() const
347 {
348     if (!isTableNameSpecified_) {
349         return {};
350     }
351     return tableName_;
352 }
353 }