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 }