1 /*
2  * Copyright (c) 2022 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 "RdbStoreHelper"
16 #include "napi_rdb_store_helper.h"
17 
18 #include <functional>
19 #include <string>
20 #include <vector>
21 
22 #include "js_ability.h"
23 #include "js_utils.h"
24 #include "logger.h"
25 #include "napi_async_call.h"
26 #include "napi_rdb_error.h"
27 #include "napi_rdb_store.h"
28 #include "napi_rdb_trace.h"
29 #include "rdb_errno.h"
30 #include "rdb_open_callback.h"
31 #include "rdb_sql_utils.h"
32 #include "rdb_store_config.h"
33 #include "unistd.h"
34 
35 using namespace OHOS::Rdb;
36 using namespace OHOS::NativeRdb;
37 using namespace OHOS::AppDataMgrJsKit;
38 
39 namespace OHOS {
40 namespace RdbJsKit {
41 
42 class OpenCallback : public OHOS::NativeRdb::RdbOpenCallback {
43 public:
44     OpenCallback() = default;
45 
OpenCallback(napi_env env,napi_value jsObj)46     OpenCallback(napi_env env, napi_value jsObj) : env_(env)
47     {
48         napi_create_reference(env, jsObj, 1, &ref_);
49         napi_value property = nullptr;
50         napi_get_named_property(env_, jsObj, "onOpen", &property);
51         napi_create_reference(env, property, 1, &onOpen_);
52         napi_get_named_property(env_, jsObj, "onCreate", &property);
53         napi_create_reference(env, property, 1, &onCreate_);
54         napi_get_named_property(env_, jsObj, "onUpgrade", &property);
55         napi_create_reference(env, property, 1, &onUpgrade_);
56         napi_get_named_property(env_, jsObj, "onDowngrade", &property);
57         napi_create_reference(env, property, 1, &onDowngrade_);
58     }
59 
~OpenCallback()60     ~OpenCallback()
61     {
62         if (env_ != nullptr) {
63             napi_delete_reference(env_, ref_);
64             napi_delete_reference(env_, onOpen_);
65             napi_delete_reference(env_, onCreate_);
66             napi_delete_reference(env_, onUpgrade_);
67             napi_delete_reference(env_, onDowngrade_);
68         }
69     }
70 
71     OpenCallback(const OpenCallback &obj) = delete;
72 
73     OpenCallback &operator=(const OpenCallback &obj) = delete;
74 
OpenCallback(OpenCallback && obj)75     OpenCallback(OpenCallback &&obj) noexcept
76     {
77         operator=(std::move(obj));
78     }
79 
operator =(OpenCallback && obj)80     OpenCallback &operator=(OpenCallback &&obj) noexcept
81     {
82         if (this == &obj) {
83             return *this;
84         }
85         if (env_ != nullptr && ref_ != nullptr) {
86             napi_delete_reference(env_, ref_);
87         }
88         env_ = obj.env_;
89         ref_ = obj.ref_;
90         onOpen_ = obj.onOpen_;
91         onCreate_ = obj.onCreate_;
92         onDowngrade_ = obj.onDowngrade_;
93         onUpgrade_ = obj.onUpgrade_;
94         callbacks_ = std::move(obj.callbacks_);
95         obj.env_ = nullptr;
96         obj.ref_ = nullptr;
97         obj.onOpen_ = nullptr;
98         obj.onCreate_ = nullptr;
99         obj.onDowngrade_ = nullptr;
100         obj.onUpgrade_ = nullptr;
101         return *this;
102     }
103 
OnCreate(OHOS::NativeRdb::RdbStore & rdbStore)104     int OnCreate(OHOS::NativeRdb::RdbStore &rdbStore) override
105     {
106         LOG_DEBUG("OnCreate Callback.");
107         callbacks_.emplace_back([this]() -> int {
108             napi_value self = nullptr;
109             napi_status status = napi_get_reference_value(env_, ref_, &self);
110             if (status != napi_ok) {
111                 LOG_ERROR("OnCreate get self reference failed, code:%{public}d", status);
112                 return E_ERROR;
113             }
114             napi_value method = nullptr;
115             status = napi_get_reference_value(env_, onCreate_, &method);
116             if (status != napi_ok) {
117                 LOG_ERROR("OnCreate get method reference failed, code:%{public}d", status);
118                 return E_ERROR;
119             }
120             napi_value retValue = nullptr;
121             status = napi_call_function(env_, self, method, 0, nullptr, &retValue);
122             if (status != napi_ok) {
123                 LOG_ERROR("OnCreate call js method failed, code:%{public}d", status);
124                 return E_ERROR;
125             }
126             return E_OK;
127         });
128         return E_OK;
129     }
130 
OnUpgrade(OHOS::NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)131     int OnUpgrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override
132     {
133         LOG_DEBUG("OnUpgrade Callback.");
134         callbacks_.emplace_back([this, oldVersion, newVersion]() -> int {
135             napi_value self = nullptr;
136             napi_status status = napi_get_reference_value(env_, ref_, &self);
137             if (status != napi_ok) {
138                 LOG_ERROR("OnUpgrade get self reference failed, code:%{public}d", status);
139                 return E_ERROR;
140             }
141             napi_value method = nullptr;
142             status = napi_get_reference_value(env_, onUpgrade_, &method);
143             if (status != napi_ok) {
144                 LOG_ERROR("OnUpgrade get method reference failed, code:%{public}d", status);
145                 return E_ERROR;
146             }
147             napi_value result[JSUtils::ASYNC_RST_SIZE] = { 0 };
148             napi_get_undefined(env_, &result[0]);
149             napi_create_object(env_, &result[1]);
150             napi_value version = nullptr;
151             napi_create_int32(env_, newVersion, &version);
152             napi_set_named_property(env_, result[1], "currentVersion", version);
153             napi_create_int32(env_, oldVersion, &version);
154             napi_set_named_property(env_, result[1], "targetVersion", version);
155             napi_value retValue = nullptr;
156             status = napi_call_function(env_, self, method, JSUtils::ASYNC_RST_SIZE, result, &retValue);
157             if (status != napi_ok) {
158                 LOG_ERROR("OnUpgrade call js method failed, code:%{public}d", status);
159                 return E_ERROR;
160             }
161             return E_OK;
162         });
163         return E_OK;
164     }
165 
OnDowngrade(OHOS::NativeRdb::RdbStore & rdbStore,int oldVersion,int newVersion)166     int OnDowngrade(OHOS::NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override
167     {
168         LOG_DEBUG("OnDowngrade Callback.");
169         callbacks_.emplace_back([this, oldVersion, newVersion]() -> int {
170             napi_value self = nullptr;
171             napi_status status = napi_get_reference_value(env_, ref_, &self);
172             if (status != napi_ok) {
173                 LOG_ERROR("OnDowngrade get self reference failed, code:%{public}d", status);
174                 return E_ERROR;
175             }
176             napi_value method = nullptr;
177             status = napi_get_reference_value(env_, onDowngrade_, &method);
178             if (status != napi_ok) {
179                 LOG_ERROR("OnDowngrade get method reference failed, code:%{public}d", status);
180                 return E_ERROR;
181             }
182             napi_value result[JSUtils::ASYNC_RST_SIZE] = { 0 };
183             napi_get_undefined(env_, &result[0]);
184             napi_create_object(env_, &result[1]);
185             napi_value version = nullptr;
186             napi_create_int32(env_, newVersion, &version);
187             napi_set_named_property(env_, result[1], "currentVersion", version);
188             napi_create_int32(env_, oldVersion, &version);
189             napi_set_named_property(env_, result[1], "targetVersion", version);
190             napi_value retValue = nullptr;
191             status = napi_call_function(env_, self, method, JSUtils::ASYNC_RST_SIZE, result, &retValue);
192             if (status != napi_ok) {
193                 LOG_ERROR("OnDowngrade call js method failed, code:%{public}d", status);
194                 return E_ERROR;
195             }
196             return E_OK;
197         });
198         return E_OK;
199     }
200 
OnOpen(OHOS::NativeRdb::RdbStore & rdbStore)201     int OnOpen(OHOS::NativeRdb::RdbStore &rdbStore) override
202     {
203         LOG_DEBUG("OnOpen Callback.");
204         callbacks_.emplace_back([this]() -> int {
205             napi_value self = nullptr;
206             napi_status status = napi_get_reference_value(env_, ref_, &self);
207             if (status != napi_ok) {
208                 LOG_ERROR("OnOpen get self reference failed, code:%{public}d", status);
209                 return E_ERROR;
210             }
211             napi_value method = nullptr;
212             status = napi_get_reference_value(env_, onOpen_, &method);
213             if (status != napi_ok) {
214                 LOG_ERROR("OnOpen get method reference failed, code:%{public}d", status);
215                 return E_ERROR;
216             }
217             napi_value retValue = nullptr;
218             status = napi_call_function(env_, self, method, 0, nullptr, &retValue);
219             if (status != napi_ok) {
220                 LOG_ERROR("OnOpen call js method failed, code:%{public}d", status);
221                 return E_ERROR;
222             }
223             return E_OK;
224         });
225         return E_OK;
226     }
227 
DelayNotify()228     void DelayNotify()
229     {
230         for (auto &callback : callbacks_) {
231             callback();
232         }
233     }
234 
235 private:
236     napi_env env_ = nullptr;
237     napi_ref ref_ = nullptr;
238     napi_ref onOpen_ = nullptr;
239     napi_ref onCreate_ = nullptr;
240     napi_ref onUpgrade_ = nullptr;
241     napi_ref onDowngrade_ = nullptr;
242     std::vector<std::function<int(void)>> callbacks_;
243 };
244 
245 struct HelperRdbContext : public BaseContext {
246     RdbStoreConfig config;
247     int32_t version;
248     bool iscontext;
249     OpenCallback openCallback;
250     std::shared_ptr<RdbStore> proxy;
251     std::shared_ptr<OHOS::AppDataMgrJsKit::Context> abilitycontext;
252 
HelperRdbContextOHOS::RdbJsKit::HelperRdbContext253     HelperRdbContext() : config(""), version(0), iscontext(false), openCallback(), proxy(nullptr)
254     {
255     }
~HelperRdbContextOHOS::RdbJsKit::HelperRdbContext256     virtual ~HelperRdbContext(){};
257 };
258 
259 using ParseStoreConfigFunction = int (*)(
260     const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context);
261 
ParserThis(const napi_env & env,const napi_value & self,std::shared_ptr<HelperRdbContext> context)262 void ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr<HelperRdbContext> context)
263 {
264     napi_unwrap(env, self, &context->boundObj);
265 }
266 
ParseContext(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)267 int ParseContext(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
268 {
269     auto abilitycontext = JSAbility::GetContext(env, object);
270     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("context", "a Context.");
271     RDB_CHECK_RETURN_CALL_RESULT(abilitycontext != nullptr, context->SetError(paramError));
272     context->abilitycontext = abilitycontext;
273     return OK;
274 }
275 
ParseDatabaseName(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)276 int ParseDatabaseName(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
277 {
278     napi_value value = nullptr;
279     napi_get_named_property(env, object, "name", &value);
280     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("config", "a StoreConfig.");
281     RDB_CHECK_RETURN_CALL_RESULT(value != nullptr, context->SetError(paramError));
282 
283     std::string name = JSUtils::Convert2String(env, value);
284     RDB_CHECK_RETURN_CALL_RESULT(!name.empty(), context->SetError(paramError));
285     if (name.find("/") != std::string::npos) {
286         paramError = std::make_shared<ParamTypeError>("StoreConfig.name", "a file name without path");
287         RDB_CHECK_RETURN_CALL_RESULT(false, context->SetError(paramError));
288     }
289 
290     context->config.SetName(std::move(name));
291     return OK;
292 }
293 
ParseIsEncrypt(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)294 int ParseIsEncrypt(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
295 {
296     napi_value value = nullptr;
297     napi_status status = napi_get_named_property(env, object, "encrypt", &value);
298     if (status == napi_ok && value != nullptr) {
299         bool isEncrypt = false;
300         JSUtils::Convert2Value(env, value, isEncrypt);
301         context->config.SetEncryptStatus(isEncrypt);
302     }
303     return OK;
304 }
305 
ParseContextProperty(const napi_env & env,std::shared_ptr<HelperRdbContext> context)306 int ParseContextProperty(const napi_env &env, std::shared_ptr<HelperRdbContext> context)
307 {
308     if (context->abilitycontext == nullptr) {
309         int status = ParseContext(env, nullptr, context); // when no context as arg got from application.
310         std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("context", "a Context.");
311         RDB_CHECK_RETURN_CALL_RESULT(status == OK, context->SetError(paramError));
312     }
313     context->config.SetModuleName(context->abilitycontext->GetModuleName());
314     context->config.SetArea(context->abilitycontext->GetArea());
315     context->config.SetBundleName(context->abilitycontext->GetBundleName());
316     return OK;
317 }
318 
ParseDatabaseDir(const napi_env & env,std::shared_ptr<HelperRdbContext> context)319 int ParseDatabaseDir(const napi_env &env, std::shared_ptr<HelperRdbContext> context)
320 {
321     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("context", "a Context.");
322     RDB_CHECK_RETURN_CALL_RESULT(context->abilitycontext != nullptr, context->SetError(paramError));
323     int errorCode = E_OK;
324     std::string databaseName = context->config.GetName();
325     std::string databaseDir = context->abilitycontext->GetDatabaseDir();
326     std::string realPath = RdbSqlUtils::GetDefaultDatabasePath(databaseDir, databaseName, errorCode);
327     paramError = std::make_shared<ParamTypeError>("config", "a StoreConfig.");
328     RDB_CHECK_RETURN_CALL_RESULT(errorCode == E_OK, context->SetError(paramError));
329     context->config.SetPath(std::move(realPath));
330     return OK;
331 }
332 
ParseSecurityLevel(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)333 int ParseSecurityLevel(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
334 {
335     napi_value value = nullptr;
336     bool hasProp = false;
337     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("config", "a StoreConfig.");
338     napi_status status = napi_has_named_property(env, object, "securityLevel", &hasProp);
339     if (status != napi_ok || !hasProp) {
340         LOG_ERROR("napi_has_named_property failed! code:%{public}d!, hasProp:%{public}d!", status, hasProp);
341         RDB_CHECK_RETURN_CALL_RESULT(false, context->SetError(paramError));
342     }
343     status = napi_get_named_property(env, object, "securityLevel", &value);
344     if (status != napi_ok) {
345         LOG_ERROR("napi_get_named_property failed! code:%{public}d!", status);
346         RDB_CHECK_RETURN_CALL_RESULT(false, context->SetError(paramError));
347     }
348 
349     int32_t securityLevel;
350     napi_get_value_int32(env, value, &securityLevel);
351     SecurityLevel sl = static_cast<SecurityLevel>(securityLevel);
352     LOG_DEBUG("Get sl:%{public}d", securityLevel);
353 
354     bool isValidSecurityLevel = sl >= SecurityLevel::S1 && sl < SecurityLevel::LAST;
355     if (!isValidSecurityLevel) {
356         LOG_ERROR("The securityLevel should be S1-S4!");
357         RDB_CHECK_RETURN_CALL_RESULT(false, context->SetError(paramError));
358     }
359     context->config.SetSecurityLevel(sl);
360 
361     LOG_DEBUG("ParseSecurityLevel end.");
362     return OK;
363 }
364 
ParseStoreConfig(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)365 int ParseStoreConfig(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
366 {
367     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDatabaseName(env, object, context));
368     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseIsEncrypt(env, object, context));
369     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseContextProperty(env, context));
370     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDatabaseDir(env, context));
371     return OK;
372 }
373 
ParseStoreConfigV9(const napi_env & env,const napi_value & object,std::shared_ptr<HelperRdbContext> context)374 int ParseStoreConfigV9(const napi_env &env, const napi_value &object, std::shared_ptr<HelperRdbContext> context)
375 {
376     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDatabaseName(env, object, context));
377     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseIsEncrypt(env, object, context));
378     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSecurityLevel(env, object, context));
379     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseContextProperty(env, context));
380     RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDatabaseDir(env, context));
381     return OK;
382 }
383 
ParsePath(const napi_env env,const napi_value arg,std::shared_ptr<HelperRdbContext> context)384 int ParsePath(const napi_env env, const napi_value arg, std::shared_ptr<HelperRdbContext> context)
385 {
386     std::string path = JSUtils::Convert2String(env, arg);
387     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("name", "a without path non empty string.");
388     RDB_CHECK_RETURN_CALL_RESULT(!path.empty(), context->SetError(paramError));
389 
390     size_t pos = path.find_first_of('/');
391     RDB_CHECK_RETURN_CALL_RESULT(pos == std::string::npos, context->SetError(paramError));
392 
393     if (context->abilitycontext == nullptr) {
394         // when no context as arg got from application.
395         ParseContext(env, nullptr, context);
396     }
397     std::string databaseDir = context->abilitycontext->GetDatabaseDir();
398     int errorCode = E_OK;
399     std::string realPath = RdbSqlUtils::GetDefaultDatabasePath(databaseDir, path, errorCode);
400     RDB_CHECK_RETURN_CALL_RESULT(errorCode == E_OK, context->SetError(paramError));
401 
402     context->config.SetPath(realPath);
403     return OK;
404 }
405 
ParseVersion(const napi_env env,const napi_value arg,std::shared_ptr<HelperRdbContext> context)406 int ParseVersion(const napi_env env, const napi_value arg, std::shared_ptr<HelperRdbContext> context)
407 {
408     napi_get_value_int32(env, arg, &context->version);
409     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("version", "an integer greater than 0.");
410     RDB_CHECK_RETURN_CALL_RESULT(context->version > 0, context->SetError(paramError));
411     return OK;
412 }
413 
414 class DefaultOpenCallback : public RdbOpenCallback {
415 public:
OnCreate(RdbStore & rdbStore)416     int OnCreate(RdbStore &rdbStore) override
417     {
418         return E_OK;
419     }
OnUpgrade(RdbStore & rdbStore,int oldVersion,int newVersion)420     int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override
421     {
422         return E_OK;
423     }
424 };
425 
InnerGetRdbStore(napi_env env,napi_callback_info info,std::shared_ptr<HelperRdbContext> context,ParseStoreConfigFunction parseStoreConfig)426 napi_value InnerGetRdbStore(napi_env env, napi_callback_info info, std::shared_ptr<HelperRdbContext> context,
427     ParseStoreConfigFunction parseStoreConfig)
428 {
429     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
430     LOG_DEBUG("RdbJsKit::GetRdbStore start.");
431     context->iscontext = JSAbility::CheckContext(env, info);
432     // context: Context, config: StoreConfig, version: number
433     auto input = [context, parseStoreConfig](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
434         if (context->iscontext || context->apiversion > APIVERSION_8) {
435             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("3 or 4");
436             RDB_CHECK_RETURN_CALL_RESULT(argc == 3 || argc == 4, context->SetError(paramNumError));
437             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseContext(env, argv[0], context));
438             RDB_ASYNC_PARAM_CHECK_FUNCTION(parseStoreConfig(env, argv[1], context));
439             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseVersion(env, argv[2], context));
440         } else {
441             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
442             RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
443             RDB_ASYNC_PARAM_CHECK_FUNCTION(parseStoreConfig(env, argv[0], context));
444             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseVersion(env, argv[1], context));
445         }
446         ParserThis(env, self, context);
447         return OK;
448     };
449     auto exec = [context]() -> int {
450         LOG_DEBUG("RdbJsKit::GetRdbStore Async.");
451         int errCode = OK;
452         DefaultOpenCallback callback;
453         context->proxy = RdbHelper::GetRdbStore(context->config, context->version, callback, errCode);
454         std::shared_ptr<Error> dbInvalidError = std::make_shared<DbInvalidError>();
455         RDB_CHECK_RETURN_CALL_RESULT(errCode == E_OK && context->proxy != nullptr, context->SetError(dbInvalidError));
456         return (errCode == E_OK) ? OK : ERR;
457     };
458     auto output = [context](napi_env env, napi_value &result) -> int {
459         result = RdbStoreProxy::NewInstance(env, context->proxy, context->apiversion);
460         context->openCallback.DelayNotify();
461         LOG_DEBUG("RdbJsKit::GetRdbStore end.");
462         return (result != nullptr) ? OK : ERR;
463     };
464     context->SetAction(env, info, input, exec, output);
465 
466     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK,
467         "RdbJsKit::GetRdbStore end with err");
468     return AsyncCall::Call(env, context);
469 }
470 
GetRdbStore(napi_env env,napi_callback_info info)471 napi_value GetRdbStore(napi_env env, napi_callback_info info)
472 {
473     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
474     auto context = std::make_shared<HelperRdbContext>();
475     context->apiversion = APIVERSION_8;
476     return InnerGetRdbStore(env, info, context, ParseStoreConfig);
477 }
478 
GetRdbStoreV9(napi_env env,napi_callback_info info)479 napi_value GetRdbStoreV9(napi_env env, napi_callback_info info)
480 {
481     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
482     auto context = std::make_shared<HelperRdbContext>();
483     context->apiversion = APIVERSION_V9;
484     return InnerGetRdbStore(env, info, context, ParseStoreConfigV9);
485 }
486 
InnerDeleteRdbStore(napi_env env,napi_callback_info info,std::shared_ptr<HelperRdbContext> context)487 napi_value InnerDeleteRdbStore(napi_env env, napi_callback_info info, std::shared_ptr<HelperRdbContext> context)
488 {
489     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
490     LOG_DEBUG("RdbJsKit::DeleteRdbStore start.");
491     context->iscontext = JSAbility::CheckContext(env, info);
492     // context: Context, config: StoreConfig, version: number
493     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
494         if (context->iscontext || context->apiversion > APIVERSION_8) {
495             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
496             RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
497             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseContext(env, argv[0], context));
498             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePath(env, argv[1], context));
499         } else {
500             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1 or 2");
501             RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError));
502             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePath(env, argv[0], context));
503         }
504         return OK;
505     };
506     auto exec = [context]() -> int {
507         int errCode = RdbHelper::DeleteRdbStore(context->config.GetPath());
508         LOG_DEBUG("RdbJsKit::DeleteRdbStore failed %{public}d", errCode);
509         std::shared_ptr<Error> dbInvalidError = std::make_shared<DbInvalidError>();
510         RDB_CHECK_RETURN_CALL_RESULT(errCode != E_INVALID_FILE_PATH, context->SetError(dbInvalidError));
511         return (errCode == E_OK) ? OK : ERR;
512     };
513     auto output = [context](napi_env env, napi_value &result) -> int {
514         napi_status status = napi_create_int64(env, OK, &result);
515         LOG_DEBUG("RdbJsKit::DeleteRdbStore end.");
516         return (status == napi_ok) ? OK : ERR;
517     };
518     context->SetAction(env, info, input, exec, output);
519 
520     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK,
521         "RdbJsKit::DeleteRdbStore end with err");
522     return AsyncCall::Call(env, context);
523 }
524 
DeleteRdbStore(napi_env env,napi_callback_info info)525 napi_value DeleteRdbStore(napi_env env, napi_callback_info info)
526 {
527     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
528     auto context = std::make_shared<HelperRdbContext>();
529     context->apiversion = APIVERSION_8;
530     return InnerDeleteRdbStore(env, info, context);
531 }
532 
DeleteRdbStoreV9(napi_env env,napi_callback_info info)533 napi_value DeleteRdbStoreV9(napi_env env, napi_callback_info info)
534 {
535     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
536     auto context = std::make_shared<HelperRdbContext>();
537     context->apiversion = APIVERSION_V9;
538     return InnerDeleteRdbStore(env, info, context);
539 }
540 
InitRdbHelper(napi_env env,napi_value exports)541 napi_value InitRdbHelper(napi_env env, napi_value exports)
542 {
543     napi_property_descriptor properties[] = {
544         DECLARE_NAPI_FUNCTION("getRdbStore", GetRdbStore),
545         DECLARE_NAPI_FUNCTION("deleteRdbStore", DeleteRdbStore),
546         DECLARE_NAPI_FUNCTION("getRdbStoreV9", GetRdbStoreV9),
547         DECLARE_NAPI_FUNCTION("deleteRdbStoreV9", DeleteRdbStoreV9),
548     };
549     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
550     return exports;
551 }
552 } // namespace RdbJsKit
553 } // namespace OHOS
554