1 /* 2 * Copyright (c) 2024 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 "relational_store_utils.h" 17 #include "native_log.h" 18 #include "rdb_store.h" 19 20 namespace OHOS { 21 namespace Relational { MallocCString(const std::string & origin)22 char* MallocCString(const std::string& origin) 23 { 24 if (origin.empty()) { 25 return nullptr; 26 } 27 auto len = origin.length() + 1; 28 char* res = static_cast<char*>(malloc(sizeof(char) * len)); 29 if (res == nullptr) { 30 return nullptr; 31 } 32 return std::char_traits<char>::copy(res, origin.c_str(), len); 33 } 34 ValueTypeToValueObjectBlob(const ValueType & value)35 NativeRdb::ValueObject ValueTypeToValueObjectBlob(const ValueType& value) 36 { 37 std::vector<uint8_t> blob = std::vector<uint8_t>(); 38 for (int64_t j = 0; j < value.Uint8Array.size; j++) { 39 blob.push_back(value.Uint8Array.head[j]); 40 } 41 return NativeRdb::ValueObject(blob); 42 } 43 ValueTypeToValueObjectAsset(const ValueType & value)44 NativeRdb::ValueObject ValueTypeToValueObjectAsset(const ValueType& value) 45 { 46 std::string modifyTime = value.asset.modifyTime; 47 std::string size = value.asset.size; 48 NativeRdb::ValueObject::Asset asset = { 49 .status = value.asset.status, 50 .name = value.asset.name, 51 .uri = value.asset.uri, 52 .createTime = value.asset.createTime, 53 .modifyTime = modifyTime, 54 .size = size, 55 .hash = modifyTime + "_" + size, 56 .path = value.asset.path 57 }; 58 return NativeRdb::ValueObject(asset); 59 } 60 ValueTypeToValueObjectAssets(const ValueType & value)61 NativeRdb::ValueObject ValueTypeToValueObjectAssets(const ValueType& value) 62 { 63 std::vector<NativeRdb::ValueObject::Asset> assets = std::vector<NativeRdb::ValueObject::Asset>(); 64 for (int64_t j = 0; j < value.assets.size; j++) { 65 Asset asset = value.assets.head[j]; 66 std::string modifyTime = asset.modifyTime; 67 std::string size = asset.size; 68 NativeRdb::ValueObject::Asset nativeAsset = { 69 .status = asset.status, 70 .name = asset.name, 71 .uri = asset.uri, 72 .createTime = asset.createTime, 73 .modifyTime = modifyTime, 74 .size = size, 75 .hash = modifyTime + "_" + size, 76 .path = asset.path 77 }; 78 assets.push_back(nativeAsset); 79 } 80 return NativeRdb::ValueObject(assets); 81 } 82 ValueTypeToValueObject(const ValueType & value)83 NativeRdb::ValueObject ValueTypeToValueObject(const ValueType& value) 84 { 85 NativeRdb::ValueObject valueObject; 86 switch (value.tag) { 87 case TYPE_NULL: { 88 valueObject = NativeRdb::ValueObject(); 89 break; 90 } 91 case TYPE_INT: { 92 valueObject = NativeRdb::ValueObject(value.integer); 93 break; 94 } 95 case TYPE_DOU: { 96 valueObject = NativeRdb::ValueObject(value.dou); 97 break; 98 } 99 case TYPE_STR: { 100 valueObject = NativeRdb::ValueObject(value.string); 101 break; 102 } 103 case TYPE_BOOL: { 104 valueObject = NativeRdb::ValueObject(value.boolean); 105 break; 106 } 107 case TYPE_BLOB: { 108 valueObject = ValueTypeToValueObjectBlob(value); 109 break; 110 } 111 case TYPE_ASSET: { 112 valueObject = ValueTypeToValueObjectAsset(value); 113 break; 114 } 115 case TYPE_ASSETS: { 116 valueObject = ValueTypeToValueObjectAssets(value); 117 break; 118 } 119 default: 120 valueObject = NativeRdb::ValueObject(); 121 break; 122 } 123 return valueObject; 124 } 125 ValueObjectToValueTypeAsset(const NativeRdb::ValueObject & object)126 ValueType ValueObjectToValueTypeAsset(const NativeRdb::ValueObject& object) 127 { 128 NativeRdb::ValueObject::Asset val; 129 object.GetAsset(val); 130 Asset asset = Asset { 131 .name = MallocCString(val.name), 132 .uri = MallocCString(val.uri), 133 .path = MallocCString(val.path), 134 .createTime = MallocCString(val.createTime), 135 .modifyTime = MallocCString(val.modifyTime), 136 .size = MallocCString(val.size), 137 .status = val.status 138 }; 139 return ValueType {.asset = asset, .tag = TYPE_ASSET}; 140 } 141 ValueObjectToValueTypeAssets(const NativeRdb::ValueObject & object)142 ValueType ValueObjectToValueTypeAssets(const NativeRdb::ValueObject& object) 143 { 144 NativeRdb::ValueObject::Assets val; 145 object.GetAssets(val); 146 Assets assets = Assets {.head = static_cast<Asset*>(malloc(val.size() * sizeof(Asset))), .size = val.size()}; 147 if (assets.head == nullptr) { 148 return ValueType {.assets = Assets{nullptr, -1}, .tag = TYPE_ASSETS}; 149 } 150 for (std::size_t i = 0; i < val.size(); i++) { 151 assets.head[i] = Asset { 152 .name = MallocCString(val[i].name), 153 .uri = MallocCString(val[i].uri), 154 .path = MallocCString(val[i].path), 155 .createTime = MallocCString(val[i].createTime), 156 .modifyTime = MallocCString(val[i].modifyTime), 157 .size = MallocCString(val[i].size), 158 .status = static_cast<int32_t>(val[i].status) 159 }; 160 } 161 return ValueType {.assets = assets, .tag = TYPE_ASSETS}; 162 } 163 ValueObjectToValueType(const NativeRdb::ValueObject & object)164 ValueType ValueObjectToValueType(const NativeRdb::ValueObject& object) 165 { 166 switch (object.GetType()) { 167 case NativeRdb::ValueObject::TYPE_NULL: 168 return ValueType {.tag = TYPE_NULL}; 169 case NativeRdb::ValueObject::TYPE_INT: { 170 int64_t val; 171 object.GetLong(val); 172 return ValueType {.integer = val, .tag = TYPE_INT}; 173 } 174 case NativeRdb::ValueObject::TYPE_DOUBLE: { 175 double val; 176 object.GetDouble(val); 177 return ValueType {.dou = val, .tag = TYPE_DOU}; 178 } 179 case NativeRdb::ValueObject::TYPE_STRING: { 180 std::string val; 181 object.GetString(val); 182 return ValueType {.string = MallocCString(val), .tag = TYPE_STR}; 183 } 184 case NativeRdb::ValueObject::TYPE_BOOL: { 185 bool val; 186 object.GetBool(val); 187 return ValueType {.boolean = val, .tag = TYPE_BOOL}; 188 } 189 case NativeRdb::ValueObject::TYPE_BLOB: { 190 std::vector<uint8_t> val; 191 object.GetBlob(val); 192 CArrUI8 arr = CArrUI8 {.head = static_cast<uint8_t*>(malloc(val.size() * sizeof(uint8_t))), 193 .size = val.size()}; 194 if (arr.head == nullptr) { 195 return ValueType {.Uint8Array = CArrUI8 {nullptr, -1}, .tag = TYPE_BLOB}; 196 } 197 return ValueType {.Uint8Array = arr, .tag = TYPE_BLOB}; 198 } 199 case NativeRdb::ValueObject::TYPE_ASSET: { 200 return ValueObjectToValueTypeAsset(object); 201 } 202 case NativeRdb::ValueObject::TYPE_ASSETS: { 203 return ValueObjectToValueTypeAssets(object); 204 } 205 case NativeRdb::ValueObject::TYPE_BUTT: 206 return ValueType {.tag = 128}; 207 default: 208 return ValueType {.tag = TYPE_NULL}; 209 } 210 } 211 VectorToCArrStr(const std::vector<std::string> & devices)212 CArrStr VectorToCArrStr(const std::vector<std::string> &devices) 213 { 214 CArrStr cArrStr{0}; 215 if (devices.size() == 0) { 216 return cArrStr; 217 } 218 cArrStr.head = static_cast<char**>(malloc(sizeof(char*) * devices.size())); 219 if (cArrStr.head == nullptr) { 220 return cArrStr; 221 } 222 for (size_t i = 0; i < devices.size(); i++) { 223 cArrStr.head[i] = MallocCString(devices[i]); 224 } 225 cArrStr.size = static_cast<int64_t>(devices.size()); 226 return cArrStr; 227 } 228 CArrStrToVector(CArrStr carr)229 std::vector<std::string> CArrStrToVector(CArrStr carr) 230 { 231 std::vector<std::string> arr; 232 for (int i = 0; i < carr.size; i++) { 233 if (carr.head[i] != nullptr) { 234 arr.push_back(carr.head[i]); 235 } else { 236 arr.push_back(std::string()); 237 } 238 } 239 return arr; 240 } 241 RetPRIKeyTypeToVariant(RetPRIKeyType & value)242 std::variant<std::monostate, std::string, int64_t, double> RetPRIKeyTypeToVariant(RetPRIKeyType &value) 243 { 244 switch (value.tag) { 245 case NativeRdb::ValueObject::TYPE_INT: 246 return std::variant<std::monostate, std::string, int64_t, double>(value.integer); 247 case NativeRdb::ValueObject::TYPE_DOUBLE: 248 return std::variant<std::monostate, std::string, int64_t, double>(value.dou); 249 case NativeRdb::ValueObject::TYPE_STRING: 250 return std::variant<std::monostate, std::string, int64_t, double>(value.string); 251 default: 252 return std::variant<std::monostate, std::string, int64_t, double>(0); 253 } 254 } 255 VariantToRetPRIKeyType(const std::variant<std::monostate,std::string,int64_t,double> & value)256 RetPRIKeyType VariantToRetPRIKeyType(const std::variant<std::monostate, std::string, int64_t, double> &value) 257 { 258 if (std::holds_alternative<int64_t>(value)) { 259 return RetPRIKeyType{ .integer = std::get<int64_t>(value), .dou = 0.0, 260 .string = nullptr, .tag = NativeRdb::ValueObject::TYPE_INT }; 261 } else if (std::holds_alternative<double>(value)) { 262 return RetPRIKeyType{ .integer = 0, .dou = std::get<double>(value), 263 .string = nullptr, .tag = NativeRdb::ValueObject::TYPE_DOUBLE }; 264 } else if (std::holds_alternative<std::string>(value)) { 265 return RetPRIKeyType{ .integer = 0, .dou = 0.0, 266 .string = MallocCString(std::get<std::string>(value)), .tag = NativeRdb::ValueObject::TYPE_STRING }; 267 } else { 268 return RetPRIKeyType{0}; 269 } 270 } 271 CArrPRIKeyTypeToPRIKeyArray(CArrPRIKeyType & cPrimaryKeys)272 std::vector<NativeRdb::RdbStore::PRIKey> CArrPRIKeyTypeToPRIKeyArray(CArrPRIKeyType &cPrimaryKeys) 273 { 274 std::vector<NativeRdb::RdbStore::PRIKey> res = std::vector<NativeRdb::RdbStore::PRIKey>(); 275 for (int64_t i = 0; i < cPrimaryKeys.size; i++) { 276 res.push_back(RetPRIKeyTypeToVariant(cPrimaryKeys.head[i])); 277 } 278 return res; 279 } 280 MapToModifyTime(std::map<NativeRdb::RdbStore::PRIKey,NativeRdb::RdbStore::Date> & map,int32_t & errCode)281 ModifyTime MapToModifyTime(std::map<NativeRdb::RdbStore::PRIKey, NativeRdb::RdbStore::Date> &map, int32_t &errCode) 282 { 283 ModifyTime modifyTime{0}; 284 modifyTime.size = static_cast<int64_t>(map.size()); 285 modifyTime.key = static_cast<RetPRIKeyType*>(malloc(sizeof(RetPRIKeyType) * modifyTime.size)); 286 modifyTime.value = static_cast<uint64_t*>(malloc(sizeof(uint64_t) * modifyTime.size)); 287 if (modifyTime.key == nullptr || modifyTime.value == nullptr) { 288 free(modifyTime.key); 289 free(modifyTime.value); 290 errCode = -1; 291 return ModifyTime{0}; 292 } 293 int64_t index = 0; 294 for (auto it = map.begin(); it != map.end(); ++it) { 295 modifyTime.key[index] = VariantToRetPRIKeyType(it->first); 296 modifyTime.value[index] = static_cast<uint64_t>((it->second).date); 297 index++; 298 } 299 return modifyTime; 300 } 301 VectorToCArrPRIKeyType(std::vector<DistributedRdb::RdbStoreObserver::PrimaryKey> arr)302 CArrPRIKeyType VectorToCArrPRIKeyType(std::vector<DistributedRdb::RdbStoreObserver::PrimaryKey> arr) 303 { 304 CArrPRIKeyType types{0}; 305 if (arr.size() == 0) { 306 return types; 307 } 308 types.head = static_cast<RetPRIKeyType*>(malloc(sizeof(RetPRIKeyType) * arr.size())); 309 if (types.head == nullptr) { 310 return types; 311 } 312 for (size_t i = 0; i < arr.size(); i++) { 313 types.head[i] = VariantToRetPRIKeyType(arr[i]); 314 } 315 types.size = static_cast<int64_t>(arr.size()); 316 return types; 317 } 318 ToRetChangeInfo(const DistributedRdb::Origin & origin,DistributedRdb::RdbStoreObserver::ChangeInfo::iterator info)319 RetChangeInfo ToRetChangeInfo(const DistributedRdb::Origin &origin, 320 DistributedRdb::RdbStoreObserver::ChangeInfo::iterator info) 321 { 322 RetChangeInfo retInfo{0}; 323 retInfo.table = MallocCString(info->first); 324 retInfo.type = origin.dataType; 325 retInfo.inserted = VectorToCArrPRIKeyType(info-> 326 second[DistributedRdb::RdbStoreObserver::ChangeType::CHG_TYPE_INSERT]); 327 retInfo.updated = VectorToCArrPRIKeyType(info-> 328 second[DistributedRdb::RdbStoreObserver::ChangeType::CHG_TYPE_UPDATE]); 329 retInfo.deleted = VectorToCArrPRIKeyType(info-> 330 second[DistributedRdb::RdbStoreObserver::ChangeType::CHG_TYPE_DELETE]); 331 return retInfo; 332 } 333 ToCArrRetChangeInfo(const DistributedRdb::Origin & origin,const DistributedRdb::RdbStoreObserver::PrimaryFields & fields,DistributedRdb::RdbStoreObserver::ChangeInfo && changeInfo)334 CArrRetChangeInfo ToCArrRetChangeInfo(const DistributedRdb::Origin &origin, 335 const DistributedRdb::RdbStoreObserver::PrimaryFields &fields, 336 DistributedRdb::RdbStoreObserver::ChangeInfo &&changeInfo) 337 { 338 CArrRetChangeInfo infos{0}; 339 if (changeInfo.size() == 0) { 340 return infos; 341 } 342 infos.head = static_cast<RetChangeInfo*>(malloc(sizeof(RetChangeInfo) * changeInfo.size())); 343 if (infos.head == nullptr) { 344 return CArrRetChangeInfo{0}; 345 } 346 int64_t index = 0; 347 for (auto it = changeInfo.begin(); it != changeInfo.end(); ++it) { 348 infos.head[index] = ToRetChangeInfo(origin, it); 349 index++; 350 } 351 infos.size = static_cast<int64_t>(changeInfo.size()); 352 return infos; 353 } 354 ToStatistic(DistributedRdb::Statistic statistic)355 CStatistic ToStatistic(DistributedRdb::Statistic statistic) 356 { 357 return CStatistic{ .total = statistic.total, .successful = statistic.success, 358 .failed = statistic.failed, .remained = statistic.untreated }; 359 } 360 ToCTableDetails(DistributedRdb::TableDetail detail)361 CTableDetails ToCTableDetails(DistributedRdb::TableDetail detail) 362 { 363 return CTableDetails{ .upload = ToStatistic(detail.upload), .download = ToStatistic(detail.download) }; 364 } 365 ToCDetails(DistributedRdb::TableDetails details)366 CDetails ToCDetails(DistributedRdb::TableDetails details) 367 { 368 if (details.size() == 0) { 369 return CDetails{0}; 370 } 371 char** key = static_cast<char**>(malloc(sizeof(char*) * details.size())); 372 CTableDetails* value = static_cast<CTableDetails*>(malloc(sizeof(CTableDetails) * details.size())); 373 if (key == nullptr || value == nullptr) { 374 free(key); 375 free(value); 376 return CDetails{0}; 377 } 378 int64_t index = 0; 379 for (auto it = details.begin(); it != details.end(); ++it) { 380 key[index] = MallocCString(it->first); 381 value[index] = ToCTableDetails(it->second); 382 index++; 383 } 384 return CDetails{ .key = key, .value = value, .size = details.size() }; 385 } 386 ToCProgressDetails(const DistributedRdb::Details & details)387 CProgressDetails ToCProgressDetails(const DistributedRdb::Details &details) 388 { 389 if (details.empty()) { 390 return CProgressDetails{0}; 391 } 392 DistributedRdb::ProgressDetail detail = details.begin() ->second; 393 return CProgressDetails{ .schedule = detail.progress, .code = detail.code, 394 .details = ToCDetails(detail.details) }; 395 } 396 } 397 }