1  /*
2   * Copyright (c) 2023 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  #define LOG_TAG "RelationalStore"
16  #include "relational_store.h"
17  
18  #include "convertor_error_code.h"
19  #include "grd_api_manager.h"
20  #include "logger.h"
21  #include "modify_time_cursor.h"
22  #include "raw_data_parser.h"
23  #include "rdb_errno.h"
24  #include "rdb_helper.h"
25  #include "rdb_predicates.h"
26  #include "rdb_sql_utils.h"
27  #include "rdb_store_config.h"
28  #include "relational_cursor.h"
29  #include "relational_predicates.h"
30  #include "relational_predicates_objects.h"
31  #include "relational_store_error_code.h"
32  #include "relational_store_impl.h"
33  #include "relational_types_v0.h"
34  #include "relational_values_bucket.h"
35  #include "securec.h"
36  #include "sqlite_global_config.h"
37  
38  using namespace OHOS::RdbNdk;
39  using namespace OHOS::DistributedRdb;
40  constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class.
41  constexpr int RDB_CONFIG_SIZE_V0 = 41;
42  constexpr int RDB_CONFIG_SIZE_V1 = 45;
43  constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE;
44  
45  static int g_supportDbTypes[] = {RDB_SQLITE, RDB_CAYLEY};
46  
47  struct OH_Rdb_ConfigV2 {
48      int magicNum = RDB_CONFIG_V2_MAGIC_CODE;
49      std::string dataBaseDir = "";
50      std::string storeName = "";
51      std::string bundleName = "";
52      std::string moduleName = "";
53      bool isEncrypt = false;
54      int securityLevel = 0;
55      int area = 0;
56      int dbType = RDB_SQLITE;
57  };
58  
OH_Rdb_CreateConfig()59  OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig()
60  {
61      return new (std::nothrow) OH_Rdb_ConfigV2();
62  }
63  
OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 * config)64  int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config)
65  {
66      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
67          LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when destroy.",
68              (config == nullptr), (config == nullptr ? 0 : config->magicNum));
69          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
70      }
71      delete config;
72      config = nullptr;
73      return OH_Rdb_ErrCode::RDB_OK;
74  }
75  
OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 * config,const char * dataBaseDir)76  int OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir)
77  {
78      if (config == nullptr || dataBaseDir == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
79          LOG_ERROR("config is null %{public}d or dataBaseDir %{public}d magic num not valid %{public}x "
80              "when Set DataBaseDir.", (config == nullptr), (dataBaseDir == nullptr),
81              (config == nullptr ? 0 : config->magicNum));
82          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
83      }
84      config->dataBaseDir = std::string(dataBaseDir);
85      return OH_Rdb_ErrCode::RDB_OK;
86  }
87  
OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 * config,const char * storeName)88  int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName)
89  {
90      if (config == nullptr || storeName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
91          LOG_ERROR("config is null %{public}d or storeName %{public}d or magic num not ok"
92              "%{public}x When set storeName.", (config == nullptr), (storeName == nullptr),
93              (config == nullptr ? 0 : config->magicNum));
94          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
95      }
96      config->storeName = std::string(storeName);
97      return OH_Rdb_ErrCode::RDB_OK;
98  }
99  
OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 * config,const char * bundleName)100  int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName)
101  {
102      if (config == nullptr || bundleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
103          LOG_ERROR("config is null %{public}d or bundleName %{public}d magic num no ok %{public}x when set bundleName.",
104              (config == nullptr), (bundleName == nullptr), (config == nullptr ? 0 : config->magicNum));
105          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
106      }
107      config->bundleName = std::string(bundleName);
108      return OH_Rdb_ErrCode::RDB_OK;
109  }
110  
OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 * config,const char * moduleName)111  int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName)
112  {
113      if (config == nullptr || moduleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
114          LOG_ERROR("config is null %{public}d or moduleName %{public}d magic num no ok %{public}x when set moduleName.",
115              (config == nullptr), (moduleName == nullptr), (config == nullptr ? 0 : config->magicNum));
116          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
117      }
118      config->moduleName = std::string(moduleName);
119      return OH_Rdb_ErrCode::RDB_OK;
120  }
121  
OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 * config,bool isEncrypted)122  int OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 *config, bool isEncrypted)
123  {
124      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
125          LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set encrypt.", (config == nullptr),
126              (config == nullptr ? 0 : config->magicNum));
127          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
128      }
129      config->isEncrypt = isEncrypted;
130      return OH_Rdb_ErrCode::RDB_OK;
131  }
132  
OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 * config,int securityLevel)133  int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel)
134  {
135      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
136          LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set security level.",
137              (config == nullptr), (config == nullptr ? 0 : config->magicNum));
138          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
139      }
140      if (securityLevel < S1 || securityLevel > S4) {
141          LOG_ERROR("securityLevel value is out of range %{public}d", securityLevel);
142          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
143      }
144      config->securityLevel = securityLevel;
145      return OH_Rdb_ErrCode::RDB_OK;
146  }
147  
OH_Rdb_SetArea(OH_Rdb_ConfigV2 * config,int area)148  int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area)
149  {
150      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
151          LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set area.", (config == nullptr),
152              (config == nullptr ? 0 : config->magicNum));
153          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
154      }
155      if (area < RDB_SECURITY_AREA_EL1 || area > RDB_SECURITY_AREA_EL5) {
156          LOG_ERROR("area value is out of range %{public}d", area);
157          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
158      }
159      config->area = area;
160      return OH_Rdb_ErrCode::RDB_OK;
161  }
162  
OH_Rdb_SetDbType(OH_Rdb_ConfigV2 * config,int dbType)163  int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType)
164  {
165      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) ||
166          (dbType < RDB_SQLITE || dbType > RDB_CAYLEY)) {
167          LOG_ERROR("config is null %{public}d or magicNum not valid %{public}d or dbType is out of range %{public}d",
168              (config == nullptr), (config == nullptr ? 0 : config->magicNum), dbType);
169          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
170      }
171      if (dbType == RDB_CAYLEY && !(OHOS::NativeRdb::IsUsingArkData())) {
172          return OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED;
173      }
174      config->dbType = dbType;
175      return OH_Rdb_ErrCode::RDB_OK;
176  }
177  
OH_Rdb_GetSupportedDbType(int * numType)178  const int *OH_Rdb_GetSupportedDbType(int *numType)
179  {
180      if (numType == nullptr) {
181          return nullptr;
182      }
183      // if use arkData, then numType will be 2 {RDB_SQLITE and RDB_CAYLEY}, otherwise only 1 {RDB_SQLITE}
184      *numType = OHOS::NativeRdb::IsUsingArkData() ? 2 : 1;
185      return g_supportDbTypes;
186  }
187  
OH_Rdb_CreateValueObject()188  OH_VObject *OH_Rdb_CreateValueObject()
189  {
190      return new (std::nothrow) RelationalPredicatesObjects();
191  }
192  
OH_Rdb_CreateValuesBucket()193  OH_VBucket *OH_Rdb_CreateValuesBucket()
194  {
195      return new (std::nothrow) RelationalValuesBucket();
196  }
197  
OH_Rdb_CreatePredicates(const char * table)198  OH_Predicates *OH_Rdb_CreatePredicates(const char *table)
199  {
200      if (table == nullptr) {
201          return nullptr;
202      }
203      return new (std::nothrow) RelationalPredicate(table);
204  }
205  
RelationalStore(std::shared_ptr<OHOS::NativeRdb::RdbStore> store)206  OHOS::RdbNdk::RelationalStore::RelationalStore(std::shared_ptr<OHOS::NativeRdb::RdbStore> store) : store_(store)
207  {
208      id = RDB_STORE_CID;
209  }
210  
SubscribeAutoSyncProgress(const Rdb_ProgressObserver * callback)211  int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback)
212  {
213      std::lock_guard<decltype(mutex_)> lock(mutex_);
214      bool result = std::any_of(
215          callbacks_.begin(), callbacks_.end(), [callback](const auto &observer) { return *observer == callback; });
216      if (result) {
217          LOG_INFO("duplicate subscribe.");
218          return OH_Rdb_ErrCode::RDB_OK;
219      }
220      auto obs = std::make_shared<NDKDetailProgressObserver>(callback);
221      int errCode = store_->RegisterAutoSyncCallback(obs);
222      if (errCode == NativeRdb::E_OK) {
223          LOG_ERROR("subscribe failed.");
224          return ConvertorErrorCode::NativeToNdk(errCode);
225      }
226      callbacks_.push_back(std::move(obs));
227      return OH_Rdb_ErrCode::RDB_OK;
228  }
229  
UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver * callback)230  int RelationalStore::UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback)
231  {
232      std::lock_guard<decltype(mutex_)> lock(mutex_);
233      for (auto it = callbacks_.begin(); it != callbacks_.end();) {
234          if (callback != nullptr && !(**it == callback)) {
235              ++it;
236              continue;
237          }
238  
239          int errCode = store_->UnregisterAutoSyncCallback(*it);
240          if (errCode != NativeRdb::E_OK) {
241              LOG_ERROR("unsubscribe failed.");
242              return ConvertorErrorCode::NativeToNdk(errCode);
243          }
244          it = callbacks_.erase(it);
245          LOG_DEBUG("progress unsubscribe success.");
246      }
247      return OH_Rdb_ErrCode::RDB_OK;
248  }
249  
~RelationalStore()250  RelationalStore::~RelationalStore()
251  {
252      if (store_ == nullptr || callbacks_.empty()) {
253          return;
254      }
255      for (auto &callback : callbacks_) {
256          store_->UnregisterAutoSyncCallback(callback);
257      }
258  }
259  
TransformMode(Rdb_SyncMode & mode)260  SyncMode NDKUtils::TransformMode(Rdb_SyncMode &mode)
261  {
262      switch (mode) {
263          case RDB_SYNC_MODE_TIME_FIRST:
264              return TIME_FIRST;
265          case RDB_SYNC_MODE_NATIVE_FIRST:
266              return NATIVE_FIRST;
267          case RDB_SYNC_MODE_CLOUD_FIRST:
268              return CLOUD_FIRST;
269          default:
270              return static_cast<SyncMode>(-1);
271      }
272  }
273  
GetSubscribeType(Rdb_SubscribeType & type)274  OHOS::DistributedRdb::SubscribeMode NDKUtils::GetSubscribeType(Rdb_SubscribeType &type)
275  {
276      switch (type) {
277          case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD:
278              return SubscribeMode::CLOUD;
279          case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD_DETAILS:
280              return SubscribeMode::CLOUD_DETAIL;
281          case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS:
282              return SubscribeMode::LOCAL_DETAIL;
283          default:
284              return SubscribeMode::SUBSCRIBE_MODE_MAX;
285      }
286  }
287  
288  class MainOpenCallback : public OHOS::NativeRdb::RdbOpenCallback {
289  public:
290      int OnCreate(OHOS::NativeRdb::RdbStore &rdbStore) override;
291      int OnUpgrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override;
292  };
293  
OnCreate(OHOS::NativeRdb::RdbStore & rdbStore)294  int MainOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &rdbStore)
295  {
296      return OH_Rdb_ErrCode::RDB_OK;
297  }
298  
OnUpgrade(OHOS::NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)299  int MainOpenCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion)
300  {
301      return OH_Rdb_ErrCode::RDB_OK;
302  }
303  
GetRelationalStore(OH_Rdb_Store * store)304  RelationalStore *GetRelationalStore(OH_Rdb_Store *store)
305  {
306      if (store == nullptr || store->id != RDB_STORE_CID) {
307          LOG_ERROR("store is invalid. is null %{public}d", (store == nullptr));
308          return nullptr;
309      }
310      return static_cast<RelationalStore *>(store);
311  }
312  
GetRdbStoreConfig(const OH_Rdb_ConfigV2 * config,int * errCode)313  static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config, int *errCode)
314  {
315      if (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE ||
316          (OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 ||
317          OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST) ||
318          (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) ||
319          (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY)) {
320          *errCode = OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
321          LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d"
322              "dbType %{public}d ret %{public}d", config->magicNum, config->securityLevel, config->area, config->dbType,
323              *errCode);
324          return OHOS::NativeRdb::RdbStoreConfig("");
325      }
326      std::string realPath =
327          OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode);
328      if (*errCode != 0) {
329          *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
330          LOG_ERROR("Get database path failed from new config, ret %{public}d ", *errCode);
331          return OHOS::NativeRdb::RdbStoreConfig("");
332      }
333      OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath);
334      rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel));
335      rdbStoreConfig.SetEncryptStatus(config->isEncrypt);
336      rdbStoreConfig.SetArea(config->area - 1);
337      rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY);
338      rdbStoreConfig.SetBundleName(config->bundleName);
339      rdbStoreConfig.SetName(config->storeName);
340      return rdbStoreConfig;
341  }
342  
OH_Rdb_GetOrOpen(const OH_Rdb_Config * config,int * errCode)343  OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode)
344  {
345      if (config == nullptr || config->selfSize > RDB_CONFIG_SIZE_V1 || errCode == nullptr) {
346          LOG_ERROR("Parameters set error:config is NULL ? %{public}d and config size is %{public}zu or "
347                    "errCode is NULL ? %{public}d ",
348                    (config == nullptr), sizeof(OH_Rdb_Config), (errCode == nullptr));
349          return nullptr;
350      }
351  
352      std::string realPath =
353          OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode);
354      if (*errCode != 0) {
355          *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
356          LOG_ERROR("Get database path failed, ret %{public}d ", *errCode);
357          return nullptr;
358      }
359      OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath);
360      rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel));
361      rdbStoreConfig.SetEncryptStatus(config->isEncrypt);
362      if (config->selfSize > RDB_CONFIG_SIZE_V0) {
363          rdbStoreConfig.SetArea(config->area - 1);
364      }
365      if (config->bundleName != nullptr) {
366          rdbStoreConfig.SetBundleName(config->bundleName);
367      }
368      rdbStoreConfig.SetName(config->storeName);
369  
370      MainOpenCallback callback;
371      std::shared_ptr<OHOS::NativeRdb::RdbStore> store =
372          OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode);
373      *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
374      if (store == nullptr) {
375          LOG_ERROR("Get RDB Store fail %{public}s", realPath.c_str());
376          return nullptr;
377      }
378      return new (std::nothrow) RelationalStore(store);
379  }
380  
OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 * config,int * errCode)381  OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode)
382  {
383      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || errCode == nullptr) {
384          LOG_ERROR("Parameters set error:config is NULL ? %{public}d or magicNum is not valid %{public}d or"
385                    " errCode is NULL ? %{public}d ", (config == nullptr), (config == nullptr ? 0 : config->magicNum),
386                    (errCode == nullptr));
387          return nullptr;
388      }
389      OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig = GetRdbStoreConfig(config, errCode);
390      if (*errCode != OH_Rdb_ErrCode::RDB_OK) {
391          return nullptr;
392      }
393      MainOpenCallback callback;
394      std::shared_ptr<OHOS::NativeRdb::RdbStore> store =
395          OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode);
396      *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
397      if (store == nullptr) {
398          LOG_ERROR("Get RDB Store fail %{public}s", rdbStoreConfig.GetPath().c_str());
399          return nullptr;
400      }
401      return new (std::nothrow) RelationalStore(store);
402  }
403  
OH_Rdb_CloseStore(OH_Rdb_Store * store)404  int OH_Rdb_CloseStore(OH_Rdb_Store *store)
405  {
406      auto rdbStore = GetRelationalStore(store);
407      if (rdbStore == nullptr) {
408          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
409      }
410      delete rdbStore;
411      return OH_Rdb_ErrCode::RDB_OK;
412  }
413  
OH_Rdb_DeleteStore(const OH_Rdb_Config * config)414  int OH_Rdb_DeleteStore(const OH_Rdb_Config *config)
415  {
416      if (config == nullptr || config->dataBaseDir == nullptr || config->storeName == nullptr) {
417          LOG_ERROR("Parameters set error:path is NULL ? %{public}d", (config == nullptr));
418          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
419      }
420      int errCode = OHOS::NativeRdb::E_OK;
421      std::string realPath =
422          OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, errCode);
423      if (errCode != OHOS::NativeRdb::E_OK) {
424          return ConvertorErrorCode::NativeToNdk(errCode);
425      }
426      return ConvertorErrorCode::NativeToNdk(OHOS::NativeRdb::RdbHelper::DeleteRdbStore(realPath));
427  }
428  
OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 * config)429  int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config)
430  {
431      if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
432          LOG_ERROR("config is NULL ? %{public}d, config is invalid ? %{public}d", (config == nullptr),
433              (config == nullptr ? 0 : config->magicNum));
434          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
435      }
436      int errCode = OHOS::NativeRdb::E_OK;
437      std::string realPath =
438          OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, errCode);
439      if (errCode != OHOS::NativeRdb::E_OK) {
440          return ConvertorErrorCode::NativeToNdk(errCode);
441      }
442      return ConvertorErrorCode::NativeToNdk(OHOS::NativeRdb::RdbHelper::DeleteRdbStore(realPath));
443  }
444  
OH_Rdb_Insert(OH_Rdb_Store * store,const char * table,OH_VBucket * valuesBucket)445  int OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket)
446  {
447      auto rdbStore = GetRelationalStore(store);
448      auto bucket = RelationalValuesBucket::GetSelf(valuesBucket);
449      if (rdbStore == nullptr || table == nullptr || bucket == nullptr) {
450          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
451      }
452      int64_t rowId = -1;
453      rdbStore->GetStore()->Insert(rowId, table, bucket->Get());
454      return rowId >= 0 ? rowId : OH_Rdb_ErrCode::RDB_ERR;
455  }
456  
OH_Rdb_Update(OH_Rdb_Store * store,OH_VBucket * valueBucket,OH_Predicates * predicates)457  int OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valueBucket, OH_Predicates *predicates)
458  {
459      auto rdbStore = GetRelationalStore(store);
460      auto predicate = RelationalPredicate::GetSelf(predicates);
461      auto bucket = RelationalValuesBucket::GetSelf(valueBucket);
462      if (rdbStore == nullptr || predicate == nullptr || bucket == nullptr) {
463          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
464      }
465      int updatedRows = -1;
466      rdbStore->GetStore()->Update(updatedRows, bucket->Get(), predicate->Get());
467      return updatedRows >= 0 ? updatedRows : OH_Rdb_ErrCode::RDB_ERR;
468  }
469  
OH_Rdb_Delete(OH_Rdb_Store * store,OH_Predicates * predicates)470  int OH_Rdb_Delete(OH_Rdb_Store *store, OH_Predicates *predicates)
471  {
472      auto rdbStore = GetRelationalStore(store);
473      auto predicate = RelationalPredicate::GetSelf(predicates);
474      if (rdbStore == nullptr || predicate == nullptr) {
475          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
476      }
477      int deletedRows = -1;
478      rdbStore->GetStore()->Delete(deletedRows, predicate->Get());
479      return deletedRows >= 0 ? deletedRows : OH_Rdb_ErrCode::RDB_ERR;
480  }
481  
OH_Rdb_Query(OH_Rdb_Store * store,OH_Predicates * predicates,const char * const * columnNames,int length)482  OH_Cursor *OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length)
483  {
484      auto rdbStore = GetRelationalStore(store);
485      auto predicate = RelationalPredicate::GetSelf(predicates);
486      if (rdbStore == nullptr || predicate == nullptr) {
487          return nullptr;
488      }
489      std::vector<std::string> columns;
490      if (columnNames != nullptr && length > 0) {
491          columns.reserve(length);
492          for (int i = 0; i < length; i++) {
493              columns.push_back(columnNames[i]);
494          }
495      }
496  
497      std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet =
498          rdbStore->GetStore()->QueryByStep(predicate->Get(), columns);
499      if (resultSet == nullptr) {
500          return nullptr;
501      }
502      return new (std::nothrow) RelationalCursor(std::move(resultSet));
503  }
504  
OH_Rdb_ExecuteQuery(OH_Rdb_Store * store,const char * sql)505  OH_Cursor *OH_Rdb_ExecuteQuery(OH_Rdb_Store *store, const char *sql)
506  {
507      auto rdbStore = GetRelationalStore(store);
508      if (rdbStore == nullptr || sql == nullptr) {
509          return nullptr;
510      }
511      std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet =
512          rdbStore->GetStore()->GetDbType() == OHOS::NativeRdb::DB_VECTOR
513              ? rdbStore->GetStore()->QueryByStep(sql, std::vector<std::string>{})
514              : rdbStore->GetStore()->QuerySql(sql, std::vector<std::string>{});
515      if (resultSet == nullptr) {
516          return nullptr;
517      }
518      return new OHOS::RdbNdk::RelationalCursor(std::move(resultSet));
519  }
520  
OH_Rdb_Execute(OH_Rdb_Store * store,const char * sql)521  int OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql)
522  {
523      auto rdbStore = GetRelationalStore(store);
524      if (rdbStore == nullptr || sql == nullptr) {
525          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
526      }
527      return ConvertorErrorCode::NativeToNdk(
528          rdbStore->GetStore()->ExecuteSql(sql, std::vector<OHOS::NativeRdb::ValueObject>{}));
529  }
530  
OH_Rdb_ExecuteByTrxId(OH_Rdb_Store * store,int64_t trxId,const char * sql)531  int OH_Rdb_ExecuteByTrxId(OH_Rdb_Store *store, int64_t trxId, const char *sql)
532  {
533      auto rdbStore = GetRelationalStore(store);
534      if (rdbStore == nullptr || sql == nullptr) {
535          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
536      }
537      return ConvertorErrorCode::NativeToNdk(
538          (rdbStore->GetStore()->Execute(sql, std::vector<OHOS::NativeRdb::ValueObject>{}, trxId)).first);
539  }
540  
OH_Rdb_BeginTransaction(OH_Rdb_Store * store)541  int OH_Rdb_BeginTransaction(OH_Rdb_Store *store)
542  {
543      auto rdbStore = GetRelationalStore(store);
544      if (rdbStore == nullptr) {
545          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
546      }
547      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->BeginTransaction());
548  }
549  
OH_Rdb_RollBack(OH_Rdb_Store * store)550  int OH_Rdb_RollBack(OH_Rdb_Store *store)
551  {
552      auto rdbStore = GetRelationalStore(store);
553      if (rdbStore == nullptr) {
554          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
555      }
556      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->RollBack());
557  }
558  
OH_Rdb_Commit(OH_Rdb_Store * store)559  int OH_Rdb_Commit(OH_Rdb_Store *store)
560  {
561      auto rdbStore = GetRelationalStore(store);
562      if (rdbStore == nullptr) {
563          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
564      }
565      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Commit());
566  }
567  
OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store * store,int64_t * trxId)568  int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId)
569  {
570      auto rdbStore = GetRelationalStore(store);
571      if (rdbStore == nullptr || trxId == nullptr) {
572          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
573      }
574      std::pair<int, int64_t> res = rdbStore->GetStore()->BeginTrans();
575      *trxId = res.second;
576      return ConvertorErrorCode::NativeToNdk(res.first);
577  }
578  
OH_Rdb_RollBackByTrxId(OH_Rdb_Store * store,int64_t trxId)579  int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId)
580  {
581      auto rdbStore = GetRelationalStore(store);
582      if (rdbStore == nullptr) {
583          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
584      }
585      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->RollBack(trxId));
586  }
587  
OH_Rdb_CommitByTrxId(OH_Rdb_Store * store,int64_t trxId)588  int OH_Rdb_CommitByTrxId(OH_Rdb_Store *store, int64_t trxId)
589  {
590      auto rdbStore = GetRelationalStore(store);
591      if (rdbStore == nullptr) {
592          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
593      }
594      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Commit(trxId));
595  }
596  
OH_Rdb_Backup(OH_Rdb_Store * store,const char * databasePath)597  int OH_Rdb_Backup(OH_Rdb_Store *store, const char *databasePath)
598  {
599      auto rdbStore = GetRelationalStore(store);
600      if (rdbStore == nullptr || databasePath == nullptr) {
601          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
602      }
603      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Backup(databasePath));
604  }
605  
OH_Rdb_Restore(OH_Rdb_Store * store,const char * databasePath)606  int OH_Rdb_Restore(OH_Rdb_Store *store, const char *databasePath)
607  {
608      auto rdbStore = GetRelationalStore(store);
609      if (rdbStore == nullptr || databasePath == nullptr) {
610          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
611      }
612      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Restore(databasePath));
613  }
614  
OH_Rdb_GetVersion(OH_Rdb_Store * store,int * version)615  int OH_Rdb_GetVersion(OH_Rdb_Store *store, int *version)
616  {
617      auto rdbStore = GetRelationalStore(store);
618      if (rdbStore == nullptr || version == nullptr) {
619          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
620      }
621      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->GetVersion(*version));
622  }
623  
OH_Rdb_SetVersion(OH_Rdb_Store * store,int version)624  int OH_Rdb_SetVersion(OH_Rdb_Store *store, int version)
625  {
626      auto rdbStore = GetRelationalStore(store);
627      if (rdbStore == nullptr) {
628          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
629      }
630      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->SetVersion(version));
631  }
632  
Convert(const Rdb_DistributedConfig * config)633  static std::pair<int32_t, Rdb_DistributedConfig> Convert(const Rdb_DistributedConfig *config)
634  {
635      std::pair<int32_t, Rdb_DistributedConfig> result = { OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, {} };
636      auto &[errCode, cfg] = result;
637      switch (config->version) {
638          case DISTRIBUTED_CONFIG_V0: {
639              const auto *realCfg = reinterpret_cast<const DistributedConfigV0 *>(config);
640              cfg.version = realCfg->version;
641              cfg.isAutoSync = realCfg->isAutoSync;
642              errCode = OH_Rdb_ErrCode::RDB_OK;
643              break;
644          }
645          default:
646              break;
647      }
648      return result;
649  }
650  
OH_Rdb_SetDistributedTables(OH_Rdb_Store * store,const char * tables[],uint32_t count,Rdb_DistributedType type,const Rdb_DistributedConfig * config)651  int OH_Rdb_SetDistributedTables(OH_Rdb_Store *store, const char *tables[], uint32_t count, Rdb_DistributedType type,
652      const Rdb_DistributedConfig *config)
653  {
654      auto rdbStore = GetRelationalStore(store);
655      if (rdbStore == nullptr || type != Rdb_DistributedType::RDB_DISTRIBUTED_CLOUD || (count > 0 && tables == nullptr)) {
656          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
657      }
658  
659      auto [errCode, cfg] = Convert(config);
660      if (errCode != OH_Rdb_ErrCode::RDB_OK) {
661          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
662      }
663      std::vector<std::string> tableNames;
664      tableNames.reserve(count);
665      for (uint32_t i = 0; i < count; i++) {
666          if (tables[i] == nullptr) {
667              return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
668          }
669          tableNames.emplace_back(tables[i]);
670      }
671      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->SetDistributedTables(
672          tableNames, DistributedTableType::DISTRIBUTED_CLOUD, { cfg.isAutoSync }));
673  }
674  
OH_Rdb_FindModifyTime(OH_Rdb_Store * store,const char * tableName,const char * columnName,OH_VObject * values)675  OH_Cursor *OH_Rdb_FindModifyTime(OH_Rdb_Store *store, const char *tableName, const char *columnName, OH_VObject *values)
676  {
677      auto rdbStore = GetRelationalStore(store);
678      auto selfObjects = RelationalPredicatesObjects::GetSelf(values);
679      if (rdbStore == nullptr || selfObjects == nullptr || tableName == nullptr) {
680          return nullptr;
681      }
682      std::vector<ValueObject> objects = selfObjects->Get();
683      std::vector<OHOS::NativeRdb::RdbStore::PRIKey> keys;
684      keys.reserve(objects.size());
685      for (auto &object : objects) {
686          OHOS::NativeRdb::RdbStore::PRIKey priKey;
687          OHOS::NativeRdb::RawDataParser::Convert(std::move(object.value), priKey);
688          keys.push_back(std::move(priKey));
689      }
690      auto results = rdbStore->GetStore()->GetModifyTime(tableName, columnName, keys);
691      return new (std::nothrow) ModifyTimeCursor(std::move(results));
692  }
693  
OH_Rdb_Subscribe(OH_Rdb_Store * store,Rdb_SubscribeType type,const Rdb_DataObserver * observer)694  int OH_Rdb_Subscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer)
695  {
696      auto rdbStore = GetRelationalStore(store);
697      if (rdbStore == nullptr || observer == nullptr) {
698          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
699      }
700      return rdbStore->DoSubScribe(type, observer);
701  }
702  
OH_Rdb_Unsubscribe(OH_Rdb_Store * store,Rdb_SubscribeType type,const Rdb_DataObserver * observer)703  int OH_Rdb_Unsubscribe(OH_Rdb_Store *store, Rdb_SubscribeType type, const Rdb_DataObserver *observer)
704  {
705      auto rdbStore = GetRelationalStore(store);
706      if (rdbStore == nullptr) {
707          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
708      }
709      return rdbStore->DoUnsubScribe(type, observer);
710  }
711  
DoSubScribe(Rdb_SubscribeType type,const Rdb_DataObserver * observer)712  int RelationalStore::DoSubScribe(Rdb_SubscribeType type, const Rdb_DataObserver *observer)
713  {
714      if (store_ == nullptr || type < RDB_SUBSCRIBE_TYPE_CLOUD || type > RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS ||
715          observer == nullptr || observer->callback.briefObserver == nullptr ||
716          observer->callback.detailsObserver == nullptr) {
717          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
718      }
719  
720      std::lock_guard<decltype(mutex_)> lock(mutex_);
721      auto result = std::any_of(dataObservers_[type].begin(), dataObservers_[type].end(),
722                                [observer](const std::shared_ptr<NDKStoreObserver> &item) {
723                                    return *item.get() == observer;
724                                });
725      if (result) {
726          LOG_INFO("duplicate subscribe.");
727          return OH_Rdb_ErrCode::RDB_OK;
728      }
729      auto subscribeOption = SubscribeOption{ .mode = NDKUtils::GetSubscribeType(type), .event = "data_change" };
730      auto ndkObserver = std::make_shared<NDKStoreObserver>(observer, type);
731      int subscribeResult = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ?
732          store_->SubscribeObserver(subscribeOption, ndkObserver) : store_->Subscribe(subscribeOption, ndkObserver.get());
733      if (subscribeResult != OHOS::NativeRdb::E_OK) {
734          LOG_ERROR("subscribe failed.");
735      } else {
736          dataObservers_[type].emplace_back(std::move(ndkObserver));
737      }
738      return ConvertorErrorCode::NativeToNdk(subscribeResult);
739  }
740  
DoUnsubScribe(Rdb_SubscribeType type,const Rdb_DataObserver * observer)741  int RelationalStore::DoUnsubScribe(Rdb_SubscribeType type, const Rdb_DataObserver *observer)
742  {
743      if (store_ == nullptr || type < RDB_SUBSCRIBE_TYPE_CLOUD || type > RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) {
744          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
745      }
746      std::lock_guard<decltype(mutex_)> lock(mutex_);
747      for (auto it = dataObservers_[type].begin(); it != dataObservers_[type].end();) {
748          if (observer != nullptr && !(**it == observer)) {
749              ++it;
750              continue;
751          }
752          auto subscribeOption = SubscribeOption{ .mode = NDKUtils::GetSubscribeType(type), .event = "data_change" };
753          int errCode = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ?
754              store_->UnsubscribeObserver(subscribeOption, *it) : store_->UnSubscribe(subscribeOption, it->get());
755          if (errCode != NativeRdb::E_OK) {
756              LOG_ERROR("unsubscribe failed.");
757              return ConvertorErrorCode::NativeToNdk(errCode);
758          }
759          it = dataObservers_[type].erase(it);
760          LOG_DEBUG("data observer unsubscribe success.");
761      }
762      return OH_Rdb_ErrCode::RDB_OK;
763  }
764  
765  namespace {
766  struct RelationalProgressDetails : public Rdb_ProgressDetails {
767      Rdb_TableDetails *details_ = nullptr;
768      explicit RelationalProgressDetails(const ProgressDetail &detail);
769      ~RelationalProgressDetails();
770  
771      Rdb_TableDetails *GetTableDetails(int paraVersion);
772      void DestroyTableDetails();
773  
774  private:
775      uint8_t *ResizeBuff(size_t size);
776  
777      TableDetails tableDetails_;
778      size_t size_ = 0;
779      uint8_t *buffer_ = nullptr;
780  };
781  
DestroyTableDetails()782  void RelationalProgressDetails::DestroyTableDetails()
783  {
784      delete[] details_;
785      details_ = nullptr;
786  }
787  
RelationalProgressDetails(const ProgressDetail & detail)788  RelationalProgressDetails::RelationalProgressDetails(const ProgressDetail &detail)
789  {
790      version = DISTRIBUTED_PROGRESS_DETAIL_VERSION;
791      schedule = detail.progress;
792      code = detail.code;
793      tableLength = (int32_t)detail.details.size();
794      tableDetails_ = detail.details;
795  }
796  
~RelationalProgressDetails()797  RelationalProgressDetails::~RelationalProgressDetails()
798  {
799      if (buffer_ != nullptr) {
800          free(buffer_);
801      }
802      buffer_ = nullptr;
803  }
804  
GetTableDetails(int paraVersion)805  Rdb_TableDetails *RelationalProgressDetails::GetTableDetails(int paraVersion)
806  {
807      switch (paraVersion) {
808          case TABLE_DETAIL_V0: {
809              auto length = sizeof(TableDetailsV0) * (tableLength + 1);
810              auto *detailsV0 = (TableDetailsV0 *)ResizeBuff(length);
811              if (detailsV0 == nullptr) {
812                  return nullptr;
813              }
814              (void)memset_s(detailsV0, length, 0, length);
815              int index = 0;
816              for (const auto &pair : tableDetails_) {
817                  detailsV0[index].table = pair.first.c_str();
818                  detailsV0[index].upload = StatisticV0{
819                      .total = (int)pair.second.upload.total,
820                      .successful = (int)pair.second.upload.success,
821                      .failed = (int)pair.second.upload.failed,
822                      .remained = (int)pair.second.upload.untreated,
823                  };
824                  detailsV0[index].download = StatisticV0{
825                      .total = (int)pair.second.download.total,
826                      .successful = (int)pair.second.download.success,
827                      .failed = (int)pair.second.download.failed,
828                      .remained = (int)pair.second.download.untreated,
829                  };
830                  index++;
831              }
832              return reinterpret_cast<Rdb_TableDetails *>(reinterpret_cast<uint8_t *>(detailsV0));
833          }
834          default:
835              return nullptr;
836      }
837  }
838  
ResizeBuff(size_t size)839  uint8_t *RelationalProgressDetails::ResizeBuff(size_t size)
840  {
841      if (size_ >= size) {
842          return buffer_;
843      }
844      if (buffer_ != nullptr) {
845          free(buffer_);
846      }
847      buffer_ = (uint8_t *)malloc(size);
848      return buffer_;
849  }
850  } // namespace
851  
GetDetails(Rdb_ProgressDetails * progress)852  static std::pair<int, RelationalProgressDetails *> GetDetails(Rdb_ProgressDetails *progress)
853  {
854      if (progress->version != DISTRIBUTED_PROGRESS_DETAIL_VERSION) {
855          return { -1, nullptr };
856      }
857      return { 0, (RelationalProgressDetails *)progress };
858  }
859  
OH_Rdb_GetTableDetails(Rdb_ProgressDetails * progress,int32_t version)860  Rdb_TableDetails *OH_Rdb_GetTableDetails(Rdb_ProgressDetails *progress, int32_t version)
861  {
862      auto [errCode, details] = GetDetails(progress);
863      if (errCode == -1 || details == nullptr) {
864          return nullptr;
865      }
866      return details->GetTableDetails(version);
867  }
868  
OH_Rdb_CloudSync(OH_Rdb_Store * store,Rdb_SyncMode mode,const char * tables[],uint32_t count,const Rdb_ProgressObserver * observer)869  int OH_Rdb_CloudSync(
870      OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[], uint32_t count, const Rdb_ProgressObserver *observer)
871  {
872      auto rdbStore = GetRelationalStore(store);
873      if (rdbStore == nullptr || mode < RDB_SYNC_MODE_TIME_FIRST || mode > RDB_SYNC_MODE_CLOUD_FIRST ||
874          observer == nullptr || observer->callback == nullptr || (count > 0 && tables == nullptr)) {
875          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
876      }
877      SyncOption syncOption{ .mode = NDKUtils::TransformMode(mode), .isBlock = false };
878      std::vector<std::string> tableNames;
879      for (uint32_t i = 0; i < count; ++i) {
880          if (tables[i] == nullptr) {
881              return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
882          }
883          tableNames.emplace_back(tables[i]);
884      }
885  
886      auto progressCallback = [cxt = (*observer).context, cb = (*observer).callback](Details &&details) {
887          if (details.size() > 1) {
888              LOG_ERROR("Not support edge to edge detail notify.");
889              return;
890          }
891          if (details.empty()) {
892              LOG_ERROR("No device or cloud synced.");
893              return;
894          }
895          for (auto &[device, detail] : details) {
896              RelationalProgressDetails cloudDetail(detail);
897              cb(cxt, &cloudDetail);
898              break;
899          }
900      };
901      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Sync(syncOption, tableNames, progressCallback));
902  }
903  
OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store * store,const Rdb_ProgressObserver * callback)904  int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *callback)
905  {
906      auto rdbStore = GetRelationalStore(store);
907      if (rdbStore == nullptr || callback == nullptr) {
908          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
909      }
910      return ConvertorErrorCode::NativeToNdk(rdbStore->SubscribeAutoSyncProgress(callback));
911  }
912  
OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store * store,const Rdb_ProgressObserver * callback)913  int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *callback)
914  {
915      auto rdbStore = GetRelationalStore(store);
916      if (rdbStore == nullptr) {
917          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
918      }
919      return ConvertorErrorCode::NativeToNdk(rdbStore->UnsubscribeAutoSyncProgress(callback));
920  }
921  
OH_Rdb_LockRow(OH_Rdb_Store * store,OH_Predicates * predicates)922  int OH_Rdb_LockRow(OH_Rdb_Store *store, OH_Predicates *predicates)
923  {
924      auto rdbStore = GetRelationalStore(store);
925      auto predicate = RelationalPredicate::GetSelf(predicates);
926      if (rdbStore == nullptr || predicate == nullptr) {
927          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
928      }
929      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->ModifyLockStatus(predicate->Get(), true));
930  }
931  
OH_Rdb_UnlockRow(OH_Rdb_Store * store,OH_Predicates * predicates)932  int OH_Rdb_UnlockRow(OH_Rdb_Store *store, OH_Predicates *predicates)
933  {
934      auto rdbStore = GetRelationalStore(store);
935      auto predicate = RelationalPredicate::GetSelf(predicates);
936      if (rdbStore == nullptr || predicate == nullptr) {
937          return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
938      }
939      return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->ModifyLockStatus(predicate->Get(), false));
940  }
941  
OH_Rdb_QueryLockedRow(OH_Rdb_Store * store,OH_Predicates * predicates,const char * const * columnNames,int length)942  OH_Cursor *OH_Rdb_QueryLockedRow(
943      OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length)
944  {
945      auto rdbStore = GetRelationalStore(store);
946      auto predicate = RelationalPredicate::GetSelf(predicates);
947      if (rdbStore == nullptr || predicate == nullptr) {
948          LOG_ERROR("rdbStore or predicate is nullptr.");
949          return nullptr;
950      }
951      std::vector<std::string> columns;
952      if (columnNames != nullptr && length > 0) {
953          columns.reserve(length);
954          for (int i = 0; i < length; i++) {
955              columns.push_back(columnNames[i]);
956          }
957      }
958      predicate->Get().BeginWrap();
959      predicate->Get().EqualTo(OHOS::NativeRdb::AbsRdbPredicates::LOCK_STATUS, OHOS::NativeRdb::AbsRdbPredicates::LOCKED);
960      predicate->Get().Or();
961      predicate->Get().EqualTo(
962          OHOS::NativeRdb::AbsRdbPredicates::LOCK_STATUS, OHOS::NativeRdb::AbsRdbPredicates::LOCK_CHANGED);
963      predicate->Get().EndWrap();
964      std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet =
965          rdbStore->GetStore()->QueryByStep(predicate->Get(), columns);
966      if (resultSet == nullptr) {
967          return nullptr;
968      }
969      return new OHOS::RdbNdk::RelationalCursor(std::move(resultSet));
970  }
971  
NDKDetailProgressObserver(const Rdb_ProgressObserver * callback)972  NDKDetailProgressObserver::NDKDetailProgressObserver(const Rdb_ProgressObserver *callback) : callback_(callback)
973  {
974  }
975  
ProgressNotification(const Details & details)976  void NDKDetailProgressObserver::ProgressNotification(const Details &details)
977  {
978      if (callback_ == nullptr || details.empty()) {
979          return;
980      }
981      RelationalProgressDetails progressDetails = RelationalProgressDetails(details.begin()->second);
982      (*(callback_->callback))(callback_->context, &progressDetails);
983      progressDetails.DestroyTableDetails();
984  }
985  
operator ==(const Rdb_ProgressObserver * callback)986  bool NDKDetailProgressObserver::operator==(const Rdb_ProgressObserver *callback)
987  {
988      return callback == callback_;
989  }
990  
NDKStoreObserver(const Rdb_DataObserver * observer,int mode)991  NDKStoreObserver::NDKStoreObserver(const Rdb_DataObserver *observer, int mode) : mode_(mode), observer_(observer)
992  {
993  }
994  
OnChange(const std::vector<std::string> & devices)995  void NDKStoreObserver::OnChange(const std::vector<std::string> &devices)
996  {
997      if (mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD) {
998          auto count = devices.size();
999          std::unique_ptr<const char *[]> deviceIds = std::make_unique<const char *[]>(count);
1000          for (uint32_t i = 0; i < count; ++i) {
1001              deviceIds[i] = devices[i].c_str();
1002          }
1003          (*observer_->callback.briefObserver)(observer_->context, deviceIds.get(), count);
1004      }
1005  }
1006  
GetKeyInfoSize(RdbStoreObserver::ChangeInfo && changeInfo)1007  size_t NDKStoreObserver::GetKeyInfoSize(RdbStoreObserver::ChangeInfo &&changeInfo)
1008  {
1009      size_t size = 0;
1010      for (auto it = changeInfo.begin(); it != changeInfo.end(); ++it) {
1011          size += it->second[RdbStoreObserver::CHG_TYPE_INSERT].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1012          size += it->second[RdbStoreObserver::CHG_TYPE_UPDATE].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1013          size += it->second[RdbStoreObserver::CHG_TYPE_DELETE].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1014      }
1015      return size;
1016  }
1017  
GetKeyDataType(std::vector<RdbStoreObserver::PrimaryKey> & primaryKey)1018  int32_t NDKStoreObserver::GetKeyDataType(std::vector<RdbStoreObserver::PrimaryKey> &primaryKey)
1019  {
1020      if (primaryKey.size() == 0) {
1021          return OH_ColumnType::TYPE_NULL;
1022      }
1023      if (std::holds_alternative<int64_t>(primaryKey[0]) || std::holds_alternative<double>(primaryKey[0])) {
1024          return OH_ColumnType::TYPE_INT64;
1025      }
1026      if (std::holds_alternative<std::string>(primaryKey[0])) {
1027          return OH_ColumnType::TYPE_TEXT;
1028      }
1029      return OH_ColumnType::TYPE_NULL;
1030  }
1031  
OnChange(const Origin & origin,const RdbStoreObserver::PrimaryFields & fields,RdbStoreObserver::ChangeInfo && changeInfo)1032  void NDKStoreObserver::OnChange(
1033      const Origin &origin, const RdbStoreObserver::PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo)
1034  {
1035      uint32_t count = changeInfo.size();
1036      if (count == 0) {
1037          LOG_ERROR("No any infos.");
1038          return;
1039      }
1040  
1041      if (mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD_DETAILS ||
1042          mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) {
1043          size_t size = count * (sizeof(Rdb_ChangeInfo *) + sizeof(Rdb_ChangeInfo)) +
1044                        GetKeyInfoSize(std::forward<RdbStoreObserver::ChangeInfo &&>(changeInfo));
1045          std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
1046          Rdb_ChangeInfo **infos = (Rdb_ChangeInfo **)(buffer.get());
1047          if (infos == nullptr) {
1048              LOG_ERROR("Failed to allocate memory for Rdb_ChangeInfo.");
1049              return;
1050          }
1051  
1052          Rdb_ChangeInfo *details = (Rdb_ChangeInfo *)(infos + count);
1053          Rdb_KeyInfo::Rdb_KeyData *data = (Rdb_KeyInfo::Rdb_KeyData *)(details + count);
1054  
1055          int index = 0;
1056          for (auto it = changeInfo.begin(); it != changeInfo.end(); ++it) {
1057              infos[index] = &details[index];
1058              infos[index]->version = DISTRIBUTED_CHANGE_INFO_VERSION;
1059              infos[index]->tableName = it->first.c_str();
1060              infos[index]->ChangeType = origin.dataType;
1061              infos[index]->inserted.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_INSERT].size());
1062              infos[index]->inserted.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_INSERT]);
1063              infos[index]->updated.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_UPDATE].size());
1064              infos[index]->updated.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_UPDATE]);
1065              infos[index]->deleted.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_DELETE].size());
1066              infos[index]->deleted.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_DELETE]);
1067              ConvertKeyInfoData(data, it->second[RdbStoreObserver::CHG_TYPE_INSERT]);
1068              infos[index]->inserted.data = data;
1069              ConvertKeyInfoData(data + infos[index]->inserted.count, it->second[RdbStoreObserver::CHG_TYPE_UPDATE]);
1070              infos[index]->updated.data = data + infos[index]->inserted.count;
1071              ConvertKeyInfoData(data + infos[index]->inserted.count + infos[index]->updated.count,
1072                  it->second[RdbStoreObserver::CHG_TYPE_DELETE]);
1073              infos[index]->deleted.data = data + infos[index]->inserted.count + infos[index]->updated.count;
1074              index++;
1075          }
1076  
1077          (*observer_->callback.detailsObserver)(observer_->context, const_cast<const Rdb_ChangeInfo **>(infos), count);
1078      }
1079  }
1080  
OnChange()1081  void NDKStoreObserver::OnChange()
1082  {
1083      RdbStoreObserver::OnChange();
1084  }
1085  
ConvertKeyInfoData(Rdb_KeyInfo::Rdb_KeyData * keyInfoData,std::vector<RdbStoreObserver::PrimaryKey> & primaryKey)1086  void NDKStoreObserver::ConvertKeyInfoData(
1087      Rdb_KeyInfo::Rdb_KeyData *keyInfoData, std::vector<RdbStoreObserver::PrimaryKey> &primaryKey)
1088  {
1089      if (keyInfoData == nullptr || primaryKey.empty()) {
1090          LOG_WARN("no data, keyInfoData is nullptr:%{public}d", keyInfoData == nullptr);
1091          return;
1092      }
1093  
1094      for (size_t i = 0; i < primaryKey.size(); ++i) {
1095          const auto &key = primaryKey[i];
1096          if (auto val = std::get_if<double>(&key)) {
1097              keyInfoData[i].real = *val;
1098          } else if (auto val = std::get_if<int64_t>(&key)) {
1099              keyInfoData[i].integer = *val;
1100          } else if (auto val = std::get_if<std::string>(&key)) {
1101              keyInfoData[i].text = val->c_str();
1102          } else {
1103              LOG_ERROR("Not support the data type.");
1104              return;
1105          }
1106      }
1107  }
1108  
operator ==(const Rdb_DataObserver * other)1109  bool NDKStoreObserver::operator==(const Rdb_DataObserver *other)
1110  {
1111      if (other == nullptr) {
1112          return false;
1113      }
1114      return other->context == observer_->context && &(other->callback) == &(observer_->callback);
1115  }