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 "RdbStoreProxy"
16 #include "napi_rdb_store.h"
17 
18 #include <cinttypes>
19 #include <string>
20 #include <vector>
21 
22 #include "js_utils.h"
23 #include "logger.h"
24 #include "napi_async_call.h"
25 #include "napi_rdb_error.h"
26 #include "napi_rdb_predicates.h"
27 #include "napi_rdb_trace.h"
28 #include "napi_result_set.h"
29 #include "rdb_errno.h"
30 
31 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
32 #include "rdb_utils.h"
33 using namespace OHOS::DataShare;
34 #endif
35 
36 using namespace OHOS::Rdb;
37 using namespace OHOS::NativeRdb;
38 using namespace OHOS::AppDataMgrJsKit;
39 
40 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
41 using OHOS::DistributedRdb::SubscribeMode;
42 using OHOS::DistributedRdb::SubscribeOption;
43 using OHOS::DistributedRdb::SyncOption;
44 using OHOS::DistributedRdb::SyncResult;
45 #endif
46 
47 namespace OHOS {
48 namespace RdbJsKit {
49 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
50 struct PredicatesProxy {
51     std::shared_ptr<DataShareAbsPredicates> predicates_;
52 };
53 #endif
54 struct RdbStoreContext : public BaseContext {
55     bool isNapiString = false;
56     std::string device;
57     std::string tableName;
58     std::vector<std::string> tablesName;
59     std::string whereClause;
60     std::vector<std::string> whereArgs;
61     std::vector<std::string> selectionArgs;
62     std::string sql;
63     RdbPredicatesProxy *predicatesProxy;
64     std::vector<std::string> columns;
65     ValuesBucket valuesBucket;
66     std::vector<ValuesBucket> valuesBuckets;
67     std::map<std::string, ValueObject> numberMaps;
68     std::vector<ValueObject> bindArgs;
69     uint64_t rowId;
70     uint64_t insertNum;
71     std::vector<uint8_t> newKey;
72 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
73     std::shared_ptr<AbsSharedResultSet> resultSet;
74 #else
75     std::shared_ptr<ResultSet> resultSet;
76 #endif
77     std::shared_ptr<ResultSet> stepResultSet;
78     std::string aliasName;
79     std::string pathName;
80     std::string srcName;
81     int32_t enumArg;
82 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
83     DistributedRdb::SyncResult syncResult;
84 #endif
85     std::shared_ptr<RdbPredicates> rdbPredicates = nullptr;
86 
RdbStoreContextOHOS::RdbJsKit::RdbStoreContext87     RdbStoreContext() : predicatesProxy(nullptr), rowId(0), insertNum(0), enumArg(0)
88     {
89     }
~RdbStoreContextOHOS::RdbJsKit::RdbStoreContext90     virtual ~RdbStoreContext()
91     {
92     }
93 };
94 
95 static __thread napi_ref constructor_ = nullptr;
96 static __thread napi_ref constructorV9_ = nullptr;
97 
RdbStoreProxy()98 RdbStoreProxy::RdbStoreProxy()
99 {
100 }
101 
~RdbStoreProxy()102 RdbStoreProxy::~RdbStoreProxy()
103 {
104     LOG_DEBUG("RdbStoreProxy destructor.");
105 }
106 
Init(napi_env env,napi_value exports)107 void RdbStoreProxy::Init(napi_env env, napi_value exports)
108 {
109     napi_property_descriptor descriptors[] = {
110         DECLARE_NAPI_FUNCTION("delete", Delete),
111         DECLARE_NAPI_FUNCTION("update", Update),
112         DECLARE_NAPI_FUNCTION("insert", Insert),
113         DECLARE_NAPI_FUNCTION("batchInsert", BatchInsert),
114         DECLARE_NAPI_FUNCTION("querySql", QuerySql),
115         DECLARE_NAPI_FUNCTION("query", Query),
116         DECLARE_NAPI_FUNCTION("executeSql", ExecuteSql),
117         DECLARE_NAPI_FUNCTION("replace", Replace),
118         DECLARE_NAPI_FUNCTION("count", Count),
119         DECLARE_NAPI_FUNCTION("addAttach", Attach),
120         DECLARE_NAPI_FUNCTION("beginTransaction", BeginTransaction),
121         DECLARE_NAPI_FUNCTION("rollBack", RollBack),
122         DECLARE_NAPI_FUNCTION("commit", Commit),
123         DECLARE_NAPI_FUNCTION("queryByStep", QueryByStep),
124         DECLARE_NAPI_FUNCTION("getVersion", GetVersion),
125         DECLARE_NAPI_FUNCTION("setVersion", SetVersion),
126         DECLARE_NAPI_GETTER("isInTransaction", IsInTransaction),
127         DECLARE_NAPI_GETTER("isOpen", IsOpen),
128         DECLARE_NAPI_GETTER("path", GetPath),
129         DECLARE_NAPI_GETTER("isHoldingConnection", IsHoldingConnection),
130         DECLARE_NAPI_GETTER("isReadOnly", IsReadOnly),
131         DECLARE_NAPI_GETTER("isMemoryRdb", IsMemoryRdb),
132 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
133         DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables),
134         DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName),
135         DECLARE_NAPI_FUNCTION("sync", Sync),
136         DECLARE_NAPI_FUNCTION("on", OnEvent),
137         DECLARE_NAPI_FUNCTION("off", OffEvent),
138 #endif
139     };
140     napi_value cons = nullptr;
141     NAPI_CALL_RETURN_VOID(env, napi_define_class(env, "RdbStore", NAPI_AUTO_LENGTH, Initialize, nullptr,
142                                    sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &cons));
143     NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, cons, 1, &constructor_));
144 
145     NAPI_CALL_RETURN_VOID(env, napi_define_class(env, "RdbStoreV9", NAPI_AUTO_LENGTH, InitializeV9, nullptr,
146                                    sizeof(descriptors) / sizeof(napi_property_descriptor), descriptors, &cons));
147     NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, cons, 1, &constructorV9_));
148 }
149 
InnerInitialize(napi_env env,napi_callback_info info,int version)150 napi_value RdbStoreProxy::InnerInitialize(napi_env env, napi_callback_info info, int version)
151 {
152     napi_value self = nullptr;
153     NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr));
154     auto finalize = [](napi_env env, void *data, void *hint) {
155         RdbStoreProxy *proxy = reinterpret_cast<RdbStoreProxy *>(data);
156         delete proxy;
157     };
158     auto *proxy = new (std::nothrow) RdbStoreProxy();
159     if (proxy == nullptr) {
160         return nullptr;
161     }
162     proxy->apiversion = version;
163     napi_status status = napi_wrap(env, self, proxy, finalize, nullptr, nullptr);
164     if (status != napi_ok) {
165         LOG_ERROR("RdbStoreProxy::Initialize napi_wrap failed! code:%{public}d!", status);
166         delete proxy;
167         return nullptr;
168     }
169     return self;
170 }
171 
Initialize(napi_env env,napi_callback_info info)172 napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info)
173 {
174     return InnerInitialize(env, info, APIVERSION_8);
175 }
176 
InitializeV9(napi_env env,napi_callback_info info)177 napi_value RdbStoreProxy::InitializeV9(napi_env env, napi_callback_info info)
178 {
179     return InnerInitialize(env, info, APIVERSION_V9);
180 }
181 
NewInstance(napi_env env,std::shared_ptr<OHOS::NativeRdb::RdbStore> value,int version)182 napi_value RdbStoreProxy::NewInstance(napi_env env, std::shared_ptr<OHOS::NativeRdb::RdbStore> value, int version)
183 {
184     if (value == nullptr) {
185         LOG_ERROR("RdbStoreProxy::NewInstance get native rdb is null.");
186         return nullptr;
187     }
188     napi_value cons = nullptr;
189     napi_status status;
190     if (version > APIVERSION_8) {
191         status = napi_get_reference_value(env, constructorV9_, &cons);
192     } else {
193         status = napi_get_reference_value(env, constructor_, &cons);
194     }
195 
196     if (status != napi_ok) {
197         LOG_ERROR("RdbStoreProxy::NewInstance get constructor failed! code:%{public}d!", status);
198         return nullptr;
199     }
200 
201     napi_value instance = nullptr;
202     status = napi_new_instance(env, cons, 0, nullptr, &instance);
203     if (status != napi_ok) {
204         LOG_ERROR("RdbStoreProxy::NewInstance napi_new_instance failed! code:%{public}d!", status);
205         return nullptr;
206     }
207 
208     RdbStoreProxy *proxy = nullptr;
209     status = napi_unwrap(env, instance, reinterpret_cast<void **>(&proxy));
210     if (proxy == nullptr) {
211         LOG_ERROR("RdbStoreProxy::NewInstance native instance is nullptr! code:%{public}d!", status);
212         return instance;
213     }
214     proxy->rdbStore_ = std::move(value);
215     proxy->apiversion = version;
216     return instance;
217 }
218 
GetNativeInstance(napi_env env,napi_value self)219 RdbStoreProxy *RdbStoreProxy::GetNativeInstance(napi_env env, napi_value self)
220 {
221     RdbStoreProxy *proxy = nullptr;
222     napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&proxy));
223     if (proxy == nullptr) {
224         LOG_ERROR("RdbStoreProxy::GetNativePredicates native instance is nullptr! code:%{public}d!", status);
225         return nullptr;
226     }
227     return proxy;
228 }
229 
ParserThis(const napi_env & env,const napi_value & self,std::shared_ptr<RdbStoreContext> context)230 int ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr<RdbStoreContext> context)
231 {
232     RdbStoreProxy *obj = RdbStoreProxy::GetNativeInstance(env, self);
233     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("RdbStore", "not nullptr.");
234     RDB_CHECK_RETURN_CALL_RESULT(obj, context->SetError(paramError));
235     context->apiversion = obj->apiversion;
236     context->boundObj = obj;
237     LOG_DEBUG("ParserThis RdbStoreProxy is v%{public}d.", obj->apiversion);
238     return OK;
239 }
240 
ParseTableName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)241 int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
242 {
243     context->tableName = JSUtils::Convert2String(env, arg);
244     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("table", "a non empty string.");
245     RDB_CHECK_RETURN_CALL_RESULT(!context->tableName.empty(), context->SetError(paramError));
246 
247     LOG_DEBUG("ParseTableName end.");
248     return OK;
249 }
250 
ParseDevice(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)251 int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
252 {
253     context->device = JSUtils::Convert2String(env, arg);
254     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("device", "a non empty string.");
255     RDB_CHECK_RETURN_CALL_RESULT(!context->device.empty(), context->SetError(paramError));
256 
257     LOG_DEBUG("ParseDevice end.");
258     return OK;
259 }
260 
ParseTablesName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)261 int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
262 {
263     uint32_t arrLen = 0;
264     napi_get_array_length(env, arg, &arrLen);
265     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("tables", "a string array.");
266     RDB_CHECK_RETURN_CALL_RESULT(arrLen >= 0, context->SetError(paramError));
267 
268     for (uint32_t i = 0; i < arrLen; ++i) {
269         napi_value element = nullptr;
270         napi_get_element(env, arg, i, &element);
271         napi_valuetype type = napi_undefined;
272         napi_typeof(env, element, &type);
273         if (type == napi_string) {
274             std::string table = JSUtils::Convert2String(env, element);
275             context->tablesName.push_back(table);
276         }
277     }
278     LOG_DEBUG("ParseTablesName end.");
279     return OK;
280 }
281 
ParseSyncModeArg(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)282 int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
283 {
284     napi_get_value_int32(env, arg, &context->enumArg);
285     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("mode", "a SyncMode.");
286     RDB_CHECK_RETURN_CALL_RESULT(context->enumArg == 0 || context->enumArg == 1, context->SetError(paramError));
287 
288     LOG_DEBUG("ParseSyncModeArg end.");
289     return OK;
290 }
291 
CheckGlobalProperty(const napi_env env,const napi_value arg,const std::string & propertyName)292 bool CheckGlobalProperty(const napi_env env, const napi_value arg, const std::string &propertyName)
293 {
294     LOG_DEBUG("CheckGlobalProperty start: %{public}s.", propertyName.c_str());
295     napi_value global = nullptr;
296     napi_status status = napi_get_global(env, &global);
297     if (status != napi_ok) {
298         return false;
299     }
300     napi_value constructor = nullptr;
301     status = napi_get_named_property(env, global, propertyName.c_str(), &constructor);
302     if (status != napi_ok) {
303         return false;
304     }
305     bool result = false;
306     status = napi_instanceof(env, arg, constructor, &result);
307     return (status == napi_ok ? result : false);
308 }
309 
ParsePredicates(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)310 int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
311 {
312     LOG_DEBUG("ParsePredicates start.");
313     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("predicates", "an RdbPredicates.");
314     if (CheckGlobalProperty(env, arg, "RdbPredicatesConstructor")
315         || CheckGlobalProperty(env, arg, "RdbPredicatesConstructorV9")) {
316         LOG_DEBUG("Parse RDB Predicates.");
317         napi_unwrap(env, arg, reinterpret_cast<void **>(&context->predicatesProxy));
318         RDB_CHECK_RETURN_CALL_RESULT(context->predicatesProxy != nullptr &&
319             context->predicatesProxy->GetPredicates() != nullptr, context->SetError(paramError));
320         context->tableName = context->predicatesProxy->GetPredicates()->GetTableName();
321         context->rdbPredicates = context->predicatesProxy->GetPredicates();
322         LOG_DEBUG("ParsePredicates end.");
323         return OK;
324     }
325 
326     LOG_DEBUG("Isn't RdbPredicates, maybe DataShare Predicates.");
327 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
328     paramError = std::make_shared<ParamTypeError>("predicates", "an RdbPredicates or DataShare Predicates.");
329     PredicatesProxy *proxy = nullptr;
330     napi_unwrap(env, arg, reinterpret_cast<void **>(&proxy));
331     // proxy is nullptr, it isn't rdb predicates or datashare predicates
332     RDB_CHECK_RETURN_CALL_RESULT(proxy != nullptr, context->SetError(paramError));
333     // proxy is not nullptr, it's a datashare predicates.
334     LOG_DEBUG("Parse DataShare Predicates.");
335     paramError = std::make_shared<ParamTypeError>("predicates", "an DataShare Predicates.");
336     LOG_ERROR("dsPredicates is null ? %{public}d.", (proxy->predicates_ == nullptr));
337     RDB_CHECK_RETURN_CALL_RESULT(proxy->predicates_ != nullptr, context->SetError(paramError));
338     std::shared_ptr<DataShareAbsPredicates> dsPredicates = proxy->predicates_;
339     context->rdbPredicates = std::make_shared<RdbPredicates>(
340         RdbDataShareAdapter::RdbUtils::ToPredicates(*dsPredicates, context->tableName));
341 #endif
342     LOG_DEBUG("ParsePredicates end.");
343     return OK;
344 }
345 
ParseSrcName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)346 int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
347 {
348     context->srcName = JSUtils::Convert2String(env, arg);
349     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("srcName", "a non empty string.");
350     RDB_CHECK_RETURN_CALL_RESULT(!context->srcName.empty(), context->SetError(paramError));
351 
352     LOG_DEBUG("ParseSrcName end.");
353     return OK;
354 }
355 
ParseColumns(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)356 int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
357 {
358     napi_valuetype type = napi_undefined;
359     napi_typeof(env, arg, &type);
360     if (type == napi_undefined || type == napi_null) {
361         return OK;
362     }
363     int32_t ret = JSUtils::Convert2Value(env, arg, context->columns);
364     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("columns", "a non empty string.");
365     RDB_CHECK_RETURN_CALL_RESULT(ret == napi_ok, context->SetError(paramError));
366     return OK;
367 }
368 
ParseWhereClause(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)369 int ParseWhereClause(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
370 {
371     context->whereClause = JSUtils::Convert2String(env, arg);
372     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("whereClause", "a non empty string.");
373     RDB_CHECK_RETURN_CALL_RESULT(!context->whereClause.empty(), context->SetError(paramError));
374 
375     LOG_DEBUG("ParseWhereClause end.");
376     return OK;
377 }
378 
ParseAlias(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)379 int ParseAlias(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
380 {
381     context->aliasName = JSUtils::Convert2String(env, arg);
382     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("aliasName", "a non empty string.");
383     RDB_CHECK_RETURN_CALL_RESULT(!context->aliasName.empty(), context->SetError(paramError));
384 
385     LOG_DEBUG("ParseAlias end.");
386     return OK;
387 }
388 
ParsePath(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)389 int ParsePath(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
390 {
391     context->pathName = JSUtils::Convert2String(env, arg);
392     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("pathName", "a non empty string.");
393     RDB_CHECK_RETURN_CALL_RESULT(!context->pathName.empty(), context->SetError(paramError));
394 
395     LOG_DEBUG("ParsePath end.");
396     return OK;
397 }
398 
ParseWhereArgs(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)399 int ParseWhereArgs(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
400 {
401     napi_valuetype type = napi_undefined;
402     napi_typeof(env, arg, &type);
403     if (type == napi_undefined || type == napi_null) {
404         return OK;
405     }
406     int32_t ret = JSUtils::Convert2Value(env, arg, context->whereArgs);
407     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("columns", "a non empty string.");
408     RDB_CHECK_RETURN_CALL_RESULT(ret == napi_ok, context->SetError(paramError));
409     return OK;
410 }
411 
ParseSelectionArgs(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)412 int ParseSelectionArgs(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
413 {
414     napi_valuetype type = napi_undefined;
415     napi_typeof(env, arg, &type);
416     if (type == napi_undefined || type == napi_null) {
417         return OK;
418     }
419     int32_t ret = JSUtils::Convert2Value(env, arg, context->selectionArgs);
420     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("columns", "a non empty string.");
421     RDB_CHECK_RETURN_CALL_RESULT(ret == napi_ok, context->SetError(paramError));
422     return OK;
423 }
424 
ParseSql(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)425 int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
426 {
427     context->sql = JSUtils::Convert2String(env, arg);
428     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("sql", "a non empty string.");
429     RDB_CHECK_RETURN_CALL_RESULT(!context->sql.empty(), context->SetError(paramError));
430 
431     LOG_DEBUG("ParseSql end.");
432     return OK;
433 }
434 
ParseValuesBucket(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)435 int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
436 {
437     napi_value keys = nullptr;
438     napi_get_all_property_names(env, arg, napi_key_own_only,
439         static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols),
440         napi_key_numbers_to_strings, &keys);
441     uint32_t arrLen = 0;
442     napi_status status = napi_get_array_length(env, keys, &arrLen);
443     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("values", "a ValuesBucket.");
444     RDB_CHECK_RETURN_CALL_RESULT(status == napi_ok, context->SetError(paramError));
445 
446     for (size_t i = 0; i < arrLen; ++i) {
447         napi_value key = nullptr;
448         status = napi_get_element(env, keys, i, &key);
449         if (status != napi_ok) {
450             LOG_DEBUG("ValuesBucket get_element errr.");
451         }
452         RDB_CHECK_RETURN_CALL_RESULT(status == napi_ok, context->SetError(paramError));
453 
454         std::string keyStr = JSUtils::Convert2String(env, key);
455         napi_value value = nullptr;
456         napi_get_property(env, arg, key, &value);
457 
458         ValueObject valueObject;
459         int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
460         if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB) {
461             std::vector<uint8_t> tmpValue;
462             valueObject.GetBlob(tmpValue);
463             if (tmpValue.empty()) {
464                 valueObject = ValueObject();
465             }
466         }
467         if (ret == napi_ok) {
468             context->valuesBucket.Put(keyStr, std::move(valueObject));
469         } else if (ret != napi_generic_failure) {
470             std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>(
471                 "The value type of " + keyStr, "valid.");
472             RDB_CHECK_RETURN_CALL_RESULT(false, context->SetError(paramError));
473         }
474     }
475     LOG_DEBUG("ParseValuesBucket end.");
476     return OK;
477 }
478 
ParseValuesBuckets(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)479 int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
480 {
481     bool isArray = false;
482     napi_is_array(env, arg, &isArray);
483     std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("values", "a ValuesBucket array.");
484     if (!isArray) {
485         context->insertNum = -1;
486         RDB_CHECK_RETURN_CALL_RESULT(isArray, context->SetError(paramError));
487     }
488     uint32_t arrLen = 0;
489     napi_status status = napi_get_array_length(env, arg, &arrLen);
490     RDB_CHECK_RETURN_CALL_RESULT(status == napi_ok || arrLen >= 0, context->SetError(paramError));
491 
492     for (uint32_t i = 0; i < arrLen; ++i) {
493         napi_value obj = nullptr;
494         status = napi_get_element(env, arg, i, &obj);
495         RDB_CHECK_RETURN_CALL_RESULT(status == napi_ok || arrLen >= 0, context->SetError(paramError));
496 
497         ParseValuesBucket(env, obj, context);
498         context->valuesBuckets.push_back(context->valuesBucket);
499         context->valuesBucket.Clear();
500     }
501     return OK;
502 }
503 
IsNapiString(napi_env env,napi_callback_info info)504 bool IsNapiString(napi_env env, napi_callback_info info)
505 {
506     constexpr size_t MIN_ARGC = 1;
507     size_t argc = MIN_ARGC;
508     napi_value args[1] = { 0 };
509     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
510     if (argc < MIN_ARGC) {
511         return false;
512     }
513     napi_valuetype type = napi_undefined;
514     napi_typeof(env, args[0], &type);
515     if (type == napi_string) {
516         return true;
517     }
518     return false;
519 }
520 
Insert(napi_env env,napi_callback_info info)521 napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info)
522 {
523     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
524     LOG_DEBUG("RdbStoreProxy::Insert start.");
525     auto context = std::make_shared<RdbStoreContext>();
526     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
527         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
528         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
529         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
530         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseValuesBucket(env, argv[1], context));
531         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
532         return OK;
533     };
534     auto exec = [context]() {
535         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
536         int64_t rowId = 0;
537         LOG_DEBUG("RdbStoreProxy::Insert Async.");
538         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
539         int errCode = obj->rdbStore_->Insert(rowId, context->tableName, context->valuesBucket);
540         context->rowId = rowId;
541         LOG_DEBUG("RdbStoreProxy::Insert errCode is: %{public}d.", errCode);
542         return (errCode == E_OK) ? OK : ERR;
543     };
544     auto output = [context](napi_env env, napi_value &result) -> int {
545         napi_status status = napi_create_int64(env, context->rowId, &result);
546         LOG_DEBUG("RdbStoreProxy::Insert end.");
547         return (status == napi_ok) ? OK : ERR;
548     };
549     context->SetAction(env, info, input, exec, output);
550 
551     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
552     return AsyncCall::Call(env, context);
553 }
554 
BatchInsert(napi_env env,napi_callback_info info)555 napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info)
556 {
557     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
558     LOG_DEBUG("RdbStoreProxy::BatchInsert start.");
559     auto context = std::make_shared<RdbStoreContext>();
560     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
561         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
562         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
563         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
564         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseValuesBuckets(env, argv[1], context));
565         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
566         return OK;
567     };
568     auto exec = [context]() {
569         LOG_INFO("RdbStoreProxy::BatchInsert Async.");
570         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
571         if (context->insertNum == -1UL) {
572             return E_OK;
573         }
574         int64_t outInsertNum = 0;
575         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
576         int errCode = obj->rdbStore_->BatchInsert(outInsertNum, context->tableName, context->valuesBuckets);
577         context->insertNum = outInsertNum;
578         return (errCode == E_OK) ? OK : ERR;
579     };
580     auto output = [context](napi_env env, napi_value &result) -> int {
581         napi_status status = napi_create_int64(env, context->insertNum, &result);
582         LOG_DEBUG("RdbStoreProxy::BatchInsert end. tableName is: %{public}s.",
583             context->tableName.c_str());
584         return (status == napi_ok) ? OK : ERR;
585     };
586     context->SetAction(env, info, input, exec, output);
587 
588     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
589     return AsyncCall::Call(env, context);
590 }
591 
Delete(napi_env env,napi_callback_info info)592 napi_value RdbStoreProxy::Delete(napi_env env, napi_callback_info info)
593 {
594     LOG_DEBUG("RdbStoreProxy::Delete start.");
595     auto context = std::make_shared<RdbStoreContext>();
596     context->isNapiString = IsNapiString(env, info);
597     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
598         if (context->isNapiString) {
599             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
600             RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
601             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
602             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[1], context));
603         } else {
604             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1 or 2");
605             RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError));
606             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[0], context));
607         }
608         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
609         return OK;
610     };
611     auto exec = [context]() {
612         LOG_DEBUG("RdbStoreProxy::Delete Async.");
613         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
614         int deletedRows = 0;
615         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
616         int errCode = obj->rdbStore_->Delete(deletedRows, *(context->rdbPredicates));
617         context->rowId = deletedRows;
618         LOG_DEBUG("RdbStoreProxy::Delete errCode is: %{public}d.", errCode);
619         return (errCode == E_OK) ? OK : ERR;
620     };
621     auto output = [context](napi_env env, napi_value &result) -> int {
622         napi_status status = napi_create_int64(env, context->rowId, &result);
623         LOG_DEBUG("RdbStoreProxy::Delete end.");
624         return (status == napi_ok) ? OK : ERR;
625     };
626     context->SetAction(env, info, input, exec, output);
627 
628     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
629     return AsyncCall::Call(env, context);
630 }
631 
Update(napi_env env,napi_callback_info info)632 napi_value RdbStoreProxy::Update(napi_env env, napi_callback_info info)
633 {
634     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
635     LOG_DEBUG("RdbStoreProxy::Update start.");
636     auto context = std::make_shared<RdbStoreContext>();
637     context->isNapiString = IsNapiString(env, info);
638     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
639         if (context->isNapiString) {
640             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("3 or 4");
641             RDB_CHECK_RETURN_CALL_RESULT(argc == 3 || argc == 4, context->SetError(paramNumError));
642             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
643             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseValuesBucket(env, argv[1], context));
644             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[2], context));
645         } else {
646             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
647             RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
648             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseValuesBucket(env, argv[0], context));
649             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[1], context));
650         }
651         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
652         return OK;
653     };
654     auto exec = [context]() {
655         LOG_DEBUG("RdbStoreProxy::Update Async.");
656         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
657         int changedRows = 0;
658         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
659         int errCode = obj->rdbStore_->Update(changedRows, context->valuesBucket, *(context->rdbPredicates));
660         context->rowId = changedRows;
661         LOG_DEBUG("RdbStoreProxy::Update errCode is: %{public}d.", errCode);
662         return (errCode == E_OK) ? OK : ERR;
663     };
664     auto output = [context](napi_env env, napi_value &result) -> int {
665         napi_status status = napi_create_int64(env, context->rowId, &result);
666         LOG_DEBUG("RdbStoreProxy::Update end.");
667         return (status == napi_ok) ? OK : ERR;
668     };
669     context->SetAction(env, info, input, exec, output);
670 
671     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
672     return AsyncCall::Call(env, context);
673 }
674 
Query(napi_env env,napi_callback_info info)675 napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info)
676 {
677     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
678     auto context = std::make_shared<RdbStoreContext>();
679     context->isNapiString = IsNapiString(env, info);
680     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
681         if (context->isNapiString) {
682             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1, 2 or 3");
683             RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2 || argc == 3, context->SetError(paramNumError));
684             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
685             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[1], context));
686             if (argc > 2) {
687                 RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseColumns(env, argv[2], context));
688             }
689         } else {
690             std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1 or 2");
691             RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError));
692             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[0], context));
693             if (argc > 1) {
694                 RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseColumns(env, argv[1], context));
695             }
696         }
697         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
698         return OK;
699     };
700     auto exec = [context]() {
701         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
702         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
703 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
704         context->resultSet = obj->rdbStore_->QueryByStep(*(context->rdbPredicates), context->columns);
705 #else
706         context->resultSet = obj->rdbStore_->Query(*(context->rdbPredicates), context->columns);
707 #endif
708         LOG_DEBUG("RdbStoreProxy::Query result is nullptr ? %{public}d.", (context->resultSet == nullptr));
709         return (context->resultSet != nullptr) ? OK : ERR;
710     };
711     auto output = [context](napi_env env, napi_value &result) -> int {
712         result = ResultSetProxy::NewInstance(
713             env, context->resultSet, context->apiversion);
714         return (result != nullptr) ? OK : ERR;
715     };
716     context->SetAction(env, info, input, exec, output);
717 
718     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
719     return AsyncCall::Call(env, context);
720 }
721 
QuerySql(napi_env env,napi_callback_info info)722 napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info)
723 {
724     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
725     auto context = std::make_shared<RdbStoreContext>();
726     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
727         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1, 2 or 3");
728         RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2 || argc == 3, context->SetError(paramNumError));
729         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSql(env, argv[0], context));
730         if (argc > 1) {
731 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
732             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseColumns(env, argv[1], context));
733 #else
734             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSelectionArgs(env, argv[1], context));
735 #endif
736         }
737         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
738         return OK;
739     };
740     auto exec = [context]() {
741         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
742 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
743         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
744         context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns);
745         LOG_ERROR("RdbStoreProxy::QuerySql is nullptr ? %{public}d ", context->resultSet == nullptr);
746         return (context->resultSet != nullptr) ? OK : ERR;
747 #else
748         std::string selectionArgs = ",";
749         for (size_t i = 0; i < context->selectionArgs.size(); i++) {
750             selectionArgs += context->selectionArgs[i];
751         }
752         context->resultSet = obj->rdbStore_->QuerySql(context->sql, context->selectionArgs);
753         return (context->resultSet != nullptr) ? OK : ERR;
754 #endif
755     };
756     auto output = [context](napi_env env, napi_value &result) -> int {
757         result = ResultSetProxy::NewInstance(
758             env, context->resultSet, context->apiversion);
759         return (result != nullptr) ? OK : ERR;
760     };
761     context->SetAction(env, info, input, exec, output);
762 
763     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
764     return AsyncCall::Call(env, context);
765 }
766 
ParseBindArgs(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)767 int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
768 {
769     context->bindArgs.clear();
770     uint32_t arrLen = 0;
771     napi_get_array_length(env, arg, &arrLen);
772     if (arrLen == 0) {
773         return OK;
774     }
775     for (uint32_t i = 0; i < arrLen; ++i) {
776         napi_value element = nullptr;
777         napi_get_element(env, arg, i, &element);
778 
779         ValueObject valueObject;
780         int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value);
781         std::shared_ptr<Error> paramError = std::make_shared<ParamTypeError>("tables", "a string array.");
782         RDB_CHECK_RETURN_CALL_RESULT(ret == napi_ok, context->SetError(paramError));
783         if (valueObject.GetType() == ValueObject::TYPE_BLOB) {
784             std::vector<uint8_t> tmpValue;
785             valueObject.GetBlob(tmpValue);
786             if (tmpValue.empty()) {
787                 valueObject = ValueObject();
788             }
789         }
790         context->bindArgs.push_back(valueObject);
791     }
792     return OK;
793 }
794 
ExecuteSql(napi_env env,napi_callback_info info)795 napi_value RdbStoreProxy::ExecuteSql(napi_env env, napi_callback_info info)
796 {
797     LOG_DEBUG("RdbStoreProxy::ExecuteSql start.");
798     auto context = std::make_shared<RdbStoreContext>();
799     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
800         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1, 2 or 3");
801         RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2 || argc == 3, context->SetError(paramNumError));
802         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSql(env, argv[0], context));
803         if (argc > 1) {
804             RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseBindArgs(env, argv[1], context));
805         }
806         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
807         return OK;
808     };
809     auto exec = [context]() {
810         LOG_DEBUG("RdbStoreProxy::ExecuteSql Async.");
811         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
812         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
813         int errCode = obj->rdbStore_->ExecuteSql(context->sql, context->bindArgs);
814         LOG_DEBUG("RdbStoreProxy::ExecuteSql errCode is: %{public}d.", errCode);
815         return (errCode == E_OK) ? OK : ERR;
816     };
817     auto output = [context](napi_env env, napi_value &result) -> int {
818         napi_status status = napi_get_undefined(env, &result);
819         LOG_DEBUG("RdbStoreProxy::ExecuteSql end.");
820         return (status == napi_ok) ? OK : ERR;
821     };
822     context->SetAction(env, info, input, exec, output);
823 
824     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
825     return AsyncCall::Call(env, context);
826 }
827 
Count(napi_env env,napi_callback_info info)828 napi_value RdbStoreProxy::Count(napi_env env, napi_callback_info info)
829 {
830     LOG_DEBUG("RdbStoreProxy::Count start.");
831     auto context = std::make_shared<RdbStoreContext>();
832     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
833         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1 or 2");
834         RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError));
835         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[0], context));
836         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
837         return OK;
838     };
839     auto exec = [context]() {
840         LOG_DEBUG("RdbStoreProxy::Count Async.");
841         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
842         std::int64_t temp = 0;
843         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
844         CHECK_RETURN_ERR(context->predicatesProxy != nullptr &&
845             context->predicatesProxy->GetPredicates() != nullptr);
846         int errCode = obj->rdbStore_->Count(temp, *(context->predicatesProxy->GetPredicates()));
847         context->rowId = temp;
848         LOG_DEBUG("RdbStoreProxy::Count errCode is: %{public}d.", errCode);
849         return (errCode == E_OK) ? OK : ERR;
850     };
851     auto output = [context](napi_env env, napi_value &result) -> int {
852         napi_status status = napi_create_int64(env, context->rowId, &result);
853         LOG_DEBUG("RdbStoreProxy::Count end.");
854         return (status == napi_ok) ? OK : ERR;
855     };
856     context->SetAction(env, info, input, exec, output);
857 
858     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
859     return AsyncCall::Call(env, context);
860 }
861 
Replace(napi_env env,napi_callback_info info)862 napi_value RdbStoreProxy::Replace(napi_env env, napi_callback_info info)
863 {
864     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
865     LOG_DEBUG("RdbStoreProxy::Replace start.");
866     auto context = std::make_shared<RdbStoreContext>();
867     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
868         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
869         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
870         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[0], context));
871         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseValuesBucket(env, argv[1], context));
872         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
873         return OK;
874     };
875     auto exec = [context]() {
876         LOG_DEBUG("RdbStoreProxy::Replace Async.");
877         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
878         int64_t rowId = 0;
879         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
880         int errCode = obj->rdbStore_->Replace(rowId, context->tableName, context->valuesBucket);
881         context->rowId = rowId;
882         LOG_DEBUG("RdbStoreProxy::Replace errCode is:%{public}d.", errCode);
883         return (errCode == E_OK) ? OK : ERR;
884     };
885     auto output = [context](napi_env env, napi_value &result) -> int {
886         napi_status status = napi_create_int64(env, context->rowId, &result);
887         LOG_DEBUG("RdbStoreProxy::Replace end.");
888         return (status == napi_ok) ? OK : ERR;
889     };
890     context->SetAction(env, info, input, exec, output);
891 
892     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
893     return AsyncCall::Call(env, context);
894 }
895 
Attach(napi_env env,napi_callback_info info)896 napi_value RdbStoreProxy::Attach(napi_env env, napi_callback_info info)
897 {
898     LOG_DEBUG("RdbStoreProxy::Attach start.");
899     auto context = std::make_shared<RdbStoreContext>();
900     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
901         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("3 or 4");
902         RDB_CHECK_RETURN_CALL_RESULT(argc == 3 || argc == 4, context->SetError(paramNumError));
903         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseAlias(env, argv[0], context));
904         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePath(env, argv[1], context));
905         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
906         return OK;
907     };
908     auto exec = [context]() {
909         LOG_DEBUG("RdbStoreProxy::Attach Async.");
910         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
911         CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr);
912         int errCode = obj->rdbStore_->Attach(context->aliasName, context->pathName, context->newKey);
913         LOG_ERROR("RdbStoreProxy::Attach errCode is:%{public}d.", errCode);
914         return (errCode != E_OK) ? OK : ERR;
915     };
916     auto output = [context](napi_env env, napi_value &result) -> int {
917         napi_status status = napi_get_undefined(env, &result);
918         LOG_DEBUG("RdbStoreProxy::Attach end.");
919         return (status == napi_ok) ? OK : ERR;
920     };
921     context->SetAction(env, info, input, exec, output);
922 
923     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
924     return AsyncCall::Call(env, context);
925 }
926 
IsHoldingConnection(napi_env env,napi_callback_info info)927 napi_value RdbStoreProxy::IsHoldingConnection(napi_env env, napi_callback_info info)
928 {
929     napi_value thisObj = nullptr;
930     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
931     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
932     NAPI_ASSERT(env, rdbStoreProxy != nullptr &&
933         rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy or rdbStore_ is nullptr");
934     bool out = rdbStoreProxy->rdbStore_->IsHoldingConnection();
935     LOG_DEBUG("RdbStoreProxy::IsHoldingConnection out is : %{public}d.", out);
936     return JSUtils::Convert2JSValue(env, out);
937 }
938 
IsReadOnly(napi_env env,napi_callback_info info)939 napi_value RdbStoreProxy::IsReadOnly(napi_env env, napi_callback_info info)
940 {
941     napi_value thisObj = nullptr;
942     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
943     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
944     NAPI_ASSERT(env, rdbStoreProxy != nullptr
945         && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy or rdbStore_ is nullptr");
946     bool out = rdbStoreProxy->rdbStore_->IsReadOnly();
947     LOG_DEBUG("RdbStoreProxy::IsReadOnly out is : %{public}d.", out);
948     return JSUtils::Convert2JSValue(env, out);
949 }
950 
IsMemoryRdb(napi_env env,napi_callback_info info)951 napi_value RdbStoreProxy::IsMemoryRdb(napi_env env, napi_callback_info info)
952 {
953     napi_value thisObj = nullptr;
954     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
955     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
956     NAPI_ASSERT(env, rdbStoreProxy != nullptr
957         && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy or rdbStore_ is nullptr");
958     bool out = rdbStoreProxy->rdbStore_->IsMemoryRdb();
959     LOG_DEBUG("RdbStoreProxy::IsMemoryRdb out is : %{public}d.", out);
960     return JSUtils::Convert2JSValue(env, out);
961 }
962 
GetPath(napi_env env,napi_callback_info info)963 napi_value RdbStoreProxy::GetPath(napi_env env, napi_callback_info info)
964 {
965     napi_value thisObj = nullptr;
966     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
967     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
968     NAPI_ASSERT(env, rdbStoreProxy != nullptr
969         && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy or rdbStore_ is nullptr");
970     std::string path = rdbStoreProxy->rdbStore_->GetPath();
971     LOG_DEBUG("RdbStoreProxy::GetPath path is empty ? %{public}d.", path.empty());
972     return JSUtils::Convert2JSValue(env, path);
973 }
974 
BeginTransaction(napi_env env,napi_callback_info info)975 napi_value RdbStoreProxy::BeginTransaction(napi_env env, napi_callback_info info)
976 {
977     napi_value thisObj = nullptr;
978     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr));
979     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
980     NAPI_ASSERT(env, rdbStoreProxy != nullptr
981         && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy or rdbStore_ is nullptr");
982     int errCode = rdbStoreProxy->rdbStore_->BeginTransaction();
983     NAPI_ASSERT(env, errCode == E_OK, "call BeginTransaction failed");
984     LOG_DEBUG("RdbStoreProxy::BeginTransaction end, errCode is:%{public}d.", errCode);
985     return nullptr;
986 }
987 
RollBack(napi_env env,napi_callback_info info)988 napi_value RdbStoreProxy::RollBack(napi_env env, napi_callback_info info)
989 {
990     napi_value thisObj = nullptr;
991     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr));
992     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
993     NAPI_ASSERT(env, rdbStoreProxy != nullptr, "RdbStoreProxy is nullptr");
994     int errCode = rdbStoreProxy->rdbStore_->RollBack();
995     NAPI_ASSERT(env, errCode == E_OK, "call RollBack failed");
996     LOG_DEBUG("RdbStoreProxy::RollBack end, errCode is:%{public}d.", errCode);
997     return nullptr;
998 }
999 
Commit(napi_env env,napi_callback_info info)1000 napi_value RdbStoreProxy::Commit(napi_env env, napi_callback_info info)
1001 {
1002     napi_value thisObj = nullptr;
1003     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr));
1004     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
1005     NAPI_ASSERT(env, rdbStoreProxy != nullptr, "RdbStoreProxy is nullptr");
1006     int errCode = rdbStoreProxy->rdbStore_->Commit();
1007     NAPI_ASSERT(env, errCode == E_OK, "call Commit failed");
1008     LOG_DEBUG("RdbStoreProxy::Commit end, errCode is:%{public}d.", errCode);
1009     return nullptr;
1010 }
1011 
QueryByStep(napi_env env,napi_callback_info info)1012 napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info)
1013 {
1014     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1015     LOG_DEBUG("RdbStoreProxy::QueryByStep start.");
1016     auto context = std::make_shared<RdbStoreContext>();
1017     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
1018         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
1019         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
1020         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSql(env, argv[0], context));
1021         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseColumns(env, argv[1], context));
1022         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
1023         return OK;
1024     };
1025     auto exec = [context]() {
1026         LOG_DEBUG("RdbStoreProxy::QueryByStep Async.");
1027         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
1028         if (obj == nullptr || obj->rdbStore_ == nullptr) {
1029             return ERR;
1030         }
1031         context->stepResultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns);
1032         LOG_ERROR("RdbStoreProxy::QueryByStep is nullptr ? %{public}d.", context->stepResultSet == nullptr);
1033         return (context->stepResultSet != nullptr) ? OK : ERR;
1034     };
1035     auto output = [context](napi_env env, napi_value &result) -> int {
1036         if (context->stepResultSet != nullptr) {
1037             result = ResultSetProxy::NewInstance(env, context->stepResultSet, context->apiversion);
1038         }
1039         LOG_DEBUG("RdbStoreProxy::QueryByStep end.");
1040         return (result != nullptr) ? OK : ERR;
1041     };
1042     context->SetAction(env, info, input, exec, output);
1043 
1044     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
1045     return AsyncCall::Call(env, context);
1046 }
1047 
IsInTransaction(napi_env env,napi_callback_info info)1048 napi_value RdbStoreProxy::IsInTransaction(napi_env env, napi_callback_info info)
1049 {
1050     napi_value thisObj = nullptr;
1051     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
1052     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
1053     NAPI_ASSERT(env, rdbStoreProxy != nullptr, "RdbStoreProxy is nullptr");
1054     bool out = rdbStoreProxy->rdbStore_->IsInTransaction();
1055     LOG_DEBUG("RdbStoreProxy::IsInTransaction out is : %{public}d.", out);
1056     return JSUtils::Convert2JSValue(env, out);
1057 }
1058 
IsOpen(napi_env env,napi_callback_info info)1059 napi_value RdbStoreProxy::IsOpen(napi_env env, napi_callback_info info)
1060 {
1061     napi_value thisObj = nullptr;
1062     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
1063     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
1064     NAPI_ASSERT(env, (rdbStoreProxy != nullptr) && (rdbStoreProxy->rdbStore_ != nullptr), "RdbStoreProxy is nullptr");
1065     bool out = rdbStoreProxy->rdbStore_->IsOpen();
1066     LOG_DEBUG("RdbStoreProxy::IsOpen out is : %{public}d.", out);
1067     return JSUtils::Convert2JSValue(env, out);
1068 }
1069 
GetVersion(napi_env env,napi_callback_info info)1070 napi_value RdbStoreProxy::GetVersion(napi_env env, napi_callback_info info)
1071 {
1072     napi_value thisObj = nullptr;
1073     napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr);
1074     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj);
1075     NAPI_ASSERT(env, (rdbStoreProxy != nullptr) && (rdbStoreProxy->rdbStore_ != nullptr), "RdbStoreProxy is nullptr");
1076     int32_t version = 0;
1077     int out = rdbStoreProxy->rdbStore_->GetVersion(version);
1078     LOG_DEBUG("RdbStoreProxy::GetVersion out is : %{public}d.", out);
1079     return JSUtils::Convert2JSValue(env, version);
1080 }
1081 
SetVersion(napi_env env,napi_callback_info info)1082 napi_value RdbStoreProxy::SetVersion(napi_env env, napi_callback_info info)
1083 {
1084     napi_value thiz = nullptr;
1085     size_t argc = 1;
1086     napi_value args[1] = { 0 };
1087     napi_get_cb_info(env, info, &argc, args, &thiz, nullptr);
1088     NAPI_ASSERT(env, argc == 1, "RdbStoreProxy::SetVersion Invalid argvs!");
1089     RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thiz);
1090     NAPI_ASSERT(env, (rdbStoreProxy != nullptr) && (rdbStoreProxy->rdbStore_ != nullptr), "RdbStoreProxy is nullptr");
1091     int32_t version = 0;
1092     napi_get_value_int32(env, args[0], &version);
1093     int out = rdbStoreProxy->rdbStore_->SetVersion(version);
1094     LOG_DEBUG("RdbStoreProxy::SetVersion out is : %{public}d.", out);
1095     return nullptr;
1096 }
1097 
1098 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
SetDistributedTables(napi_env env,napi_callback_info info)1099 napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info)
1100 {
1101     LOG_DEBUG("RdbStoreProxy::SetDistributedTables start.");
1102     auto context = std::make_shared<RdbStoreContext>();
1103     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
1104         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("1 or 2");
1105         RDB_CHECK_RETURN_CALL_RESULT(argc == 1 || argc == 2, context->SetError(paramNumError));
1106         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTablesName(env, argv[0], context));
1107         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
1108         return OK;
1109     };
1110     auto exec = [context]() {
1111         LOG_DEBUG("RdbStoreProxy::SetDistributedTables Async.");
1112         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
1113         if (obj == nullptr || obj->rdbStore_.get() == nullptr) {
1114             return ERR;
1115         }
1116         int res = obj->rdbStore_->SetDistributedTables(context->tablesName);
1117         LOG_DEBUG("RdbStoreProxy::SetDistributedTables res is : %{public}d.", res);
1118         return (res == E_OK || res == E_NOT_SUPPORT) ? OK : ERR;
1119     };
1120     auto output = [context](napi_env env, napi_value &result) -> int {
1121         napi_status status = napi_get_undefined(env, &result);
1122         LOG_DEBUG("RdbStoreProxy::SetDistributedTables end.");
1123         return (status == napi_ok) ? OK : ERR;
1124     };
1125     context->SetAction(env, info, input, exec, output);
1126 
1127     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
1128     return AsyncCall::Call(env, context);
1129 }
1130 
ObtainDistributedTableName(napi_env env,napi_callback_info info)1131 napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback_info info)
1132 {
1133     LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName start.");
1134     auto context = std::make_shared<RdbStoreContext>();
1135     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
1136         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
1137         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
1138         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseDevice(env, argv[0], context));
1139         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseTableName(env, argv[1], context));
1140         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
1141         return OK;
1142     };
1143     auto exec = [context]() {
1144         LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async.");
1145         RdbStoreProxy *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
1146         int errCode = E_ERROR;
1147         if (obj == nullptr || obj->rdbStore_.get() == nullptr) {
1148             return ERR;
1149         }
1150         auto name = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName, errCode);
1151         LOG_INFO("RdbStoreProxy::ObtainDistributedTableName name is empty ? : %{public}d, errCode is %{public}d",
1152             name.empty(), errCode);
1153         context->tableName = name;
1154         return name.empty() ? ERR : OK;
1155     };
1156     auto output = [context](napi_env env, napi_value &result) -> int {
1157         napi_status status =
1158             napi_create_string_utf8(env, context->tableName.c_str(), context->tableName.length(), &result);
1159         LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName end.");
1160         return (status == napi_ok) ? OK : ERR;
1161     };
1162     context->SetAction(env, info, input, exec, output);
1163 
1164     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
1165     return AsyncCall::Call(env, context);
1166 }
1167 
Sync(napi_env env,napi_callback_info info)1168 napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info)
1169 {
1170     LOG_DEBUG("RdbStoreProxy::Sync start.");
1171     auto context = std::make_shared<RdbStoreContext>();
1172     auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> int {
1173         std::shared_ptr<Error> paramNumError = std::make_shared<ParamNumError>("2 or 3");
1174         RDB_CHECK_RETURN_CALL_RESULT(argc == 2 || argc == 3, context->SetError(paramNumError));
1175         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParseSyncModeArg(env, argv[0], context));
1176         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParsePredicates(env, argv[1], context));
1177         RDB_ASYNC_PARAM_CHECK_FUNCTION(ParserThis(env, self, context));
1178         return OK;
1179     };
1180     auto exec = [context]() {
1181         LOG_DEBUG("RdbStoreProxy::Sync Async.");
1182         auto *obj = reinterpret_cast<RdbStoreProxy *>(context->boundObj);
1183         SyncOption option;
1184         option.mode = static_cast<DistributedRdb::SyncMode>(context->enumArg);
1185         option.isBlock = true;
1186         if (obj == nullptr || obj->rdbStore_.get() == nullptr) {
1187             return ERR;
1188         }
1189         int res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(),
1190             [context](const SyncResult &result) { context->syncResult = result; });
1191         LOG_INFO("RdbStoreProxy::Sync res is : %{public}d.", res);
1192         return res == E_OK ? OK : ERR;
1193     };
1194     auto output = [context](napi_env env, napi_value &result) -> int {
1195         result = JSUtils::Convert2JSValue(env, context->syncResult);
1196         LOG_DEBUG("RdbStoreProxy::Sync end.");
1197         return (result != nullptr) ? OK : ERR;
1198     };
1199     context->SetAction(env, info, input, exec, output);
1200 
1201     RDB_CHECK_RETURN_NULLPTR(context->error == nullptr || context->error->GetCode() == OK, "");
1202     return AsyncCall::Call(env, context);
1203 }
1204 
OnDataChangeEvent(napi_env env,size_t argc,napi_value * argv)1205 void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *argv)
1206 {
1207     napi_valuetype type = napi_undefined;
1208     napi_typeof(env, argv[0], &type);
1209     if (type != napi_number) {
1210         LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: first argument is not number.");
1211         return;
1212     }
1213     int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX;
1214     napi_get_value_int32(env, argv[0], &mode);
1215     if (mode < 0 || mode >= SubscribeMode::SUBSCRIBE_MODE_MAX) {
1216         LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: first argument value is invalid.");
1217         return;
1218     }
1219     LOG_INFO("RdbStoreProxy::OnDataChangeEvent: mode=%{public}d.", mode);
1220 
1221     napi_typeof(env, argv[1], &type);
1222     if (type != napi_function) {
1223         LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: second argument is not function.");
1224         return;
1225     }
1226 
1227     std::lock_guard<std::mutex> lockGuard(mutex_);
1228     for (const auto &observer : observers_[mode]) {
1229         if (observer != nullptr && *observer == argv[1]) {
1230             LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: duplicate subscribe.");
1231             return;
1232         }
1233     }
1234     SubscribeOption option;
1235     option.mode = static_cast<SubscribeMode>(mode);
1236     auto observer = std::make_shared<NapiRdbStoreObserver>(env, argv[1]);
1237     int errCode = rdbStore_->Subscribe(option, observer.get());
1238     if (errCode != E_OK) {
1239         LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe failed.");
1240         return;
1241     }
1242     observers_[mode].push_back(observer);
1243     LOG_INFO("RdbStoreProxy::OnDataChangeEvent: subscribe success, mode is: %{public}d.", mode);
1244 }
1245 
OffDataChangeEvent(napi_env env,size_t argc,napi_value * argv)1246 void RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *argv)
1247 {
1248     napi_valuetype type = napi_undefined;
1249     napi_typeof(env, argv[0], &type);
1250     if (type != napi_number) {
1251         LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: first argument is not number.");
1252         return;
1253     }
1254     int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX;
1255     napi_get_value_int32(env, argv[0], &mode);
1256     if (mode < 0 || mode >= SubscribeMode::SUBSCRIBE_MODE_MAX) {
1257         LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: first argument value is invalid.");
1258         return;
1259     }
1260     LOG_INFO("RdbStoreProxy::OffDataChangeEvent: mode=%{public}d.", mode);
1261 
1262     napi_typeof(env, argv[1], &type);
1263     if (type != napi_function) {
1264         LOG_ERROR("RdbStoreProxy::OffDataChangeEvent: second argument is not function.");
1265         return;
1266     }
1267 
1268     SubscribeOption option;
1269     option.mode = static_cast<SubscribeMode>(mode);
1270     std::lock_guard<std::mutex> lockGuard(mutex_);
1271     for (auto it = observers_[mode].begin(); it != observers_[mode].end(); it++) {
1272         if (*it != nullptr && **it == argv[1]) {
1273             if (rdbStore_.get() == nullptr) {
1274                 LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: rdbStore_ invalid.");
1275                 return;
1276             }
1277             rdbStore_->UnSubscribe(option, it->get());
1278             observers_[mode].erase(it);
1279             LOG_INFO("RdbStoreProxy::OffDataChangeEvent: unsubscribe success.");
1280             return;
1281         }
1282     }
1283     LOG_INFO("RdbStoreProxy::OffDataChangeEvent: not found.");
1284 }
1285 
OnEvent(napi_env env,napi_callback_info info)1286 napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info)
1287 {
1288     size_t argc = MAX_ON_EVENT_ARG_NUM;
1289     napi_value argv[MAX_ON_EVENT_ARG_NUM]{};
1290     napi_value self = nullptr;
1291     if (napi_get_cb_info(env, info, &argc, argv, &self, nullptr) != napi_ok) {
1292         LOG_ERROR("RdbStoreProxy::OnEvent: get args failed.");
1293         return nullptr;
1294     }
1295     bool invalid_condition = argc < MIN_ON_EVENT_ARG_NUM || argc > MAX_ON_EVENT_ARG_NUM || self == nullptr;
1296     NAPI_ASSERT(env, !invalid_condition, "RdbStoreProxy::OnEvent: invalid args");
1297 
1298     auto proxy = RdbStoreProxy::GetNativeInstance(env, self);
1299     NAPI_ASSERT(env, proxy != nullptr, "RdbStoreProxy::OnEvent: invalid args");
1300 
1301     std::string event = JSUtils::Convert2String(env, argv[0]);
1302     if (event == "dataChange") {
1303         proxy->OnDataChangeEvent(env, argc - 1, argv + 1);
1304     }
1305 
1306     LOG_INFO("RdbStoreProxy::OnEvent end.");
1307     return nullptr;
1308 }
1309 
OffEvent(napi_env env,napi_callback_info info)1310 napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info)
1311 {
1312     size_t argc = MAX_ON_EVENT_ARG_NUM;
1313     napi_value argv[MAX_ON_EVENT_ARG_NUM]{};
1314     napi_value self = nullptr;
1315     if (napi_get_cb_info(env, info, &argc, argv, &self, nullptr) != napi_ok) {
1316         LOG_ERROR("RdbStoreProxy::OffEvent: get args failed.");
1317         return nullptr;
1318     }
1319     bool invalid_condition = argc < MIN_ON_EVENT_ARG_NUM || argc > MAX_ON_EVENT_ARG_NUM || self == nullptr;
1320     NAPI_ASSERT(env, !invalid_condition, "RdbStoreProxy::OffEvent: invalid args");
1321 
1322     auto proxy = RdbStoreProxy::GetNativeInstance(env, self);
1323     NAPI_ASSERT(env, proxy != nullptr, "RdbStoreProxy::OffEvent: invalid args");
1324 
1325     std::string event = JSUtils::Convert2String(env, argv[0]);
1326     if (event == "dataChange") {
1327         proxy->OffDataChangeEvent(env, argc - 1, argv + 1);
1328     }
1329 
1330     LOG_INFO("RdbStoreProxy::OffEvent end.");
1331     return nullptr;
1332 }
1333 #endif
1334 } // namespace RdbJsKit
1335 } // namespace OHOS
1336