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 }