• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 
16 #include "napi_rdb_context.h"
17 
18 using namespace OHOS::RelationalStoreJsKit;
19 
20 namespace OHOS {
21 namespace RelationalStoreJsKit {
22 constexpr int32_t KEY_INDEX = 0;
23 constexpr int32_t VALUE_INDEX = 1;
StealRdbStore()24 std::shared_ptr<NativeRdb::RdbStore> RdbStoreContextBase::StealRdbStore()
25 {
26     auto rdb = std::move(rdbStore);
27     rdbStore = nullptr;
28     return rdb;
29 }
ParseTransactionOptions(const napi_env & env,size_t argc,napi_value * argv,std::shared_ptr<CreateTransactionContext> context)30 int ParseTransactionOptions(
31     const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr<CreateTransactionContext> context)
32 {
33     context->transactionOptions.transactionType = Transaction::DEFERRED;
34     if (argc > 0 && !JSUtils::IsNull(env, argv[0])) {
35         auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions);
36         CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("options", "a transactionOptions"));
37     }
38     return OK;
39 }
ParseTableName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)40 int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
41 {
42     context->tableName = JSUtils::Convert2String(env, arg);
43     CHECK_RETURN_SET(!context->tableName.empty(), std::make_shared<ParamError>("table", "not empty string."));
44     return OK;
45 }
46 
ParseCursor(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)47 int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
48 {
49     double cursor = 0;
50     auto status = JSUtils::Convert2Value(env, arg, cursor);
51     CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared<ParamError>("cursor", "valid cursor."));
52     context->cursor = static_cast<uint64_t>(cursor);
53     return OK;
54 }
55 
ParseCryptoParam(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)56 int ParseCryptoParam(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
57 {
58     auto status = JSUtils::Convert2Value(env, arg, context->cryptoParam);
59     CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("cryptoParam", "valid cryptoParam."));
60     return OK;
61 }
62 
ParseColumnName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)63 int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
64 {
65     context->columnName = JSUtils::Convert2String(env, arg);
66     CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared<ParamError>("columnName", "not empty string."));
67     return OK;
68 }
69 
ParsePrimaryKey(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)70 int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
71 {
72     JSUtils::Convert2Value(env, arg, context->keys);
73     CHECK_RETURN_SET(!context->keys.empty(), std::make_shared<ParamError>("PRIKey", "number or string."));
74     return OK;
75 }
76 
ParseDevice(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)77 int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
78 {
79     context->device = JSUtils::Convert2String(env, arg);
80     CHECK_RETURN_SET(!context->device.empty(), std::make_shared<ParamError>("device", "not empty"));
81     return OK;
82 }
83 
ParseSrcType(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)84 int ParseSrcType(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
85 {
86     std::string value = "";
87     int32_t status = JSUtils::Convert2Value(env, arg, value);
88     CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("srcName", "not null"));
89     context->srcName = value;
90     return OK;
91 }
92 
ParseTablesName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)93 int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
94 {
95     int32_t ret = JSUtils::Convert2Value(env, arg, context->tablesNames);
96     CHECK_RETURN_SET(ret == napi_ok, std::make_shared<ParamError>("tablesNames", "not empty string."));
97     return OK;
98 }
99 
ParseSyncModeArg(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)100 int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
101 {
102     napi_valuetype type = napi_undefined;
103     napi_typeof(env, arg, &type);
104     CHECK_RETURN_SET(type == napi_number, std::make_shared<ParamError>("mode", "a SyncMode Type."));
105     napi_status status = napi_get_value_int32(env, arg, &context->enumArg);
106     CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("mode", "a SyncMode Type."));
107     bool checked = context->enumArg == 0 || context->enumArg == 1;
108     CHECK_RETURN_SET(checked, std::make_shared<ParamError>("mode", "a SyncMode of device."));
109     return OK;
110 }
111 
ParseDistributedTypeArg(const napi_env & env,size_t argc,napi_value * argv,std::shared_ptr<RdbStoreContext> context)112 int ParseDistributedTypeArg(
113     const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr<RdbStoreContext> context)
114 {
115     context->distributedType = DistributedRdb::DISTRIBUTED_DEVICE;
116     if (argc > 1) {
117         auto status = JSUtils::Convert2ValueExt(env, argv[1], context->distributedType);
118         bool checked = status == napi_ok && context->distributedType >= DistributedRdb::DISTRIBUTED_DEVICE &&
119                        context->distributedType <= DistributedRdb::DISTRIBUTED_CLOUD;
120         CHECK_RETURN_SET(JSUtils::IsNull(env, argv[1]) || checked,
121             std::make_shared<ParamError>("distributedType", "a DistributedType"));
122     }
123     return OK;
124 }
125 
ParseDistributedConfigArg(const napi_env & env,size_t argc,napi_value * argv,std::shared_ptr<RdbStoreContext> context)126 int ParseDistributedConfigArg(
127     const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr<RdbStoreContext> context)
128 {
129     context->distributedConfig = { false };
130     // '2' Ensure that the incoming argv contains 3 parameter
131     if (argc > 2) {
132         auto status = JSUtils::Convert2Value(env, argv[2], context->distributedConfig);
133         bool checked = status == napi_ok || JSUtils::IsNull(env, argv[2]);
134         CHECK_RETURN_SET(checked, std::make_shared<ParamError>("distributedConfig", "a DistributedConfig type"));
135     }
136     return OK;
137 }
138 
ParseCloudSyncModeArg(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)139 int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
140 {
141     auto status = JSUtils::Convert2ValueExt(env, arg, context->syncMode);
142     bool checked = (status == napi_ok && context->syncMode >= DistributedRdb::TIME_FIRST &&
143                     context->syncMode <= DistributedRdb::CLOUD_FIRST);
144     CHECK_RETURN_SET(checked, std::make_shared<ParamError>("mode", "a SyncMode of cloud."));
145     return OK;
146 }
147 
ParseCallback(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)148 int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
149 {
150     napi_valuetype valueType = napi_undefined;
151     napi_status status = napi_typeof(env, arg, &valueType);
152     CHECK_RETURN_SET(
153         (status == napi_ok && valueType == napi_function), std::make_shared<ParamError>("callback", "a function."));
154     NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->callback_), ERR);
155     return OK;
156 }
157 
ParseCloudSyncCallback(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)158 int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
159 {
160     napi_valuetype valueType = napi_undefined;
161     napi_typeof(env, arg, &valueType);
162     CHECK_RETURN_SET(valueType == napi_function, std::make_shared<ParamError>("progress", "a callback type"));
163     NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR);
164     return OK;
165 }
166 
ParsePredicates(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)167 int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
168 {
169     auto status = napi_unwrap(env, arg, reinterpret_cast<void **>(&context->predicatesProxy));
170     CHECK_RETURN_SET(status == napi_ok && context->predicatesProxy != nullptr,
171         std::make_shared<ParamError>("predicates", "an RdbPredicates."));
172     context->tableName = context->predicatesProxy->GetPredicates()->GetTableName();
173     context->rdbPredicates = context->predicatesProxy->GetPredicates();
174     return OK;
175 }
176 
ParseSrcName(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)177 int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
178 {
179     context->srcName = JSUtils::Convert2String(env, arg);
180     CHECK_RETURN_SET(!context->srcName.empty(), std::make_shared<ParamError>("srcName", "not empty"));
181     return OK;
182 }
183 
ParseColumns(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)184 int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
185 {
186     napi_valuetype type = napi_undefined;
187     napi_typeof(env, arg, &type);
188     if (type == napi_undefined || type == napi_null) {
189         return OK;
190     }
191     int32_t ret = JSUtils::Convert2Value(env, arg, context->columns);
192     CHECK_RETURN_SET(ret == napi_ok, std::make_shared<ParamError>("columns", "a string array"));
193     return OK;
194 }
195 
ParseBindArgs(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)196 int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
197 {
198     context->bindArgs.clear();
199     napi_valuetype type = napi_undefined;
200     napi_typeof(env, arg, &type);
201     if (type == napi_undefined || type == napi_null) {
202         return OK;
203     }
204     bool isArray = false;
205     napi_status status = napi_is_array(env, arg, &isArray);
206     CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared<ParamError>("values", "a BindArgs array."));
207 
208     uint32_t arrLen = 0;
209     status = napi_get_array_length(env, arg, &arrLen);
210     CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("values", "not empty."));
211     for (size_t i = 0; i < arrLen; ++i) {
212         napi_value element = nullptr;
213         napi_get_element(env, arg, i, &element);
214         ValueObject valueObject;
215         int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value);
216         CHECK_RETURN_SET(ret == OK, std::make_shared<ParamError>(std::to_string(i), "ValueObject"));
217         // The blob is an empty vector.
218         // If the API version is less than 14, and insert null. Otherwise, insert an empty vector.
219         if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) {
220             std::vector<uint8_t> tmpValue;
221             valueObject.GetBlob(tmpValue);
222             if (tmpValue.empty()) {
223                 valueObject = ValueObject();
224             }
225         }
226         context->bindArgs.push_back(std::move(valueObject));
227     }
228     return OK;
229 }
230 
ParseSql(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)231 int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
232 {
233     context->sql = JSUtils::Convert2String(env, arg);
234     CHECK_RETURN_SET(!context->sql.empty(), std::make_shared<ParamError>("sql", "not empty"));
235     return OK;
236 }
237 
ParseTxId(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)238 int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
239 {
240     int64_t txId = 0;
241     auto status = JSUtils::Convert2ValueExt(env, arg, txId);
242     CHECK_RETURN_SET(status == napi_ok && txId >= 0, std::make_shared<ParamError>("txId", "not invalid txId"));
243     context->txId = txId;
244     return OK;
245 }
246 
ParseSendableValuesBucket(const napi_env env,const napi_value map,std::shared_ptr<RdbStoreContext> context)247 int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr<RdbStoreContext> context)
248 {
249     uint32_t length = 0;
250     napi_status status = napi_map_get_size(env, map, &length);
251     auto error = std::make_shared<ParamError>("ValuesBucket is invalid.");
252     CHECK_RETURN_SET(status == napi_ok && length > 0, error);
253     napi_value entries = nullptr;
254     status = napi_map_get_entries(env, map, &entries);
255     CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_map_get_entries failed."));
256     for (uint32_t i = 0; i < length; ++i) {
257         napi_value iter = nullptr;
258         status = napi_map_iterator_get_next(env, entries, &iter);
259         CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_map_iterator_get_next failed."));
260         napi_value values = nullptr;
261         status = napi_get_named_property(env, iter, "value", &values);
262         CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_named_property value failed."));
263         napi_value key = nullptr;
264         status = napi_get_element(env, values, KEY_INDEX, &key);
265         CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_element key failed."));
266         std::string keyStr = JSUtils::Convert2String(env, key);
267         napi_value value = nullptr;
268         status = napi_get_element(env, values, VALUE_INDEX, &value);
269         CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_element value failed."));
270         ValueObject valueObject;
271         int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
272         if (ret == napi_ok) {
273             context->valuesBucket.Put(keyStr, valueObject);
274         } else if (ret != napi_generic_failure) {
275             CHECK_RETURN_SET(false, std::make_shared<ParamError>("The value type of " + keyStr, "invalid."));
276         }
277     }
278     return OK;
279 }
280 
ParseValuesBucket(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)281 int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
282 {
283     bool isMap = false;
284     napi_status status = napi_is_map(env, arg, &isMap);
285     CHECK_RETURN_SET(
286         status == napi_ok, std::make_shared<InnerError>("call napi_is_map failed" + std::to_string(status)));
287     if (isMap) {
288         return ParseSendableValuesBucket(env, arg, context);
289     }
290     napi_value keys = nullptr;
291     napi_get_all_property_names(env, arg, napi_key_own_only,
292         static_cast<napi_key_filter>(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys);
293     uint32_t arrLen = 0;
294     status = napi_get_array_length(env, keys, &arrLen);
295     CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared<ParamError>("ValuesBucket is invalid"));
296 
297     for (size_t i = 0; i < arrLen; ++i) {
298         napi_value key = nullptr;
299         status = napi_get_element(env, keys, i, &key);
300         CHECK_RETURN_SET(status == napi_ok, std::make_shared<ParamError>("ValuesBucket is invalid."));
301         std::string keyStr = JSUtils::Convert2String(env, key);
302         napi_value value = nullptr;
303         napi_get_property(env, arg, key, &value);
304         ValueObject valueObject;
305         int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value);
306         // The blob is an empty vector.
307         // If the API version is less than 14, and insert null. Otherwise, insert an empty vector.
308         if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) {
309             std::vector<uint8_t> tmpValue;
310             valueObject.GetBlob(tmpValue);
311             if (tmpValue.empty()) {
312                 valueObject = ValueObject();
313             }
314         }
315         if (ret == napi_ok) {
316             context->valuesBucket.Put(keyStr, valueObject);
317         } else if (ret != napi_generic_failure) {
318             CHECK_RETURN_SET(false, std::make_shared<ParamError>("The value type of " + keyStr, "invalid."));
319         }
320     }
321     return OK;
322 }
323 
ParseValuesBuckets(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)324 int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
325 {
326     bool isArray = false;
327     napi_status status = napi_is_array(env, arg, &isArray);
328     CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared<ParamError>("ValuesBuckets is invalid."));
329 
330     uint32_t arrLen = 0;
331     status = napi_get_array_length(env, arg, &arrLen);
332     CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared<ParamError>("ValuesBuckets is invalid."));
333 
334     for (uint32_t i = 0; i < arrLen; ++i) {
335         napi_value obj = nullptr;
336         status = napi_get_element(env, arg, i, &obj);
337         CHECK_RETURN_SET(status == napi_ok, std::make_shared<InnerError>("napi_get_element failed."));
338 
339         CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK);
340         context->sharedValuesBuckets.Put(context->valuesBucket);
341         context->valuesBucket.Clear();
342     }
343     return OK;
344 }
345 
ParseConflictResolution(const napi_env env,const napi_value arg,std::shared_ptr<RdbStoreContext> context)346 int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr<RdbStoreContext> context)
347 {
348     int32_t conflictResolution = 0;
349     napi_get_value_int32(env, arg, &conflictResolution);
350     int32_t min = static_cast<int32_t>(NativeRdb::ConflictResolution::ON_CONFLICT_NONE);
351     int32_t max = static_cast<int32_t>(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE);
352     bool checked = (conflictResolution >= min) && (conflictResolution <= max);
353     CHECK_RETURN_SET(checked, std::make_shared<ParamError>("conflictResolution", "a ConflictResolution."));
354     context->conflictResolution = static_cast<NativeRdb::ConflictResolution>(conflictResolution);
355     return OK;
356 }
357 } // namespace RelationalStoreJsKit
358 } // namespace OHOS