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