• 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 "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 #include "oh_data_define.h"
38 #include "oh_data_utils.h"
39 #include "values_buckets.h"
40 
41 using namespace OHOS::RdbNdk;
42 using namespace OHOS::DistributedRdb;
43 constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class.
44 constexpr int RDB_CONFIG_SIZE_V0 = 41;
45 constexpr int RDB_CONFIG_SIZE_V1 = 45;
46 constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE;
47 
48 static int g_supportDbTypes[] = { RDB_SQLITE, RDB_CAYLEY };
49 
50 struct OH_Rdb_ConfigV2 {
51     int magicNum = RDB_CONFIG_V2_MAGIC_CODE;
52     std::string dataBaseDir = "";
53     std::string storeName = "";
54     std::string bundleName = "";
55     std::string moduleName = "";
56     bool isEncrypt = false;
57     bool persist = true;
58     int securityLevel = 0;
59     int area = 0;
60     int dbType = RDB_SQLITE;
61     int token = RDB_NONE_TOKENIZER;
62 };
63 
OH_Rdb_CreateConfig()64 OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig()
65 {
66     return new (std::nothrow) OH_Rdb_ConfigV2();
67 }
68 
OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 * config)69 int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config)
70 {
71     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
72         LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when destroy.", (config == nullptr),
73             (config == nullptr ? 0 : config->magicNum));
74         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
75     }
76     delete config;
77     config = nullptr;
78     return OH_Rdb_ErrCode::RDB_OK;
79 }
80 
OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 * config,const char * dataBaseDir)81 int OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir)
82 {
83     if (config == nullptr || dataBaseDir == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
84         LOG_ERROR("config is null %{public}d or dataBaseDir %{public}d magic num not valid %{public}x "
85                   "when Set DataBaseDir.",
86             (config == nullptr), (dataBaseDir == nullptr), (config == nullptr ? 0 : config->magicNum));
87         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
88     }
89     config->dataBaseDir = std::string(dataBaseDir);
90     return OH_Rdb_ErrCode::RDB_OK;
91 }
92 
OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 * config,const char * storeName)93 int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName)
94 {
95     if (config == nullptr || storeName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
96         LOG_ERROR("config is null %{public}d or storeName %{public}d or magic num not ok"
97                   "%{public}x When set storeName.",
98             (config == nullptr), (storeName == nullptr), (config == nullptr ? 0 : config->magicNum));
99         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
100     }
101     config->storeName = std::string(storeName);
102     return OH_Rdb_ErrCode::RDB_OK;
103 }
104 
OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 * config,const char * bundleName)105 int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName)
106 {
107     if (config == nullptr || bundleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
108         LOG_ERROR("config is null %{public}d or bundleName %{public}d magic num no ok %{public}x when set bundleName.",
109             (config == nullptr), (bundleName == nullptr), (config == nullptr ? 0 : config->magicNum));
110         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
111     }
112     config->bundleName = std::string(bundleName);
113     return OH_Rdb_ErrCode::RDB_OK;
114 }
115 
OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 * config,const char * moduleName)116 int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName)
117 {
118     if (config == nullptr || moduleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
119         LOG_ERROR("config is null %{public}d or moduleName %{public}d magic num no ok %{public}x when set moduleName.",
120             (config == nullptr), (moduleName == nullptr), (config == nullptr ? 0 : config->magicNum));
121         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
122     }
123     config->moduleName = std::string(moduleName);
124     return OH_Rdb_ErrCode::RDB_OK;
125 }
126 
OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 * config,bool isEncrypted)127 int OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 *config, bool isEncrypted)
128 {
129     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
130         LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set encrypt.", (config == nullptr),
131             (config == nullptr ? 0 : config->magicNum));
132         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
133     }
134     config->isEncrypt = isEncrypted;
135     return OH_Rdb_ErrCode::RDB_OK;
136 }
137 
OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 * config,int securityLevel)138 int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel)
139 {
140     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
141         LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set security level.",
142             (config == nullptr), (config == nullptr ? 0 : config->magicNum));
143         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
144     }
145     if (securityLevel < S1 || securityLevel > S4) {
146         LOG_ERROR("securityLevel value is out of range %{public}d", securityLevel);
147         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
148     }
149     config->securityLevel = securityLevel;
150     return OH_Rdb_ErrCode::RDB_OK;
151 }
152 
OH_Rdb_SetArea(OH_Rdb_ConfigV2 * config,int area)153 int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area)
154 {
155     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
156         LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set area.", (config == nullptr),
157             (config == nullptr ? 0 : config->magicNum));
158         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
159     }
160     if (area < RDB_SECURITY_AREA_EL1 || area > RDB_SECURITY_AREA_EL5) {
161         LOG_ERROR("area value is out of range %{public}d", area);
162         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
163     }
164     config->area = area;
165     return OH_Rdb_ErrCode::RDB_OK;
166 }
167 
OH_Rdb_SetDbType(OH_Rdb_ConfigV2 * config,int dbType)168 int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType)
169 {
170     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) ||
171         (dbType < RDB_SQLITE || dbType > RDB_CAYLEY)) {
172         LOG_ERROR("config is null %{public}d or magicNum not valid %{public}d or dbType is out of range %{public}d",
173             (config == nullptr), (config == nullptr ? 0 : config->magicNum), dbType);
174         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
175     }
176     if (dbType == RDB_CAYLEY && !(OHOS::NativeRdb::IsUsingArkData())) {
177         return OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED;
178     }
179     config->dbType = dbType;
180     return OH_Rdb_ErrCode::RDB_OK;
181 }
182 
OH_Rdb_IsTokenizerSupported(Rdb_Tokenizer tokenizer,bool * isSupported)183 int OH_Rdb_IsTokenizerSupported(Rdb_Tokenizer tokenizer, bool *isSupported)
184 {
185     if (tokenizer < RDB_NONE_TOKENIZER || tokenizer > RDB_CUSTOM_TOKENIZER) {
186         LOG_ERROR("token is out of range %{public}d", tokenizer);
187         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
188     }
189     if (isSupported == nullptr) {
190         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
191     }
192     *isSupported = OHOS::NativeRdb::RdbHelper::IsSupportedTokenizer(static_cast<OHOS::NativeRdb::Tokenizer>(tokenizer));
193     return OH_Rdb_ErrCode::RDB_OK;
194 }
195 
OH_Rdb_SetTokenizer(OH_Rdb_ConfigV2 * config,Rdb_Tokenizer tokenizer)196 int OH_Rdb_SetTokenizer(OH_Rdb_ConfigV2 *config, Rdb_Tokenizer tokenizer)
197 {
198     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) ||
199         (tokenizer < RDB_NONE_TOKENIZER || tokenizer > RDB_CUSTOM_TOKENIZER)) {
200         LOG_ERROR("config is null %{public}d or magicNum not valid %{public}d or token is out of range %{public}d",
201             (config == nullptr), (config == nullptr ? 0 : config->magicNum), tokenizer);
202         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
203     }
204     if (config->dbType != Rdb_DBType::RDB_SQLITE) {
205         LOG_ERROR("ICU Tokenizer only support sqlite db type.");
206         return OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED;
207     }
208     config->token = tokenizer;
209     return OH_Rdb_ErrCode::RDB_OK;
210 }
211 
OH_Rdb_SetPersistent(OH_Rdb_ConfigV2 * config,bool isPersistent)212 int OH_Rdb_SetPersistent(OH_Rdb_ConfigV2 *config, bool isPersistent)
213 {
214     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) {
215         LOG_ERROR("config is null %{public}d or magicNum not valid %{public}d. isPersistent %{public}d",
216             (config == nullptr), (config == nullptr ? 0 : config->magicNum), isPersistent);
217         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
218     }
219     config->persist = isPersistent;
220     return OH_Rdb_ErrCode::RDB_OK;
221 }
222 
OH_Rdb_GetSupportedDbType(int * numType)223 const int *OH_Rdb_GetSupportedDbType(int *numType)
224 {
225     if (numType == nullptr) {
226         return nullptr;
227     }
228     // if use arkData, then numType will be 2 {RDB_SQLITE and RDB_CAYLEY}, otherwise only 1 {RDB_SQLITE}
229     *numType = OHOS::NativeRdb::IsUsingArkData() ? 2 : 1;
230     return g_supportDbTypes;
231 }
232 
OH_Rdb_CreateValueObject()233 OH_VObject *OH_Rdb_CreateValueObject()
234 {
235     return new (std::nothrow) RelationalPredicatesObjects();
236 }
237 
OH_Rdb_CreateValuesBucket()238 OH_VBucket *OH_Rdb_CreateValuesBucket()
239 {
240     return new (std::nothrow) RelationalValuesBucket();
241 }
242 
OH_Rdb_CreatePredicates(const char * table)243 OH_Predicates *OH_Rdb_CreatePredicates(const char *table)
244 {
245     if (table == nullptr) {
246         return nullptr;
247     }
248     return new (std::nothrow) RelationalPredicate(table);
249 }
250 
RelationalStore(std::shared_ptr<OHOS::NativeRdb::RdbStore> store)251 OHOS::RdbNdk::RelationalStore::RelationalStore(std::shared_ptr<OHOS::NativeRdb::RdbStore> store) : store_(store)
252 {
253     id = RDB_STORE_CID;
254 }
255 
SubscribeAutoSyncProgress(const Rdb_ProgressObserver * callback)256 int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback)
257 {
258     std::lock_guard<decltype(mutex_)> lock(mutex_);
259     bool result = std::any_of(
260         callbacks_.begin(), callbacks_.end(), [callback](const auto &observer) { return *observer == callback; });
261     if (result) {
262         LOG_INFO("duplicate subscribe.");
263         return OH_Rdb_ErrCode::RDB_OK;
264     }
265     auto obs = std::make_shared<NDKDetailProgressObserver>(callback);
266     int errCode = store_->RegisterAutoSyncCallback(obs);
267     if (errCode == NativeRdb::E_OK) {
268         LOG_ERROR("subscribe failed.");
269         return ConvertorErrorCode::NativeToNdk(errCode);
270     }
271     callbacks_.push_back(std::move(obs));
272     return OH_Rdb_ErrCode::RDB_OK;
273 }
274 
UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver * callback)275 int RelationalStore::UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback)
276 {
277     std::lock_guard<decltype(mutex_)> lock(mutex_);
278     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
279         if (callback != nullptr && !(**it == callback)) {
280             ++it;
281             continue;
282         }
283 
284         int errCode = store_->UnregisterAutoSyncCallback(*it);
285         if (errCode != NativeRdb::E_OK) {
286             LOG_ERROR("unsubscribe failed.");
287             return ConvertorErrorCode::NativeToNdk(errCode);
288         }
289         it = callbacks_.erase(it);
290         LOG_DEBUG("progress unsubscribe success.");
291     }
292     return OH_Rdb_ErrCode::RDB_OK;
293 }
294 
~RelationalStore()295 RelationalStore::~RelationalStore()
296 {
297     if (store_ == nullptr || callbacks_.empty()) {
298         return;
299     }
300     for (auto &callback : callbacks_) {
301         store_->UnregisterAutoSyncCallback(callback);
302     }
303 }
304 
TransformMode(Rdb_SyncMode & mode)305 SyncMode NDKUtils::TransformMode(Rdb_SyncMode &mode)
306 {
307     switch (mode) {
308         case RDB_SYNC_MODE_TIME_FIRST:
309             return TIME_FIRST;
310         case RDB_SYNC_MODE_NATIVE_FIRST:
311             return NATIVE_FIRST;
312         case RDB_SYNC_MODE_CLOUD_FIRST:
313             return CLOUD_FIRST;
314         default:
315             return static_cast<SyncMode>(-1);
316     }
317 }
318 
GetSubscribeType(Rdb_SubscribeType & type)319 OHOS::DistributedRdb::SubscribeMode NDKUtils::GetSubscribeType(Rdb_SubscribeType &type)
320 {
321     switch (type) {
322         case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD:
323             return SubscribeMode::CLOUD;
324         case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD_DETAILS:
325             return SubscribeMode::CLOUD_DETAIL;
326         case Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS:
327             return SubscribeMode::LOCAL_DETAIL;
328         default:
329             return SubscribeMode::SUBSCRIBE_MODE_MAX;
330     }
331 }
332 
333 class MainOpenCallback : public OHOS::NativeRdb::RdbOpenCallback {
334 public:
335     int OnCreate(OHOS::NativeRdb::RdbStore &rdbStore) override;
336     int OnUpgrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override;
337 };
338 
OnCreate(OHOS::NativeRdb::RdbStore & rdbStore)339 int MainOpenCallback::OnCreate(OHOS::NativeRdb::RdbStore &rdbStore)
340 {
341     return OH_Rdb_ErrCode::RDB_OK;
342 }
343 
OnUpgrade(OHOS::NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)344 int MainOpenCallback::OnUpgrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion)
345 {
346     return OH_Rdb_ErrCode::RDB_OK;
347 }
348 
GetRelationalStore(OH_Rdb_Store * store)349 RelationalStore *GetRelationalStore(OH_Rdb_Store *store)
350 {
351     if (store == nullptr || store->id != RDB_STORE_CID) {
352         LOG_ERROR("store is invalid. is null %{public}d", (store == nullptr));
353         return nullptr;
354     }
355     return static_cast<RelationalStore *>(store);
356 }
357 
358 // caller must ensure token is valid
ConvertTokenizer2Native(Rdb_Tokenizer token)359 static OHOS::NativeRdb::Tokenizer ConvertTokenizer2Native(Rdb_Tokenizer token)
360 {
361     if (token == Rdb_Tokenizer::RDB_NONE_TOKENIZER) {
362         return OHOS::NativeRdb::Tokenizer::NONE_TOKENIZER;
363     }
364     if (token == Rdb_Tokenizer::RDB_ICU_TOKENIZER) {
365         return OHOS::NativeRdb::Tokenizer::ICU_TOKENIZER;
366     }
367     if (token == Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER) {
368         return OHOS::NativeRdb::Tokenizer::CUSTOM_TOKENIZER;
369     }
370     return OHOS::NativeRdb::Tokenizer::TOKENIZER_END;
371 }
372 
GetRdbStoreConfig(const OH_Rdb_ConfigV2 * config,int * errCode)373 static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config, int *errCode)
374 {
375     if (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE || (config->persist &&
376         ((OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 ||
377             OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST))) ||
378         (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) ||
379         (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY) ||
380         (config->token < RDB_NONE_TOKENIZER || config->token > RDB_CUSTOM_TOKENIZER)) {
381         *errCode = OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
382         LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d"
383                   "dbType %{public}d token %{public}d ret %{public}d persist %{public}d",
384             config->magicNum, config->securityLevel, config->area, config->dbType, config->token, *errCode,
385             config->persist);
386         return OHOS::NativeRdb::RdbStoreConfig("");
387     }
388     std::string realPath = !config->persist ? config->dataBaseDir:
389         OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode);
390     if (*errCode != 0) {
391         *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
392         LOG_ERROR("Get database path failed from new config, ret %{public}d ", *errCode);
393         return OHOS::NativeRdb::RdbStoreConfig("");
394     }
395     OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath);
396     if (!config->storeName.empty()) {
397         rdbStoreConfig.SetName(config->storeName);
398     }
399     rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel));
400     rdbStoreConfig.SetEncryptStatus(config->isEncrypt);
401     rdbStoreConfig.SetArea(config->area - 1);
402     rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY);
403     rdbStoreConfig.SetBundleName(config->bundleName);
404     rdbStoreConfig.SetName(config->storeName);
405     rdbStoreConfig.SetTokenizer(ConvertTokenizer2Native(static_cast<Rdb_Tokenizer>(config->token)));
406     rdbStoreConfig.SetStorageMode(
407         config->persist ? OHOS::NativeRdb::StorageMode::MODE_DISK : OHOS::NativeRdb::StorageMode::MODE_MEMORY);
408     return rdbStoreConfig;
409 }
410 
OH_Rdb_GetOrOpen(const OH_Rdb_Config * config,int * errCode)411 OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode)
412 {
413     if (config == nullptr || config->selfSize > RDB_CONFIG_SIZE_V1 || errCode == nullptr) {
414         LOG_ERROR("Parameters set error:config is NULL ? %{public}d and config size is %{public}zu or "
415                   "errCode is NULL ? %{public}d ",
416             (config == nullptr), sizeof(OH_Rdb_Config), (errCode == nullptr));
417         return nullptr;
418     }
419 
420     std::string realPath =
421         OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode);
422     if (*errCode != 0) {
423         *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
424         LOG_ERROR("Get database path failed, ret %{public}d ", *errCode);
425         return nullptr;
426     }
427     OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath);
428     rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel));
429     rdbStoreConfig.SetEncryptStatus(config->isEncrypt);
430     if (config->selfSize > RDB_CONFIG_SIZE_V0) {
431         rdbStoreConfig.SetArea(config->area - 1);
432     }
433     if (config->bundleName != nullptr) {
434         rdbStoreConfig.SetBundleName(config->bundleName);
435     }
436     rdbStoreConfig.SetName(config->storeName);
437 
438     MainOpenCallback callback;
439     std::shared_ptr<OHOS::NativeRdb::RdbStore> store =
440         OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode);
441     *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
442     if (store == nullptr) {
443         LOG_ERROR("Get RDB Store fail %{public}s", realPath.c_str());
444         return nullptr;
445     }
446     return new (std::nothrow) RelationalStore(store);
447 }
448 
OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 * config,int * errCode)449 OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode)
450 {
451     if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || errCode == nullptr) {
452         LOG_ERROR("Parameters set error:config is NULL ? %{public}d or magicNum is not valid %{public}d or"
453                   " errCode is NULL ? %{public}d ",
454             (config == nullptr), (config == nullptr ? 0 : config->magicNum), (errCode == nullptr));
455         return nullptr;
456     }
457     OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig = GetRdbStoreConfig(config, errCode);
458     if (*errCode != OH_Rdb_ErrCode::RDB_OK) {
459         return nullptr;
460     }
461     MainOpenCallback callback;
462     std::shared_ptr<OHOS::NativeRdb::RdbStore> store =
463         OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode);
464     *errCode = ConvertorErrorCode::NativeToNdk(*errCode);
465     if (store == nullptr) {
466         LOG_ERROR("Get RDB Store fail %{public}s", 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()->BatchInsertWithConflictResolution(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.get());
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->get());
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             (void)memset_s(detailsV0, length, 0, length);
907             int index = 0;
908             for (const auto &pair : tableDetails_) {
909                 detailsV0[index].table = pair.first.c_str();
910                 detailsV0[index].upload = StatisticV0{
911                     .total = (int)pair.second.upload.total,
912                     .successful = (int)pair.second.upload.success,
913                     .failed = (int)pair.second.upload.failed,
914                     .remained = (int)pair.second.upload.untreated,
915                 };
916                 detailsV0[index].download = StatisticV0{
917                     .total = (int)pair.second.download.total,
918                     .successful = (int)pair.second.download.success,
919                     .failed = (int)pair.second.download.failed,
920                     .remained = (int)pair.second.download.untreated,
921                 };
922                 index++;
923             }
924             return reinterpret_cast<Rdb_TableDetails *>(reinterpret_cast<uint8_t *>(detailsV0));
925         }
926         default:
927             return nullptr;
928     }
929 }
930 
ResizeBuff(size_t size)931 uint8_t *RelationalProgressDetails::ResizeBuff(size_t size)
932 {
933     if (size_ >= size) {
934         return buffer_;
935     }
936     if (buffer_ != nullptr) {
937         free(buffer_);
938     }
939     buffer_ = (uint8_t *)malloc(size);
940     return buffer_;
941 }
942 } // namespace
943 
GetDetails(Rdb_ProgressDetails * progress)944 static std::pair<int, RelationalProgressDetails *> GetDetails(Rdb_ProgressDetails *progress)
945 {
946     if (progress->version != DISTRIBUTED_PROGRESS_DETAIL_VERSION) {
947         return { -1, nullptr };
948     }
949     return { 0, (RelationalProgressDetails *)progress };
950 }
951 
OH_Rdb_GetTableDetails(Rdb_ProgressDetails * progress,int32_t version)952 Rdb_TableDetails *OH_Rdb_GetTableDetails(Rdb_ProgressDetails *progress, int32_t version)
953 {
954     auto [errCode, details] = GetDetails(progress);
955     if (errCode == -1 || details == nullptr) {
956         return nullptr;
957     }
958     return details->GetTableDetails(version);
959 }
960 
OH_Rdb_CloudSync(OH_Rdb_Store * store,Rdb_SyncMode mode,const char * tables[],uint32_t count,const Rdb_ProgressObserver * observer)961 int OH_Rdb_CloudSync(
962     OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[], uint32_t count, const Rdb_ProgressObserver *observer)
963 {
964     auto rdbStore = GetRelationalStore(store);
965     if (rdbStore == nullptr || mode < RDB_SYNC_MODE_TIME_FIRST || mode > RDB_SYNC_MODE_CLOUD_FIRST ||
966         observer == nullptr || observer->callback == nullptr || (count > 0 && tables == nullptr)) {
967         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
968     }
969     SyncOption syncOption{ .mode = NDKUtils::TransformMode(mode), .isBlock = false };
970     std::vector<std::string> tableNames;
971     for (uint32_t i = 0; i < count; ++i) {
972         if (tables[i] == nullptr) {
973             return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
974         }
975         tableNames.emplace_back(tables[i]);
976     }
977 
978     auto progressCallback = [cxt = (*observer).context, cb = (*observer).callback](Details &&details) {
979         if (details.size() > 1) {
980             LOG_ERROR("Not support edge to edge detail notify.");
981             return;
982         }
983         if (details.empty()) {
984             LOG_ERROR("No device or cloud synced.");
985             return;
986         }
987         for (auto &[device, detail] : details) {
988             RelationalProgressDetails cloudDetail(detail);
989             cb(cxt, &cloudDetail);
990             break;
991         }
992     };
993     return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->Sync(syncOption, tableNames, progressCallback));
994 }
995 
OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store * store,const Rdb_ProgressObserver * callback)996 int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *callback)
997 {
998     auto rdbStore = GetRelationalStore(store);
999     if (rdbStore == nullptr || callback == nullptr) {
1000         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1001     }
1002     return ConvertorErrorCode::NativeToNdk(rdbStore->SubscribeAutoSyncProgress(callback));
1003 }
1004 
OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store * store,const Rdb_ProgressObserver * callback)1005 int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, const Rdb_ProgressObserver *callback)
1006 {
1007     auto rdbStore = GetRelationalStore(store);
1008     if (rdbStore == nullptr) {
1009         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1010     }
1011     return ConvertorErrorCode::NativeToNdk(rdbStore->UnsubscribeAutoSyncProgress(callback));
1012 }
1013 
OH_Rdb_LockRow(OH_Rdb_Store * store,OH_Predicates * predicates)1014 int OH_Rdb_LockRow(OH_Rdb_Store *store, OH_Predicates *predicates)
1015 {
1016     auto rdbStore = GetRelationalStore(store);
1017     auto predicate = RelationalPredicate::GetSelf(predicates);
1018     if (rdbStore == nullptr || predicate == nullptr) {
1019         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1020     }
1021     return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->ModifyLockStatus(predicate->Get(), true));
1022 }
1023 
OH_Rdb_UnlockRow(OH_Rdb_Store * store,OH_Predicates * predicates)1024 int OH_Rdb_UnlockRow(OH_Rdb_Store *store, OH_Predicates *predicates)
1025 {
1026     auto rdbStore = GetRelationalStore(store);
1027     auto predicate = RelationalPredicate::GetSelf(predicates);
1028     if (rdbStore == nullptr || predicate == nullptr) {
1029         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1030     }
1031     return ConvertorErrorCode::NativeToNdk(rdbStore->GetStore()->ModifyLockStatus(predicate->Get(), false));
1032 }
1033 
OH_Rdb_QueryLockedRow(OH_Rdb_Store * store,OH_Predicates * predicates,const char * const * columnNames,int length)1034 OH_Cursor *OH_Rdb_QueryLockedRow(
1035     OH_Rdb_Store *store, OH_Predicates *predicates, const char *const *columnNames, int length)
1036 {
1037     auto rdbStore = GetRelationalStore(store);
1038     auto predicate = RelationalPredicate::GetSelf(predicates);
1039     if (rdbStore == nullptr || predicate == nullptr) {
1040         LOG_ERROR("rdbStore or predicate is nullptr.");
1041         return nullptr;
1042     }
1043     std::vector<std::string> columns;
1044     if (columnNames != nullptr && length > 0) {
1045         columns.reserve(length);
1046         for (int i = 0; i < length; i++) {
1047             columns.push_back(columnNames[i]);
1048         }
1049     }
1050     predicate->Get().BeginWrap();
1051     predicate->Get().EqualTo(OHOS::NativeRdb::AbsRdbPredicates::LOCK_STATUS, OHOS::NativeRdb::AbsRdbPredicates::LOCKED);
1052     predicate->Get().Or();
1053     predicate->Get().EqualTo(
1054         OHOS::NativeRdb::AbsRdbPredicates::LOCK_STATUS, OHOS::NativeRdb::AbsRdbPredicates::LOCK_CHANGED);
1055     predicate->Get().EndWrap();
1056     std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet =
1057         rdbStore->GetStore()->QueryByStep(predicate->Get(), columns);
1058     if (resultSet == nullptr) {
1059         return nullptr;
1060     }
1061     return new OHOS::RdbNdk::RelationalCursor(std::move(resultSet));
1062 }
1063 
OH_Rdb_CreateTransaction(OH_Rdb_Store * store,const OH_RDB_TransOptions * options,OH_Rdb_Transaction ** trans)1064 int OH_Rdb_CreateTransaction(OH_Rdb_Store *store, const OH_RDB_TransOptions *options, OH_Rdb_Transaction **trans)
1065 {
1066     auto rdbStore = GetRelationalStore(store);
1067     if (rdbStore == nullptr || trans == nullptr || options == nullptr || !options->IsValid()) {
1068         LOG_ERROR("params exist nullptr or invalid options.");
1069         return RDB_E_INVALID_ARGS;
1070     }
1071     OH_Rdb_Transaction *transaction = new (std::nothrow) OH_Rdb_Transaction();
1072     if (transaction == nullptr) {
1073         LOG_ERROR("new OH_Rdb_Transaction failed.");
1074         return RDB_E_ERROR;
1075     }
1076     auto [ret, tmpTrans] = rdbStore->GetStore()->CreateTransaction(static_cast<int>(options->type_));
1077     transaction->trans_ = tmpTrans;
1078     *trans = transaction;
1079     return ConvertorErrorCode::NativeToNdk(ret);
1080 }
1081 
OH_Rdb_ExecuteV2(OH_Rdb_Store * store,const char * sql,const OH_Data_Values * args,OH_Data_Value ** result)1082 int OH_Rdb_ExecuteV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values *args, OH_Data_Value **result)
1083 {
1084     auto rdbStore = GetRelationalStore(store);
1085     if (rdbStore == nullptr || sql == nullptr || (args != nullptr && !args->IsValid())) {
1086         return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1087     }
1088     std::vector<ValueObject> datas;
1089     if (args != nullptr) {
1090         for (auto arg : args->values_) {
1091             if (!arg.IsValid()) {
1092                 return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS;
1093             }
1094             datas.push_back(arg.value_);
1095         }
1096     }
1097     auto innerStore = rdbStore->GetStore();
1098     if (innerStore == nullptr) {
1099         LOG_ERROR("store is nullptr");
1100         return OH_Rdb_ErrCode::RDB_E_ALREADY_CLOSED;
1101     }
1102     auto [errCode, valueObj] = innerStore->Execute(sql, datas);
1103     if (errCode != OHOS::NativeRdb::E_OK) {
1104         LOG_ERROR("execute fail, errCode=%{public}d", errCode);
1105         return ConvertorErrorCode::GetInterfaceCode(errCode);
1106     }
1107     if (result != nullptr) {
1108         OH_Data_Value *value = OH_Value_Create();
1109         if (value == nullptr) {
1110             return RDB_E_ERROR;
1111         }
1112         value->value_ = valueObj;
1113         *result = value;
1114     }
1115     return OH_Rdb_ErrCode::RDB_OK;
1116 }
1117 
OH_Rdb_ExecuteQueryV2(OH_Rdb_Store * store,const char * sql,const OH_Data_Values * args)1118 OH_Cursor *OH_Rdb_ExecuteQueryV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values *args)
1119 {
1120     auto rdbStore = GetRelationalStore(store);
1121     if (rdbStore == nullptr || sql == nullptr || (args != nullptr && !args->IsValid())) {
1122         return nullptr;
1123     }
1124     std::vector<ValueObject> datas;
1125     if (args != nullptr) {
1126         for (auto arg : args->values_) {
1127             if (!arg.IsValid()) {
1128                 LOG_ERROR("args is invalid");
1129                 return nullptr;
1130             }
1131             datas.push_back(arg.value_);
1132         }
1133     }
1134     auto innerStore = rdbStore->GetStore();
1135     if (innerStore == nullptr) {
1136         LOG_ERROR("store is nullptr");
1137         return nullptr;
1138     }
1139     auto resultSet = innerStore->QueryByStep(sql, datas);
1140     if (resultSet == nullptr) {
1141         return nullptr;
1142     }
1143     return new (std::nothrow) RelationalCursor(std::move(resultSet));
1144 }
1145 
NDKDetailProgressObserver(const Rdb_ProgressObserver * callback)1146 NDKDetailProgressObserver::NDKDetailProgressObserver(const Rdb_ProgressObserver *callback) : callback_(callback)
1147 {
1148 }
1149 
ProgressNotification(const Details & details)1150 void NDKDetailProgressObserver::ProgressNotification(const Details &details)
1151 {
1152     if (callback_ == nullptr || details.empty()) {
1153         return;
1154     }
1155     RelationalProgressDetails progressDetails = RelationalProgressDetails(details.begin()->second);
1156     (*(callback_->callback))(callback_->context, &progressDetails);
1157     progressDetails.DestroyTableDetails();
1158 }
1159 
operator ==(const Rdb_ProgressObserver * callback)1160 bool NDKDetailProgressObserver::operator==(const Rdb_ProgressObserver *callback)
1161 {
1162     return callback == callback_;
1163 }
1164 
NDKStoreObserver(const Rdb_DataObserver * observer,int mode)1165 NDKStoreObserver::NDKStoreObserver(const Rdb_DataObserver *observer, int mode) : mode_(mode), observer_(observer)
1166 {
1167 }
1168 
OnChange(const std::vector<std::string> & devices)1169 void NDKStoreObserver::OnChange(const std::vector<std::string> &devices)
1170 {
1171     if (mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD) {
1172         auto count = devices.size();
1173         std::unique_ptr<const char *[]> deviceIds = std::make_unique<const char *[]>(count);
1174         for (uint32_t i = 0; i < count; ++i) {
1175             deviceIds[i] = devices[i].c_str();
1176         }
1177         (*observer_->callback.briefObserver)(observer_->context, deviceIds.get(), count);
1178     }
1179 }
1180 
GetKeyInfoSize(RdbStoreObserver::ChangeInfo && changeInfo)1181 size_t NDKStoreObserver::GetKeyInfoSize(RdbStoreObserver::ChangeInfo &&changeInfo)
1182 {
1183     size_t size = 0;
1184     for (auto it = changeInfo.begin(); it != changeInfo.end(); ++it) {
1185         size += it->second[RdbStoreObserver::CHG_TYPE_INSERT].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1186         size += it->second[RdbStoreObserver::CHG_TYPE_UPDATE].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1187         size += it->second[RdbStoreObserver::CHG_TYPE_DELETE].size() * sizeof(Rdb_KeyInfo::Rdb_KeyData);
1188     }
1189     return size;
1190 }
1191 
GetKeyDataType(std::vector<RdbStoreObserver::PrimaryKey> & primaryKey)1192 int32_t NDKStoreObserver::GetKeyDataType(std::vector<RdbStoreObserver::PrimaryKey> &primaryKey)
1193 {
1194     if (primaryKey.size() == 0) {
1195         return OH_ColumnType::TYPE_NULL;
1196     }
1197     if (std::holds_alternative<int64_t>(primaryKey[0]) || std::holds_alternative<double>(primaryKey[0])) {
1198         return OH_ColumnType::TYPE_INT64;
1199     }
1200     if (std::holds_alternative<std::string>(primaryKey[0])) {
1201         return OH_ColumnType::TYPE_TEXT;
1202     }
1203     return OH_ColumnType::TYPE_NULL;
1204 }
1205 
OnChange(const Origin & origin,const RdbStoreObserver::PrimaryFields & fields,RdbStoreObserver::ChangeInfo && changeInfo)1206 void NDKStoreObserver::OnChange(
1207     const Origin &origin, const RdbStoreObserver::PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo)
1208 {
1209     uint32_t count = changeInfo.size();
1210     if (count == 0) {
1211         LOG_ERROR("No any infos.");
1212         return;
1213     }
1214 
1215     if (mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_CLOUD_DETAILS ||
1216         mode_ == Rdb_SubscribeType::RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) {
1217         size_t size = count * (sizeof(Rdb_ChangeInfo *) + sizeof(Rdb_ChangeInfo)) +
1218                       GetKeyInfoSize(std::forward<RdbStoreObserver::ChangeInfo &&>(changeInfo));
1219         std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
1220         Rdb_ChangeInfo **infos = (Rdb_ChangeInfo **)(buffer.get());
1221         if (infos == nullptr) {
1222             LOG_ERROR("Failed to allocate memory for Rdb_ChangeInfo.");
1223             return;
1224         }
1225 
1226         Rdb_ChangeInfo *details = (Rdb_ChangeInfo *)(infos + count);
1227         Rdb_KeyInfo::Rdb_KeyData *data = (Rdb_KeyInfo::Rdb_KeyData *)(details + count);
1228 
1229         int index = 0;
1230         for (auto it = changeInfo.begin(); it != changeInfo.end(); ++it) {
1231             infos[index] = &details[index];
1232             infos[index]->version = DISTRIBUTED_CHANGE_INFO_VERSION;
1233             infos[index]->tableName = it->first.c_str();
1234             infos[index]->ChangeType = origin.dataType;
1235             infos[index]->inserted.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_INSERT].size());
1236             infos[index]->inserted.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_INSERT]);
1237             infos[index]->updated.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_UPDATE].size());
1238             infos[index]->updated.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_UPDATE]);
1239             infos[index]->deleted.count = static_cast<int>(it->second[RdbStoreObserver::CHG_TYPE_DELETE].size());
1240             infos[index]->deleted.type = GetKeyDataType(it->second[RdbStoreObserver::CHG_TYPE_DELETE]);
1241             ConvertKeyInfoData(data, it->second[RdbStoreObserver::CHG_TYPE_INSERT]);
1242             infos[index]->inserted.data = data;
1243             ConvertKeyInfoData(data + infos[index]->inserted.count, it->second[RdbStoreObserver::CHG_TYPE_UPDATE]);
1244             infos[index]->updated.data = data + infos[index]->inserted.count;
1245             ConvertKeyInfoData(data + infos[index]->inserted.count + infos[index]->updated.count,
1246                 it->second[RdbStoreObserver::CHG_TYPE_DELETE]);
1247             infos[index]->deleted.data = data + infos[index]->inserted.count + infos[index]->updated.count;
1248             index++;
1249         }
1250 
1251         (*observer_->callback.detailsObserver)(observer_->context, const_cast<const Rdb_ChangeInfo **>(infos), count);
1252     }
1253 }
1254 
OnChange()1255 void NDKStoreObserver::OnChange()
1256 {
1257     RdbStoreObserver::OnChange();
1258 }
1259 
ConvertKeyInfoData(Rdb_KeyInfo::Rdb_KeyData * keyInfoData,std::vector<RdbStoreObserver::PrimaryKey> & primaryKey)1260 void NDKStoreObserver::ConvertKeyInfoData(
1261     Rdb_KeyInfo::Rdb_KeyData *keyInfoData, std::vector<RdbStoreObserver::PrimaryKey> &primaryKey)
1262 {
1263     if (keyInfoData == nullptr || primaryKey.empty()) {
1264         LOG_WARN("no data, keyInfoData is nullptr:%{public}d", keyInfoData == nullptr);
1265         return;
1266     }
1267 
1268     for (size_t i = 0; i < primaryKey.size(); ++i) {
1269         const auto &key = primaryKey[i];
1270         if (auto val = std::get_if<double>(&key)) {
1271             keyInfoData[i].real = *val;
1272         } else if (auto val = std::get_if<int64_t>(&key)) {
1273             keyInfoData[i].integer = *val;
1274         } else if (auto val = std::get_if<std::string>(&key)) {
1275             keyInfoData[i].text = val->c_str();
1276         } else {
1277             LOG_ERROR("Not support the data type.");
1278             return;
1279         }
1280     }
1281 }
1282 
operator ==(const Rdb_DataObserver * other)1283 bool NDKStoreObserver::operator==(const Rdb_DataObserver *other)
1284 {
1285     if (other == nullptr) {
1286         return false;
1287     }
1288     return other->context == observer_->context && &(other->callback) == &(observer_->callback);
1289 }