1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #define LOG_TAG "NapiRdbJsUtils"
16 #include "napi_rdb_js_utils.h"
17 
18 #include <memory>
19 #include <tuple>
20 
21 #include "js_ability.h"
22 #include "js_native_api_types.h"
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_sql_statistic.h"
26 #include "rdb_sql_utils.h"
27 #include "rdb_types.h"
28 #include "result_set.h"
29 #include "transaction.h"
30 
31 #define NAPI_CALL_RETURN_ERR(theCall, retVal) \
32     do {                                      \
33         if ((theCall) != napi_ok) {           \
34             return retVal;                    \
35         }                                     \
36     } while (0)
37 
38 #ifndef PATH_SPLIT
39 #define PATH_SPLIT '/'
40 #endif
41 namespace OHOS::AppDataMgrJsKit {
42 namespace JSUtils {
43 using namespace OHOS::Rdb;
44 using namespace NativeRdb;
45 using RelationalStoreJsKit::ParamError;
46 using namespace RelationalStoreJsKit;
47 template<>
Convert2Value(napi_env env,napi_value jsValue,Asset & output)48 int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output)
49 {
50     napi_valuetype type = napi_undefined;
51     napi_status status = napi_typeof(env, jsValue, &type);
52     bool isArray;
53     napi_status status_array = napi_is_array(env, jsValue, &isArray);
54     if (status != napi_ok || type != napi_object || status_array != napi_ok || isArray) {
55         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
56         return napi_invalid_arg;
57     }
58 
59     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "name", output.name), napi_invalid_arg);
60     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "uri", output.uri), napi_invalid_arg);
61     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "createTime", output.createTime), napi_invalid_arg);
62     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "modifyTime", output.modifyTime), napi_invalid_arg);
63     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "size", output.size), napi_invalid_arg);
64     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "path", output.path), napi_invalid_arg);
65     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, jsValue, "status", output.status, true), napi_invalid_arg);
66     if (output.status != AssetValue::STATUS_DELETE) {
67         output.status = AssetValue::STATUS_UNKNOWN;
68     }
69     output.hash = output.modifyTime + "_" + output.size;
70     return napi_ok;
71 }
72 
73 template<>
Convert2Value(napi_env env,napi_value input,DistributedRdb::Reference & output)74 int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Reference &output)
75 {
76     napi_valuetype type = napi_undefined;
77     napi_status status = napi_typeof(env, input, &type);
78     if (status != napi_ok || type != napi_object) {
79         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
80         return napi_invalid_arg;
81     }
82 
83     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "sourceTable", output.sourceTable), napi_invalid_arg);
84     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "targetTable", output.targetTable), napi_invalid_arg);
85     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "refFields", output.refFields), napi_invalid_arg);
86     return napi_ok;
87 }
88 
89 template<>
Convert2Value(napi_env env,napi_value input,DistributedRdb::DistributedConfig & output)90 int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::DistributedConfig &output)
91 {
92     napi_valuetype type = napi_undefined;
93     napi_status status = napi_typeof(env, input, &type);
94     if (status != napi_ok || type != napi_object) {
95         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
96         return napi_invalid_arg;
97     }
98 
99     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "autoSync", output.autoSync), napi_invalid_arg);
100     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "references", output.references, true), napi_invalid_arg);
101     return napi_ok;
102 }
103 
104 template<>
Convert2Value(napi_env env,napi_value jsValue,ValueObject & valueObject)105 int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject)
106 {
107     auto status = Convert2Value(env, jsValue, valueObject.value);
108     if (status != napi_ok) {
109         return napi_invalid_arg;
110     }
111     return napi_ok;
112 }
113 
114 template<>
Convert2JSValue(napi_env env,const Asset & value)115 napi_value Convert2JSValue(napi_env env, const Asset &value)
116 {
117     auto outputStatus = value.status & ~0xF0000000;
118     std::vector<napi_property_descriptor> descriptors = {
119         DECLARE_JS_PROPERTY(env, "name", value.name),
120         DECLARE_JS_PROPERTY(env, "uri", value.uri),
121         DECLARE_JS_PROPERTY(env, "createTime", value.createTime),
122         DECLARE_JS_PROPERTY(env, "modifyTime", value.modifyTime),
123         DECLARE_JS_PROPERTY(env, "size", value.size),
124         DECLARE_JS_PROPERTY(env, "path", value.path),
125         DECLARE_JS_PROPERTY(env, "status", outputStatus),
126     };
127 
128     napi_value object = nullptr;
129     NAPI_CALL_RETURN_ERR(
130         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
131     return object;
132 }
133 
134 template<>
Convert2JSValue(napi_env env,const RowEntity & rowEntity)135 napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity)
136 {
137     napi_value object = nullptr;
138     NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object);
139     auto &values = rowEntity.Get();
140     for (auto const &[key, value] : values) {
141         NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, key.c_str(), value), object);
142     }
143     return object;
144 }
145 
146 template<>
Convert2JSValue(napi_env env,const ValueObject & value)147 napi_value Convert2JSValue(napi_env env, const ValueObject &value)
148 {
149     return Convert2JSValue(env, value.value);
150 }
151 
152 template<>
Convert2JSValue(napi_env env,const DistributedRdb::Statistic & value)153 napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value)
154 {
155     std::vector<napi_property_descriptor> descriptors = {
156         DECLARE_JS_PROPERTY(env, "total", value.total),
157         DECLARE_JS_PROPERTY(env, "success", value.success),
158         DECLARE_JS_PROPERTY(env, "successful", value.success),
159         DECLARE_JS_PROPERTY(env, "failed", value.failed),
160         DECLARE_JS_PROPERTY(env, "remained", value.untreated),
161     };
162 
163     napi_value object = nullptr;
164     NAPI_CALL_RETURN_ERR(
165         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
166     return object;
167 }
168 
169 template<>
Convert2JSValue(napi_env env,const DistributedRdb::TableDetail & value)170 napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value)
171 {
172     std::vector<napi_property_descriptor> descriptors = {
173         DECLARE_JS_PROPERTY(env, "upload", value.upload),
174         DECLARE_JS_PROPERTY(env, "download", value.download),
175     };
176 
177     napi_value object = nullptr;
178     NAPI_CALL_RETURN_ERR(
179         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
180     return object;
181 }
182 
183 template<>
Convert2JSValue(napi_env env,const DistributedRdb::ProgressDetail & value)184 napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value)
185 {
186     std::vector<napi_property_descriptor> descriptors = {
187         DECLARE_JS_PROPERTY(env, "schedule", value.progress),
188         DECLARE_JS_PROPERTY(env, "code", value.code),
189         DECLARE_JS_PROPERTY(env, "details", value.details),
190     };
191 
192     napi_value object = nullptr;
193     NAPI_CALL_RETURN_ERR(
194         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
195     return object;
196 }
197 
198 template<>
Convert2JSValue(napi_env env,const DistributedRdb::SqlObserver::SqlExecutionInfo & value)199 napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlExecutionInfo &value)
200 {
201     std::vector<napi_property_descriptor> descriptors = {
202         DECLARE_JS_PROPERTY(env, "sql", value.sql_),
203         DECLARE_JS_PROPERTY(env, "totalTime", value.totalTime_),
204         DECLARE_JS_PROPERTY(env, "waitTime", value.waitTime_),
205         DECLARE_JS_PROPERTY(env, "prepareTime", value.prepareTime_),
206         DECLARE_JS_PROPERTY(env, "executeTime", value.executeTime_),
207     };
208 
209     napi_value object = nullptr;
210     NAPI_CALL_RETURN_ERR(
211         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
212     return object;
213 }
214 
215 template<>
Convert2JSValue(napi_env env,const DistributedRdb::Details & details)216 napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details)
217 {
218     return nullptr;
219 }
220 
221 template<>
Convert2JSValue(napi_env env,const JSChangeInfo & value)222 napi_value Convert2JSValue(napi_env env, const JSChangeInfo &value)
223 {
224     std::vector<napi_property_descriptor> descriptors = {
225         DECLARE_JS_PROPERTY(env, "table", value.table),
226         DECLARE_JS_PROPERTY(env, "type", value.type),
227         DECLARE_JS_PROPERTY(env, "inserted", value.inserted),
228         DECLARE_JS_PROPERTY(env, "updated", value.updated),
229         DECLARE_JS_PROPERTY(env, "deleted", value.deleted),
230     };
231 
232     napi_value object = nullptr;
233     NAPI_CALL_RETURN_ERR(
234         napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object);
235     return object;
236 }
237 
238 template<>
Convert2JSValue(napi_env env,const Date & date)239 napi_value Convert2JSValue(napi_env env, const Date &date)
240 {
241     napi_value jsDeta = nullptr;
242     NAPI_CALL_RETURN_ERR(napi_create_date(env, date, &jsDeta), jsDeta);
243     return jsDeta;
244 }
245 template<>
Convert2JSValue(napi_env env,const BigInt & value)246 napi_value Convert2JSValue(napi_env env, const BigInt &value)
247 {
248     napi_value val = nullptr;
249     napi_status status = napi_create_bigint_words(env, value.Sign(), value.Size(), value.TrueForm(), &val);
250     if (status != napi_ok) {
251         return nullptr;
252     }
253     return val;
254 }
255 
256 template<>
Convert2Value(napi_env env,napi_value jsValue,BigInt & value)257 int32_t Convert2Value(napi_env env, napi_value jsValue, BigInt &value)
258 {
259     napi_valuetype type = napi_undefined;
260     napi_status status = napi_typeof(env, jsValue, &type);
261     if (status != napi_ok || type != napi_bigint) {
262         return napi_invalid_arg;
263     }
264     int sign = 0;
265     size_t count = 0;
266     status = napi_get_value_bigint_words(env, jsValue, nullptr, &count, nullptr);
267     if (status != napi_ok) {
268         return napi_bigint_expected;
269     }
270     std::vector<uint64_t> words(count, 0);
271     status = napi_get_value_bigint_words(env, jsValue, &sign, &count, words.data());
272     if (status != napi_ok) {
273         return napi_bigint_expected;
274     }
275     value = BigInteger(sign, std::move(words));
276     return napi_ok;
277 }
278 
279 template<>
ToString(const PRIKey & key)280 std::string ToString(const PRIKey &key)
281 {
282     auto strVal = std::get_if<std::string>(&key);
283     if (strVal != nullptr) {
284         return *strVal;
285     }
286     auto intVal = std::get_if<int64_t>(&key);
287     if (intVal != nullptr) {
288         return std::to_string(*intVal);
289     }
290     auto dbVal = std::get_if<double>(&key);
291     if (dbVal != nullptr) {
292         return std::to_string(static_cast<int64_t>(*dbVal));
293     }
294     return {};
295 }
296 
IsNapiString(napi_env env,napi_value value)297 bool IsNapiString(napi_env env, napi_value value)
298 {
299     napi_valuetype type = napi_undefined;
300     NAPI_CALL_BASE(env, napi_typeof(env, value, &type), false);
301     return type == napi_string;
302 }
303 
GetLevel(SecurityLevel level,SecurityLevel & out)304 int32_t GetLevel(SecurityLevel level, SecurityLevel &out)
305 {
306     switch (level) {
307         case SecurityLevel::S1:
308         case SecurityLevel::S2:
309         case SecurityLevel::S3:
310         case SecurityLevel::S4:
311             out = level;
312             return napi_ok;
313         default:
314             return napi_invalid_arg;
315     }
316 }
317 
318 template<>
Convert2Value(napi_env env,napi_value input,CryptoParam & cryptoParam)319 int32_t Convert2Value(napi_env env, napi_value input, CryptoParam &cryptoParam)
320 {
321     napi_valuetype type = napi_undefined;
322     napi_status status = napi_typeof(env, input, &type);
323     if (status != napi_ok || type != napi_object) {
324         LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type);
325         return napi_invalid_arg;
326     }
327 
328     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "encryptionKey", cryptoParam.encryptKey_), napi_invalid_arg);
329     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "iterationCount", cryptoParam.iterNum, true), napi_invalid_arg);
330     NAPI_CALL_RETURN_ERR(
331         GetNamedProperty(env, input, "encryptionAlgo", cryptoParam.encryptAlgo, true), napi_invalid_arg);
332     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "hmacAlgo", cryptoParam.hmacAlgo, true), napi_invalid_arg);
333     NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "kdfAlgo", cryptoParam.kdfAlgo, true), napi_invalid_arg);
334     NAPI_CALL_RETURN_ERR(
335         GetNamedProperty(env, input, "cryptoPageSize", cryptoParam.cryptoPageSize, true), napi_invalid_arg);
336 
337     return napi_ok;
338 }
339 
340 template<>
Convert2Value(napi_env env,napi_value jsValue,RdbConfig & rdbConfig)341 int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig)
342 {
343     int32_t status = GetNamedProperty(env, jsValue, "encrypt", rdbConfig.isEncrypt, true);
344     ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg);
345 
346     int32_t securityLevel;
347     status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel);
348     ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg);
349     status = GetLevel(static_cast<SecurityLevel>(securityLevel), rdbConfig.securityLevel);
350     ASSERT(status == napi_ok, "get securityLevel failed", status);
351 
352     status = GetNamedProperty(env, jsValue, "dataGroupId", rdbConfig.dataGroupId, true);
353     ASSERT(OK == status, "get dataGroupId failed.", napi_invalid_arg);
354 
355     status = GetNamedProperty(env, jsValue, "autoCleanDirtyData", rdbConfig.isAutoClean, true);
356     ASSERT(OK == status, "get autoCleanDirtyData failed.", napi_invalid_arg);
357 
358     status = GetNamedProperty(env, jsValue, "name", rdbConfig.name);
359     ASSERT(OK == status, "get name failed.", napi_invalid_arg);
360 
361     status = GetNamedProperty(env, jsValue, "customDir", rdbConfig.customDir, true);
362     ASSERT(OK == status, "get customDir failed.", napi_invalid_arg);
363 
364     GetNamedProperty(env, jsValue, "isSearchable", rdbConfig.isSearchable, true);
365     ASSERT(OK == status, "get isSearchable failed.", napi_invalid_arg);
366 
367     GetNamedProperty(env, jsValue, "vector", rdbConfig.vector, true);
368     ASSERT(OK == status, "get vector failed.", napi_invalid_arg);
369 
370     GetNamedProperty(env, jsValue, "allowRebuild", rdbConfig.allowRebuild, true);
371     ASSERT(OK == status, "get allowRebuild failed.", napi_invalid_arg);
372 
373     GetNamedProperty(env, jsValue, "isReadOnly", rdbConfig.isReadOnly, true);
374     ASSERT(OK == status, "get isReadOnly failed.", napi_invalid_arg);
375 
376     GetNamedProperty(env, jsValue, "pluginLibs", rdbConfig.pluginLibs, true);
377     ASSERT(OK == status, "get pluginLibs failed.", napi_invalid_arg);
378 
379     status = GetNamedProperty(env, jsValue, "haMode", rdbConfig.haMode, true);
380     ASSERT(OK == status, "get haMode failed.", napi_invalid_arg);
381 
382     status = GetNamedProperty(env, jsValue, "cryptoParam", rdbConfig.cryptoParam, true);
383     ASSERT(OK == status, "get cryptoParam failed.", napi_invalid_arg);
384     return napi_ok;
385 }
386 
387 template<>
Convert2Value(napi_env env,napi_value jsValue,TransactionOptions & transactionOptions)388 int32_t Convert2Value(napi_env env, napi_value jsValue, TransactionOptions &transactionOptions)
389 {
390     int32_t status = GetNamedProperty(env, jsValue, "transactionType", transactionOptions.transactionType, true);
391     bool checked = transactionOptions.transactionType >= Transaction::DEFERRED &&
392                    transactionOptions.transactionType <= Transaction::EXCLUSIVE;
393     ASSERT(OK == status && checked, "get transactionType failed.", napi_invalid_arg);
394     return napi_ok;
395 }
396 
GetCurrentAbilityParam(napi_env env,napi_value jsValue,ContextParam & param)397 int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam &param)
398 {
399     std::shared_ptr<Context> context = JSAbility::GetCurrentAbility(env, jsValue);
400     if (context == nullptr) {
401         return napi_invalid_arg;
402     }
403     param.baseDir = context->GetDatabaseDir();
404     param.moduleName = context->GetModuleName();
405     param.area = context->GetArea();
406     param.bundleName = context->GetBundleName();
407     param.isSystemApp = context->IsSystemAppCalled();
408     return napi_ok;
409 }
410 
411 template<>
Convert2Value(napi_env env,napi_value jsValue,ContextParam & param)412 int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &param)
413 {
414     if (jsValue == nullptr) {
415         LOG_INFO("hasProp is false -> fa stage");
416         param.isStageMode = false;
417         return GetCurrentAbilityParam(env, jsValue, param);
418     }
419 
420     int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode);
421     ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg);
422     if (!param.isStageMode) {
423         LOG_WARN("isStageMode is false -> fa stage");
424         return GetCurrentAbilityParam(env, jsValue, param);
425     }
426     LOG_DEBUG("stage mode branch");
427     status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir);
428     ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg);
429     status = GetNamedProperty(env, jsValue, "area", param.area, true);
430     ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg);
431 
432     napi_value hapInfo = nullptr;
433     GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo);
434     if (hapInfo != nullptr) {
435         status = GetNamedProperty(env, hapInfo, "name", param.moduleName);
436         ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg);
437     }
438 
439     napi_value appInfo = nullptr;
440     GetNamedProperty(env, jsValue, "applicationInfo", appInfo);
441     if (appInfo != nullptr) {
442         status = GetNamedProperty(env, appInfo, "name", param.bundleName);
443         ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg);
444         status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp, true);
445         ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg);
446         int32_t hapVersion = JSAbility::GetHapVersion(env, jsValue);
447         JSUtils::SetHapVersion(hapVersion);
448     }
449     return napi_ok;
450 }
451 
GetRealPath(napi_env env,napi_value jsValue,RdbConfig & rdbConfig,ContextParam & param)452 std::tuple<int32_t, std::shared_ptr<Error>> GetRealPath(
453     napi_env env, napi_value jsValue, RdbConfig &rdbConfig, ContextParam &param)
454 {
455     CHECK_RETURN_CORE(rdbConfig.name.find(PATH_SPLIT) == std::string::npos, RDB_DO_NOTHING,
456         std::make_tuple(ERR, std::make_shared<ParamError>("StoreConfig.name", "a file name without path.")));
457 
458     if (!rdbConfig.customDir.empty()) {
459         // determine if the first character of customDir is '/'
460         CHECK_RETURN_CORE(rdbConfig.customDir.find_first_of(PATH_SPLIT) != 0, RDB_DO_NOTHING,
461             std::make_tuple(ERR, std::make_shared<ParamError>("customDir", "a relative directory.")));
462         // customDir length is limited to 128 bytes
463         CHECK_RETURN_CORE(rdbConfig.customDir.length() <= 128, RDB_DO_NOTHING,
464             std::make_tuple(ERR, std::make_shared<ParamError>("customDir length", "less than or equal to 128 "
465                                                                                   "bytes.")));
466     }
467 
468     std::string baseDir = param.baseDir;
469     if (!rdbConfig.dataGroupId.empty()) {
470         if (!param.isStageMode) {
471             return std::make_tuple(ERR, std::make_shared<InnerError>(E_NOT_STAGE_MODE));
472         }
473         auto stageContext = JSAbility::GetStageModeContext(env, jsValue);
474         if (stageContext == nullptr) {
475             return std::make_tuple(ERR, std::make_shared<ParamError>("Illegal context."));
476         }
477         std::string groupDir;
478         int errCode = stageContext->GetSystemDatabaseDir(rdbConfig.dataGroupId, groupDir);
479         CHECK_RETURN_CORE(errCode == E_OK || !groupDir.empty(), RDB_DO_NOTHING,
480             std::make_tuple(ERR, std::make_shared<InnerError>(E_DATA_GROUP_ID_INVALID)));
481         baseDir = groupDir;
482     }
483 
484     auto [realPath, errorCode] = RdbSqlUtils::GetDefaultDatabasePath(baseDir, rdbConfig.name, rdbConfig.customDir);
485     // realPath length is limited to 1024 bytes
486     CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= 1024, RDB_DO_NOTHING,
487         std::make_tuple(ERR, std::make_shared<ParamError>("database path", "a valid path.")));
488     rdbConfig.path = realPath;
489     return std::make_tuple(E_OK, nullptr);
490 }
491 
GetRdbStoreConfig(const RdbConfig & rdbConfig,const ContextParam & param)492 RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam &param)
493 {
494     RdbStoreConfig rdbStoreConfig(rdbConfig.path);
495     rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt);
496     rdbStoreConfig.SetSearchable(rdbConfig.isSearchable);
497     rdbStoreConfig.SetIsVector(rdbConfig.vector);
498     rdbConfig.vector ? rdbStoreConfig.SetDBType(DB_VECTOR) : rdbStoreConfig.SetDBType(DB_SQLITE);
499     rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean);
500     rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel);
501     rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId);
502     rdbStoreConfig.SetName(rdbConfig.name);
503     rdbStoreConfig.SetCustomDir(rdbConfig.customDir);
504     rdbStoreConfig.SetAllowRebuild(rdbConfig.allowRebuild);
505     rdbStoreConfig.SetReadOnly(rdbConfig.isReadOnly);
506     rdbStoreConfig.SetIntegrityCheck(IntegrityCheck::NONE);
507 
508     if (!param.bundleName.empty()) {
509         rdbStoreConfig.SetBundleName(param.bundleName);
510     }
511     rdbStoreConfig.SetModuleName(param.moduleName);
512     rdbStoreConfig.SetArea(param.area);
513     rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs);
514     rdbStoreConfig.SetHaMode(rdbConfig.haMode);
515 
516     rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam);
517     return rdbStoreConfig;
518 }
519 
HasDuplicateAssets(const ValueObject & value)520 bool HasDuplicateAssets(const ValueObject &value)
521 {
522     auto *assets = std::get_if<ValueObject::Assets>(&value.value);
523     if (assets == nullptr) {
524         return false;
525     }
526     std::set<std::string> names;
527     auto item = assets->begin();
528     while (item != assets->end()) {
529         if (!names.insert(item->name).second) {
530             LOG_ERROR("duplicate assets! name = %{public}.6s", item->name.c_str());
531             return true;
532         }
533         item++;
534     }
535     return false;
536 }
537 
HasDuplicateAssets(const std::vector<ValueObject> & values)538 bool HasDuplicateAssets(const std::vector<ValueObject> &values)
539 {
540     for (auto &val : values) {
541         if (HasDuplicateAssets(val)) {
542             return true;
543         }
544     }
545     return false;
546 }
547 
HasDuplicateAssets(const ValuesBucket & value)548 bool HasDuplicateAssets(const ValuesBucket &value)
549 {
550     for (auto &[key, val] : value.values_) {
551         if (HasDuplicateAssets(val)) {
552             return true;
553         }
554     }
555     return false;
556 }
557 
HasDuplicateAssets(const std::vector<ValuesBucket> & values)558 bool HasDuplicateAssets(const std::vector<ValuesBucket> &values)
559 {
560     for (auto &valueBucket : values) {
561         if (HasDuplicateAssets(valueBucket)) {
562             return true;
563         }
564     }
565     return false;
566 }
567 
HasDuplicateAssets(const ValuesBuckets & values)568 bool HasDuplicateAssets(const ValuesBuckets &values)
569 {
570     const auto &[fields, vals] = values.GetFieldsAndValues();
571     for (const auto &valueObject : *vals) {
572         if (HasDuplicateAssets(valueObject)) {
573             return true;
574         }
575     }
576     return false;
577 }
578 }; // namespace JSUtils
579 } // namespace OHOS::AppDataMgrJsKit