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 }