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 }